Skip to content

Commit 1538e1e

Browse files
authored
fix: improve recipe templates and documentation accuracy (#18)
## Changes Templates: - motoko: fix args parameter to be optional (fixes dfinity/icp-cli#337) - motoko: add candid parameter documentation in template header - prebuilt: add shrink and compress support - rust/motoko: fix typo in comment (compressed → compress) Documentation (all recipes): - Fix YAML syntax in examples (canister: → canisters: - name:) - Fix recipe type references (@dfinity/pre-built → @dfinity/prebuilt) - Update config option descriptions to accurately reflect behavior - Add icp-cli installation guide references for prerequisites - Document candid parameter behavior for motoko/rust recipes Add .claude/CLAUDE.md with documentation verification guidelines ## Release required - motoko: patch release - prebuilt: minor release
1 parent 6188a49 commit 1538e1e

9 files changed

Lines changed: 288 additions & 174 deletions

File tree

‎.claude/CLAUDE.md‎

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
`icp-cli-recipes` contains official build recipe templates for Internet Computer (ICP) canisters. Recipes provide standardized, reusable build configurations using Handlebars templates.
8+
9+
## Repository Structure
10+
11+
```
12+
recipes/
13+
├── rust/ # Rust canister recipe
14+
│ ├── recipe.hbs # Handlebars template
15+
│ └── README.md # Documentation
16+
├── motoko/ # Motoko canister recipe
17+
├── prebuilt/ # Pre-built WASM recipe
18+
└── asset-canister/ # Asset canister recipe
19+
```
20+
21+
## Recipe Template Structure
22+
23+
Each recipe is a Handlebars template (`.hbs`) that generates YAML build/sync configuration:
24+
25+
```handlebars
26+
{{! Documentation comments for parameters }}
27+
{{! `param: type` Description }}
28+
29+
build:
30+
steps:
31+
- type: script
32+
commands:
33+
- command using {{ param }}
34+
35+
{{#if optional_param}}
36+
- type: script
37+
commands:
38+
- conditional command
39+
{{/if}}
40+
```
41+
42+
## Key Patterns
43+
44+
### Required vs Optional Parameters
45+
46+
- **Required parameters**: Used directly as `{{ param }}` - will cause strict mode error if missing
47+
- **Optional parameters**: Wrapped in conditionals `{{#if param}}{{ param }}{{/if}}`
48+
49+
### Common Configuration Options
50+
51+
Most recipes support these optional parameters:
52+
- `shrink: boolean` - Optimize WASM with ic-wasm shrink
53+
- `compress: boolean` - Gzip compress the WASM
54+
- `metadata: array` - Custom metadata key-value pairs
55+
56+
## Documentation Verification
57+
58+
**IMPORTANT**: When modifying recipes, always verify:
59+
60+
1. **Template matches README**: Every parameter in `recipe.hbs` must be documented in the README
61+
2. **Required vs Optional**: Parameters used directly (not in `{{#if}}`) are required - document accordingly
62+
3. **Config option descriptions**: Each parameter must accurately describe what it does, verified against the actual behavior in `recipe.hbs`. For example, if `shrink` runs `ic-wasm shrink`, the description should reflect what that command does ("Remove unused functions and debug info to reduce file size")
63+
4. **YAML syntax in examples**: Use `canisters: - name:` array syntax, not `canister:`
64+
5. **Recipe type format**: Use `@dfinity/<recipe-name>`, not just `<recipe-name>`
65+
6. **Prerequisites accuracy**: List actual dependencies (mops vs moc, ic-wasm requirements, etc.)
66+
7. **Build process accuracy**: Document what the recipe actually does, step by step
67+
68+
### Cross-Repository Verification
69+
70+
This repository is used by `icp-cli`. When making changes:
71+
72+
1. Check `icp-cli/docs/guides/using-recipes.md` for recipe usage examples
73+
2. Check `icp-cli/examples/` for example projects using recipes
74+
3. Ensure documentation in both repos stays in sync
75+
76+
## Testing Changes
77+
78+
Since recipes are Handlebars templates, test by:
79+
80+
1. Creating a test project with `icp.yaml` using the recipe
81+
2. Running `icp project show` to see the expanded configuration
82+
3. Running `icp build` to verify the build works

‎README.md‎

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ Official build recipe templates for Internet Computer (ICP) canisters. Recipes p
2020
Reference a recipe in your `icp.yaml` file:
2121

2222
```yaml
23-
canister:
24-
name: backend
25-
recipe:
26-
type: "@dfinity/rust"
27-
configuration:
28-
package: my-canister
29-
shrink: true
23+
canisters:
24+
- name: backend
25+
recipe:
26+
type: "@dfinity/rust"
27+
configuration:
28+
package: my-canister
29+
shrink: true
3030
```
3131
3232
### Recipe Naming Convention
@@ -42,12 +42,12 @@ Recipes follow the `@dfinity/<recipe-name>` naming pattern:
4242
To pin to a specific recipe version, append `@<version>` to the recipe type:
4343

4444
```yaml
45-
canister:
46-
name: backend
47-
recipe:
48-
type: "@dfinity/rust@v3.0.0"
49-
configuration:
50-
package: my-canister
45+
canisters:
46+
- name: backend
47+
recipe:
48+
type: "@dfinity/rust@v3.0.0"
49+
configuration:
50+
package: my-canister
5151
```
5252

5353
Without a version specified, the latest stable version is used. View available versions in the [releases page](https://github.com/dfinity/icp-cli-recipes/releases).

‎recipes/asset-canister/README.md‎

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,61 +7,63 @@ Download and configure the official IC assets canister with asset synchronizatio
77
Example of how to reference this recipe in an `icp.yaml` file:
88

99
```yaml
10-
canister:
11-
name: frontend
12-
recipe:
13-
type: "@dfinity/asset-canister"
14-
configuration:
15-
version: 0.30.2
16-
dir: dist
10+
canisters:
11+
- name: frontend
12+
recipe:
13+
type: "@dfinity/asset-canister"
14+
configuration:
15+
version: 0.30.2
16+
dir: dist
1717
```
1818
1919
## Configuration Parameters
2020
2121
| Parameter | Type | Required | Description | Default |
2222
|-----------|------|----------|-------------|---------|
23-
| version | string | No | SDK version tag to download assets canister from | latest |
24-
| dir | string | Yes | Directory containing frontend assets to synchronize | - |
25-
| build | array | No | Commands to build the frontend assets | [] |
26-
| metadata | array | No | Array of key-value pairs for custom metadata | [] |
23+
| version | string | No | SDK version tag to download the assets canister from (e.g., `0.30.2`) | latest |
24+
| dir | string | Yes | Directory containing frontend assets to synchronize to the canister | - |
25+
| build | array | No | Shell commands to build the frontend assets before deployment (e.g., `npm run build`) | [] |
26+
| metadata | array | No | Array of key-value pairs for custom metadata to inject into the WASM | [] |
2727

2828
## Prerequisites
2929

30-
- `ic-wasm` tool must be installed for metadata injection and optimization
31-
- Frontend assets must either exist in the specified directory or be built using provided commands
30+
- Frontend assets must either exist in the specified directory or be built using provided `build` commands
3231
- Internet connection required to download the assets canister WASM
32+
- `ic-wasm` (included with icp-cli installation) - only required if using `metadata` option
33+
34+
> **Note:** If you followed the [icp-cli installation guide](https://github.com/dfinity/icp-cli#installation), `ic-wasm` is already installed.
3335

3436
## Examples
3537

3638
### Basic Example
3739

3840
```yaml
39-
canister:
40-
name: website
41-
recipe:
42-
type: "@dfinity/asset-canister"
43-
configuration:
44-
dir: build
41+
canisters:
42+
- name: website
43+
recipe:
44+
type: "@dfinity/asset-canister"
45+
configuration:
46+
dir: build
4547
```
4648

4749
### Advanced Example
4850

4951
```yaml
50-
canister:
51-
name: spa-frontend
52-
recipe:
53-
type: "@dfinity/asset-canister"
54-
configuration:
55-
version: 0.30.2
56-
build:
57-
- npm install
58-
- npm run build
59-
dir: dist
60-
metadata:
61-
- name: "frontend:framework"
62-
value: "react"
63-
- name: "frontend:version"
64-
value: "1.0.0"
52+
canisters:
53+
- name: spa-frontend
54+
recipe:
55+
type: "@dfinity/asset-canister"
56+
configuration:
57+
version: 0.30.2
58+
build:
59+
- npm install
60+
- npm run build
61+
dir: dist
62+
metadata:
63+
- name: "frontend:framework"
64+
value: "react"
65+
- name: "frontend:version"
66+
value: "1.0.0"
6567
```
6668

6769
## Build Process

‎recipes/motoko/README.md‎

Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -7,78 +7,81 @@ Compile Motoko source code using the moc compiler to create IC canisters.
77
Example of how to reference this recipe in an `icp.yaml` file:
88

99
```yaml
10-
canister:
11-
name: backend
12-
recipe:
13-
type: "@dfinity/motoko"
14-
configuration:
15-
entry: src/main.mo
16-
shrink: true
10+
canisters:
11+
- name: backend
12+
recipe:
13+
type: "@dfinity/motoko"
14+
configuration:
15+
main: src/main.mo
16+
shrink: true
1717
```
1818
1919
## Configuration Parameters
2020
21-
| Parameter | Type | Required | Description | Default |
22-
|-----------|---------|----------|----------------------------------------------|---------------------------|
23-
| entry | string | Yes | Path to the main Motoko source file | (autogenerated interface) |
24-
| candid | string | No | Path to the Candid interface file | |
25-
| metadata | array | No | Array of key-value pairs for custom metadata | [] |
26-
| shrink | boolean | No | Enable WASM optimization to reduce file size | false |
27-
| compress | boolean | No | Enable gzip compression of WASM file | false |
21+
| Parameter | Type | Required | Description | Default |
22+
|-----------|---------|----------|----------------------------------------------|---------|
23+
| main | string | Yes | Path to the main Motoko source file | |
24+
| args | string | No | Additional arguments to pass to moc compiler (e.g., `--incremental-gc`) | |
25+
| candid | string | No | Path to a custom Candid interface file. If not provided, the interface is auto-generated by the Motoko compiler | (auto-generated) |
26+
| metadata | array | No | Array of key-value pairs for custom metadata | [] |
27+
| shrink | boolean | No | Remove unused functions and debug info to reduce file size | false |
28+
| compress | boolean | No | Gzip compress the WASM file | false |
2829

2930
## Prerequisites
3031

31-
- `moc` (Motoko compiler) must be installed
32-
- `ic-wasm` tool must be installed for metadata injection and optimization
33-
- Motoko source files must be available in your project
32+
- `mops` (Motoko package manager) - this recipe uses `mops toolchain` to manage the Motoko compiler
33+
- `ic-wasm` (included with icp-cli installation)
3434

35-
### Installation
35+
> **Note:** If you followed the [icp-cli installation guide](https://github.com/dfinity/icp-cli#installation), both `mops` and `ic-wasm` are already installed.
3636

37-
To install the Motoko compiler, see: <https://internetcomputer.org/docs/building-apps/getting-started/install>
37+
### Additional Installation
38+
39+
If mops is not installed, see: <https://mops.one/docs/install>
3840

3941
## Examples
4042

4143
### Basic Example
4244

4345
```yaml
44-
canister:
45-
name: hello-world
46-
recipe:
47-
type: "@dfinity/motoko"
48-
configuration:
49-
entry: src/main.mo
46+
canisters:
47+
- name: hello-world
48+
recipe:
49+
type: "@dfinity/motoko"
50+
configuration:
51+
main: src/main.mo
5052
```
5153

5254
### Advanced Example
5355

5456
```yaml
55-
canister:
56-
name: complex-backend
57-
recipe:
58-
type: "@dfinity/motoko"
59-
configuration:
60-
entry: src/backend.mo
61-
shrink: true
62-
compress: true
63-
metadata:
64-
- name: "canister:type"
65-
value: "backend"
66-
- name: "language:version"
67-
value: "0.10.0"
57+
canisters:
58+
- name: complex-backend
59+
recipe:
60+
type: "@dfinity/motoko"
61+
configuration:
62+
main: src/backend.mo
63+
args: --incremental-gc
64+
shrink: true
65+
compress: true
66+
metadata:
67+
- name: "canister:type"
68+
value: "backend"
69+
- name: "language:version"
70+
value: "0.10.0"
6871
```
6972

7073
## Build Process
7174

7275
When this recipe is executed:
7376

74-
1. Checks if the Motoko compiler (`moc`) is installed
75-
2. Compiles the specified Motoko entry file using `moc`
76-
3. Moves the resulting WASM file to the output location
77+
1. Checks if `mops` is installed (used for Motoko toolchain management)
78+
2. Compiles the specified Motoko entry file using `moc` via `mops toolchain`
79+
3. Handles Candid interface: auto-generates from Motoko source, or uses the provided `candid` file
7780
4. Injects compiler version metadata ("moc:version")
7881
5. Injects template type metadata ("template:type" = "motoko")
7982
6. Injects any custom metadata specified in the configuration
80-
7. Optionally optimizes the WASM file if `shrink` is enabled
81-
8. Optionally compresses the WASM file if `compress` is enabled
83+
7. Optionally removes unused functions if `shrink` is enabled
84+
8. Optionally gzip compresses the WASM file if `compress` is enabled
8285

8386
## Project Structure
8487

‎recipes/motoko/recipe.hbs‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
{{! A recipe for building a Motoko canister }}
22
{{! `main: string` Motoko file which contains the main actor }}
33
{{! `args: string` Additional arguments to pass to the moc compiler }}
4+
{{! `candid: string` Optional, the path to the Candid interface file }}
45
{{! `shrink: boolean` Optimizes the wasm with ic-wasm }}
5-
{{! `compressed: boolean` determins whether the was should be gzipped }}
6+
{{! `compress: boolean` determines whether the wasm should be gzipped }}
67
{{! `metadata: [name: string, value: string]`: An array of name/value pairs that get injected into the wasm metadata section }}
78

89
build:
910
steps:
1011
- type: script
1112
commands:
1213
- sh -c 'command -v mops >/dev/null 2>&1 || { echo >&2 "'mops' not found on path. To install Mops, see https://mops.one/docs/install.\n"; exit 1; }'
13-
- sh -c '$(mops toolchain bin moc) "{{ main }}" {{ args }} {{#if candid}}--omit-metadata{{else}}--public-metadata{{/if}} candid:service $(mops sources) -o "$ICP_WASM_OUTPUT_PATH"'
14+
- sh -c '$(mops toolchain bin moc) "{{ main }}" {{#if args}}{{ args }} {{/if}}{{#if candid}}--omit-metadata{{else}}--public-metadata{{/if}} candid:service $(mops sources) -o "$ICP_WASM_OUTPUT_PATH"'
1415

1516
- type: script
1617
commands:

0 commit comments

Comments
 (0)