Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion evaluations/asset-canister.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@
"Set up stable memory in Motoko",
"Connect a wallet to my dapp",
"How do I create an ICRC-1 token?",
"Deploy a Rust backend canister"
"Deploy a Rust backend canister",
"How do I set up a custom domain on the IC?",
"Configure DNS for my IC canister"
]
}
}
105 changes: 105 additions & 0 deletions evaluations/custom-domains.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
{
"skill": "custom-domains",
"description": "Evaluation cases for the custom-domains skill. Tests whether agents produce correct DNS records, use the right registration API endpoints, and warn about common pitfalls like provider SSL interference and stale ACME records.",

"output_evals": [
{
"name": "DNS record configuration",
"prompt": "What DNS records do I need to set up to serve my canister ryjl3-tyaaa-aaaaa-aaaba-cai under app.example.com on the IC? Just the DNS records, no code or deploy steps.",
"expected_behaviors": [
"Shows a CNAME record for app.example.com pointing to app.example.com.icp1.io",
"Shows a TXT record for _canister-id.app.example.com with the canister ID ryjl3-tyaaa-aaaaa-aaaba-cai",
"Shows a CNAME record for _acme-challenge.app.example.com pointing to _acme-challenge.app.example.com.icp2.io",
"Does NOT hallucinate incorrect subdomains or record types"
]
},
{
"name": "Domain registration API",
"prompt": "I've set up my DNS records and deployed my canister with the ic-domains file. What curl commands do I run to register my custom domain app.example.com? Just the commands.",
"expected_behaviors": [
"Uses the validate endpoint: GET https://icp0.io/custom-domains/v1/app.example.com/validate",
"Uses the registration endpoint: POST https://icp0.io/custom-domains/v1/app.example.com",
"Uses the status check endpoint: GET https://icp0.io/custom-domains/v1/app.example.com",
"Does NOT invent non-existent API endpoints or parameters"
]
},
{
"name": "ic-domains file setup",
"prompt": "What file does my canister need to serve for custom domain verification, and what should it contain for mydomain.com? Keep it brief.",
"expected_behaviors": [
"Identifies the file as .well-known/ic-domains",
"States the canister must serve /.well-known/ic-domains",
"Lists the domain in the file (mydomain.com)",
"Does NOT assume a specific canister type or framework"
]
},
{
"name": "Cloudflare SSL pitfall",
"prompt": "I'm using Cloudflare as my DNS provider for my IC custom domain. The registration keeps failing. What's likely wrong? Keep it brief.",
"expected_behaviors": [
"Identifies Cloudflare's Universal SSL as the likely culprit",
"Advises disabling Cloudflare's SSL/TLS certificate features",
"Explains that provider SSL interferes with the IC's ACME challenge"
]
},
{
"name": "Apex domain limitation",
"prompt": "I want to use example.com (no subdomain) as my custom domain on the IC, but my DNS provider won't let me set a CNAME on the apex. What are my options? Keep it brief.",
"expected_behaviors": [
"Provides solutions for the CNAME-on-apex limitation",
"Suggests using ANAME or ALIAS record types (CNAME flattening)",
"Suggests using a subdomain like www.example.com as an alternative"
]
},
{
"name": "HttpAgent host configuration",
"prompt": "My IC frontend works fine on icp0.io but API calls fail when I access it through my custom domain. What's wrong? Just the fix.",
"expected_behaviors": [
"Identifies that HttpAgent cannot auto-detect the IC API host on custom domains",
"Shows setting host to https://icp-api.io for mainnet",
"Shows HttpAgent.create({ host }) or equivalent configuration"
]
},
{
"name": "Domain update flow",
"prompt": "I want to point my existing custom domain to a different canister. What do I need to do? Just the steps.",
"expected_behaviors": [
"Updates the _canister-id TXT record to the new canister ID",
"Uses PATCH https://icp0.io/custom-domains/v1/DOMAIN to notify the service",
"Does NOT say to delete and re-register the domain"
]
},
{
"name": "Domain removal flow",
"prompt": "How do I remove a custom domain registration from the IC? Just the steps.",
"expected_behaviors": [
"Removes the _canister-id TXT and _acme-challenge CNAME DNS records",
"Uses DELETE https://icp0.io/custom-domains/v1/DOMAIN to notify the service",
"Does NOT suggest only removing DNS records without calling the API"
]
}
],

"trigger_evals": {
"description": "Queries to test whether the skill activates correctly.",
"should_trigger": [
"How do I set up a custom domain for my IC canister?",
"My custom domain registration is failing",
"What DNS records do I need for an IC custom domain?",
"How do I update my custom domain to point to a different canister?",
"How do I remove a custom domain from the IC?",
"The ACME challenge for my IC domain keeps failing",
"How do I validate my custom domain configuration?"
],
"should_not_trigger": [
"How do I deploy a frontend on the IC?",
"Set up Internet Identity for my app",
"How do I make inter-canister calls?",
"Configure .ic-assets.json5 for SPA routing",
"How do I transfer ICP tokens?",
"Deploy a Rust backend canister",
"Configure .ic-assets.json5 for my project",
"How do I upload files to an asset canister programmatically?"
]
}
}
37 changes: 2 additions & 35 deletions skills/asset-canister/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: asset-canister
description: "Deploy frontend assets to the IC. Covers certified assets, SPA routing with .ic-assets.json5, custom domains, content encoding, and programmatic uploads. Use when hosting a frontend, deploying static files, configuring custom domains, or setting up SPA routing on IC. Do NOT use for canister-level code patterns."
description: "Deploy frontend assets to the IC. Covers certified assets, SPA routing with .ic-assets.json5, content encoding, and programmatic uploads. Use when hosting a frontend, deploying static files, or setting up SPA routing on IC. Do NOT use for canister-level code patterns or custom domain setup — use custom-domains instead."
license: Apache-2.0
compatibility: "icp-cli >= 0.1.0, Node.js >= 22"
metadata:
Expand Down Expand Up @@ -122,40 +122,7 @@ icp canister call frontend http_request '(record {

### Custom Domain Setup

To serve your asset canister from a custom domain:

1. Create a file `.well-known/ic-domains` in your `dir` directory containing your domain:
```text
yourdomain.com
www.yourdomain.com
```

2. Add DNS records:
```text
# CNAME record pointing to boundary nodes
yourdomain.com. CNAME yourdomain.com.icp1.io.

# ACME challenge record for TLS certificate provisioning
_acme-challenge.yourdomain.com. CNAME _acme-challenge.yourdomain.com.icp2.io.

# Canister ID TXT record for verification
_canister-id.yourdomain.com. TXT "<your-canister-id>"
```

3. Deploy your canister so the `.well-known/ic-domains` file is available.

4. Validate that DNS records and canister ownership are correct:
```bash
curl -sL -X GET https://icp0.io/custom-domains/v1/yourdomain.com/validate | jq
# Expected: { "status": "success", "message": "Domain is eligible for registration: DNS records are valid and canister ownership is verified", ... }
```

5. Register the domain with the boundary nodes (required — registration is NOT automatic):
```bash
curl -sL -X POST https://icp0.io/custom-domains/v1/yourdomain.com | jq
```

6. Wait for the boundary nodes to provision the TLS certificate. This typically takes a few minutes. Verify by visiting `https://yourdomain.com` once DNS has propagated.
For custom domain setup (DNS configuration, TLS certificates, domain registration via the REST API), see the `custom-domains` skill. The only asset-canister-specific detail: your `.well-known/ic-domains` file must be in your `dir` directory so it gets deployed. Add `{ "match": ".well-known", "ignore": false }` to your `.ic-assets.json5` to ensure the hidden directory is included.

### Programmatic Uploads with @icp-sdk/canisters

Expand Down
Loading
Loading