Skip to content

feat: add blazor-hello-world template (Blazor WASM .NET 10 + Motoko) - #40

Open
mitnick2012 wants to merge 5 commits into
dfinity:mainfrom
mitnick2012:main
Open

mitnick2012 wants to merge 5 commits into
dfinity:mainfrom
mitnick2012:main

Conversation

@mitnick2012

Copy link
Copy Markdown

Summary

Adds a new blazor-hello-world/ sub-template: full-stack Blazor WebAssembly (.NET 10) frontend + Motoko backend, deployed fully on-chain.

This follows up on the review suggestion that community Blazor examples don't belong in the main icp-cli repo and are better suited for icp-cli-templates as suggested by @marc0olo here.
So this PR contributes the example here instead, as a properly registered sub-template.

What's included

  • blazor-hello-world/ — 24-file template (icp.yaml, cargo-generate.toml, backend/, frontend/canister.yaml, frontend/vendor/assetstorage.wasm.gz, frontend/{{project-name}}/, scripts/fix-wsl-keyring.sh)
  • Registration: added "blazor-hello-world" to root cargo-generate.toml sub_templates
  • Docs: new row in root README.md Templates table
  • CI: new blazor-hello-world entry in tests/matrix.yaml (default permutation; asserts {{project-name}}-backend.hello("ICP") returns Hello, ICP! and curls {{project-name}}-frontend for HTTP 200)
  • Template hygiene per repo conventions:
    • No lock files committed (package-lock.json / Cargo.lock excluded via root .gitignore + template ignore)
    • Tilde (~) ranges in package.json so scaffolders get latest compatible patches/security fixes
    • frontend/vendor/ excluded from Liquid; bin/obj/node_modules in template ignore

Alignment with review feedback (from Marco)

  • Right repo: moved here to icp-cli-templates instead of an external example repo, as suggested.
  • Motoko recipe v5.0.0 / mops build: backend/mops.toml mirrors hello-world/motoko-backend/mops.toml, compilation is delegated to mops build.
  • @dfinity/agent vs js.icp.build/core: this template currently still bundles @dfinity/agent via webpack into a plain defer-loaded JS file (avoids the ES-module vs. Blazor IJSRuntime race). Happy to migrate to https://js.icp.build/core/latest/libs/agent in a follow-up if maintainers prefer, please advise whether you want that migration inside this PR or as a second step.

Verification

  • icp new --path ./icp-cli-templates --subfolder blazor-hello-world renders with exit 0, no bin//obj//node_modules/lock files, all {{project-name}} placeholders substituted
  • Fresh npm install + npm run build succeed in the scaffolded frontend (webpack bundle compiles)
  • icp deploy to local network serves the frontend over HTTP 200 (friendly domain + canister-id URL)

@mitnick2012
mitnick2012 requested a review from a team as a code owner October 4, 2026 23:21
@marc0olo

marc0olo commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

@mitnick2012 thanks for the contribution. I don't think it is likely that we merge this in to the official template repo.

if you provide the template in a dedicated git repo, you can share this with others and guide them to run icp new --git https://github.com/<org/user>/<repo>

@mitnick2012

Copy link
Copy Markdown
Author

Hi @marc0olo, as you suggested the template now lives in its own repo and is maintained by me:
https://github.com/mitnick2012

icp new icp-my-app --git https://github.com/mitnick2012/icp-cli-templates --subfolder blazor-hello-world

You mentioned the idea of listing community templates in the icp-cli-templates README or the icp-cli docs. Would you be open to a small "Community templates" section in the README, with a link to this one? It would make clear these are community-maintained and not supported by DFINITY.

If that works for you, I'm happy to open a README-only PR, or to wait if you'd rather handle this through the docs or the registry you mentioned.

Copilot AI balanced review requested due to automatic review settings November 9, 2026 23:33

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new template lacks both the shared post-generation hook and the required AGENTS.md/CLAUDE.md files, causing its test matrix entry to fail immediately after scaffolding, before build or deployment checks.

4 open issues
What changed in this PR

Adds a Blazor WebAssembly (.NET 10) and Motoko starter to the template collection, with frontend-to-canister interop and deployment configuration.

Changes:

  • Registers and documents the new blazor-hello-world sub-template.
  • Adds the Blazor UI, JavaScript agent bridge, and Motoko greeting service.
  • Adds deployment scripts, setup guidance, and CI smoke-test configuration.
File Description
tests/​matrix.yaml Adds backend-call and frontend HTTP checks.
README.md Lists the new template.
cargo-generate.toml Registers the sub-template.
blazor-hello-world/​scripts/​fix-wsl-keyring.sh Adds a headless identity helper for WSL.
blazor-hello-world/​README.md Documents setup, architecture, and deployment.
blazor-hello-world/​icp.yaml Configures canisters and the local gateway.
blazor-hello-world/​frontend/​vendor/​README.md Documents the vendored asset module.
blazor-hello-world/​frontend/​canister.yaml Configures frontend build and asset upload.
blazor-hello-world/​frontend/​{{project-name}}/​wwwroot/​index.html Loads the Blazor app and agent bundle.
blazor-hello-world/​frontend/​{{project-name}}/​wwwroot/​app.css Styles the demo interface.
blazor-hello-world/​frontend/​{{project-name}}/​webpack.config.js Bundles the TypeScript agent bridge.
blazor-hello-world/​frontend/​{{project-name}}/​tsconfig.json Configures TypeScript compilation.
blazor-hello-world/​frontend/​{{project-name}}/​src/​icpAgent.ts Implements backend discovery and canister calls.
blazor-hello-world/​frontend/​{{project-name}}/​Services/​IcpAgentService.cs Wraps JavaScript calls for C# consumers.
blazor-hello-world/​frontend/​{{project-name}}/​Program.cs Initializes Blazor and registers the service.
blazor-hello-world/​frontend/​{{project-name}}/​Pages/​Home.razor Adds greeting controls and error display.
blazor-hello-world/​frontend/​{{project-name}}/​package.json Declares agent and bundling dependencies.
blazor-hello-world/​frontend/​{{project-name}}/​Layout/​MainLayout.razor Defines the page layout.
blazor-hello-world/​frontend/​{{project-name}}/​App.razor Configures routing and navigation focus.
blazor-hello-world/​frontend/​{{project-name}}/​{{project-name}}.csproj Defines the .NET 10 WebAssembly project.
blazor-hello-world/​frontend/​{{project-name}}/​_Imports.razor Provides shared Razor imports.
blazor-hello-world/​cargo-generate.toml Configures template rendering and exclusions.
blazor-hello-world/​backend/​src/​main.mo Implements persistent greeting state and methods.
blazor-hello-world/​backend/​mops.toml Pins the Motoko compiler.
blazor-hello-world/​backend/​canister.yaml Configures the Motoko build recipe.
blazor-hello-world/​backend/​backend.did Declares the backend Candid interface.

Review effort: Balanced

# Webpack output is regenerated by `npm run build` during deploy.
"frontend/{{project-name}}/wwwroot/icpAgent.js",
"frontend/{{project-name}}/wwwroot/icpAgent.js.LICENSE.txt",
]
# yaml-language-server: $schema=https://github.com/dfinity/icp-cli/raw/refs/tags/v1.3.0/docs/schemas/canister-yaml-schema.json
name: "{{ project-name }}-backend"
recipe:
type: "@dfinity/motoko@v4.1.0"
Comment on lines +17 to +19
"frontend/{{project-name}}/bin",
"frontend/{{project-name}}/obj",
"frontend/{{project-name}}/node_modules",
mkdir -p "$(dirname "$PW_FILE")"
if [[ ! -f "$PW_FILE" ]]; then
echo "==> generating password file $PW_FILE"
openssl rand -base64 24 > "$PW_FILE"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants