Tutorial: build a Note Drafts napplet with an AI Agent and @napplet/skills
This tutorial builds the Note Drafts napplet with a coding agent instead of typing every file yourself. It uses @napplet/skills, the packaged authoring guidance that teaches agents the current napplet package surface, the boilerplate-first project shape, the sandbox boundary, and the verification checklist.
Use this path when you want the agent to do the implementation work, while you keep control of scope, review, and release evidence.
Protocol references the agent must defer to:
- NIP-5D, the proposed web projection: sandboxed iframe,
postMessageenvelope, and runtime-injected domains - NIP-5A, the manifest and aggregate-hash model
- NAPs, the capability-domain specs for
identity,storage, andoutbox
1. Create and initialize the project
Start from the maintained scaffold and record deployment metadata before the agent edits application code:
napplet create note-drafts
cd note-drafts
napplet init --name notedrafts --title "Note Drafts" \
--description "Draft and publish short Nostr notes from a sandboxed napplet." \
--archetype note:NAP-42. Install the napplet skills for your agent
@napplet/skills can install the guidance into several agent surfaces. Pick the target your tool reads:
napplet skills install make-napplet --to agentsCommon targets:
napplet skills install make-napplet --to claude
napplet skills install make-napplet --to cursor
napplet skills install make-napplet --to gemini
napplet skills install make-napplet --to copilotIf your agent supports local skills directly, install the full set instead:
napplet skills install --to agentsWhat this teaches: the skill file is not a protocol spec. It is a build guide that tells the agent to check NIP-5D and NAPs, preserve the napplet create scaffold and napplet init metadata, use shipped @napplet/* package exports, and stop instead of inventing missing protocol surface.
Before implementation, the agent should inspect the project state and available tools. An empty directory, a maintained boilerplate, an initialized napplet, a boilerplate-based brownfield app, and an unrelated brownfield app require different paths. It should also check whether napplet and Kehto/Paja are installed rather than assuming either binary exists.
3. Give the agent a small product prompt
Paste a prompt like this into your coding agent:
Build a Note Drafts napplet in this directory using the installed
@napplet/skills guidance.
The app should let a user write one short Nostr note, autosave the draft, and
publish it through the host shell.
The project is already scaffolded and its deployment metadata is in
.napplet/config.json. Follow the skills end to end and report the changed files
plus verification evidence.This prompt is intentionally short. The installed make-napplet guidance is responsible for routing the work through the build-napplet and test-napplet skills, preserving the napplet create scaffold, choosing the shell-mediated domains, preserving the generated scripts, and refusing direct browser or signing authority.
For this app, the skills should infer:
identityreads the shell-user pubkey and listens for changes.storageautosaves and clears the draft under shell-managed storage.outboxpublishes the note with shell signing and fanout.requirescontains only the domains the app directly calls:identity,storage, andoutbox.- If a needed API is missing from current packages or specs, the agent should stop and flag that package/spec gap instead of inventing a local protocol.
4. Review the agent's first diff
Before running the app, inspect the files the agent changed:
git status --short
git diff -- package.json vite.config.ts index.html src/main.ts src/styles.css README.mdThe diff should look like this:
package.jsonpreserves the generated scripts and uses current@napplet/sdk,@napplet/vite-plugin, and@napplet/conformance-cliversions..napplet/config.jsonstill ownsnotedrafts, title, description, and the canonicalnote:NAP-4archetype contract.vite.config.tsdeclaresrequires: ['identity', 'storage', 'outbox']and does not become a second source of deployment metadata.src/main.tsimportsidentity,storage, andoutboxfrom@napplet/sdk.- Draft persistence goes through
storage.instance. - Publishing goes through
outbox.publishwith an unsigned kind1event template. - The code checks for absent hard domains only to show user-facing errors; it does not invent a shell discovery API.
Run a quick forbidden-surface scan. You should not need to paste this list into the first prompt; it is here so you can audit the result:
rg "window\\.nostr|localStorage|sessionStorage|indexedDB|fetch\\(|WebSocket|EventSource|shell\\.ready|shell\\.supports|discoverServices" srcNo matches is the expected result. If there are matches, ask the agent to repair them before continuing.
5. Use a repair prompt when needed
If the first pass keeps starter-demo code, broad requirements, or shell bypasses, use a focused repair prompt:
The first pass drifted from the installed napplet skills.
Re-run the make-napplet/build-napplet/test-napplet guidance, repair any boundary
or verification failures, and keep the Note Drafts product scope unchanged.Keep repair prompts narrow. Do not ask the agent to redesign the whole app after you already have a working structure. If the same boundary detail must be added to every user prompt, treat that as a @napplet/skills bug and update the relevant skill instead of growing the prompt.
6. Verify the artifact, not just the source
Run the same checks you would run by hand:
pnpm install
pnpm type-check
pnpm build
pnpm test:conformanceThen inspect the built metadata:
grep -n "napplet-type\\|napplet-requires" dist/index.htmlExpected metadata:
<meta name="napplet-type" content="notedrafts">
<meta name="napplet-requires" content="identity,outbox,storage">The metadata check matters because the shell loads the built artifact. A source file can look correct while the generated dist/index.html still carries stale manifest fields.
7. Run a shell smoke test
Use the shell/runtime you target for local testing. Start the project through Paja, not as a raw Vite page:
napplet paja -- pnpm vite --host 127.0.0.1Report the URL printed by Paja. The underlying Vite URL is only an asset server and is not a valid napplet preview. If Paja is unavailable, report that manual runtime verification is pending instead of linking to Vite.
In Paja or another compatible runtime:
- Load the built or dev Note Drafts napplet through the shell, not as a raw Vite page.
- Confirm identity renders as a short pubkey or signed-out state.
- Type a draft and reload the iframe; the draft should restore through
storage. - Publish a note; the shell should own signing and relay fanout.
- Disable
storageoroutboxand reload; the UI should show a clear status message.
Do not treat a raw browser preview as proof. The app only proves the napplet boundary when a shell injects the required NAP domains.
The visual implementation should also use NAP-THEME when available. Apply theme.colors.background to html, body, and the app root, apply theme.colors.text and theme.colors.primary to the design tokens, and update the full surface from themeOnChanged. A dark component palette on a white page is not themed; test both dark and light backgrounds.
8. Ask the agent for a completion report
Use one final prompt:
Summarize the Note Drafts napplet build.
Include:
- changed files
- NAP domains used and why
- forbidden surfaces scanned
- commands that passed with exact output summaries
- any manual shell smoke evidence
- any untested gapsThe useful output is not "done"; it is evidence. Keep the report with the project or PR so future edits can tell which claims were verified.
What the skills are buying you
The skills do not make the agent authoritative. They make the default path better:
- Preserve the
napplet createscaffold andnapplet initdeployment metadata instead of recreating build plumbing. - Use current shipped
@napplet/sdkhelpers instead of imagined APIs. - Prefer
outboxfor social reads/publishes instead of direct relay ownership. - Keep browser storage, direct network, private keys, and external runtime assets out of napplet code.
- Run conformance before claiming completion.
You still review the diff, run the checks, and compare any protocol-facing claim against the living NIP-5D and NAP documents.