Skip to main content

caffeine-app

Scaffold and build a complete Caffeine app (caffeine.ai) from scratch — the project layout, the caffeine.toml workspace + canister manifests, the mops.toml for the single Motoko `backend` canister, the React/Vite frontend, and the caffeine CLI build loop (auth login, doctor, install, check --fix, preview --build). Use whenever the user wants to create, scaffold, set up, or build a Caffeine app or a caffeine.ai project, asks about caffeine.toml or mops.toml structure, or needs the caffeine CLI workflow — even if they do not say the words 'from scratch'. Always pair it with the `writing-motoko` skill for the backend code. Do NOT use it for Motoko language syntax or compiler errors (use the `writing-motoko` skill), and do NOT use it for generic Internet Computer / dfx / icp deployment (use the `icp-cli` skill).

Jump to install

Source facts

Repository
dfinity/icskills
Last source activity
August 11, 2026 at 16:11
Detected SKILL.md language
English
Stars
34
Forks
14

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
2 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
caffeine-app
description
Scaffold and build a complete Caffeine app (caffeine.ai) from scratch — the project layout, the caffeine.toml workspace + canister manifests, the mops.toml for the single Motoko `backend` canister, the React/Vite frontend, and the caffeine CLI build loop (auth login, doctor, install, check --fix, preview --build). Use whenever the user wants to create, scaffold, set up, or build a Caffeine app or a caffeine.ai project, asks about caffeine.toml or mops.toml structure, or needs the caffeine CLI workflow — even if they do not say the words 'from scratch'. Always pair it with the `writing-motoko` skill for the backend code. Do NOT use it for Motoko language syntax or compiler errors (use the `writing-motoko` skill), and do NOT use it for generic Internet Computer / dfx / icp deployment (use the `icp-cli` skill).
license
Apache-2.0
compatibility
@caffeineai/cli (the `caffeine` command), Node.js >= 18.17, pnpm, network access + a caffeine.ai account
metadata
{"title":"Caffeine App (build from scratch)","category":"Integration"}
# Caffeine App (build from scratch) Caffeine (caffeine.ai) builds and hosts full-stack apps on the Internet Computer: a single **Motoko backend canister** plus a **React/Vite frontend** served as an assets canister. This skill teaches the exact **project shape** and the **CLI build loop** so you can produce a buildable Caffeine app from nothing. **This skill owns the project shape and the build workflow. It does NOT own the Motoko language.** Before you write or edit any backend code, fetch and follow the `writing-motoko` skill: <https://skills.internetcomputer.org/skills/writing-motoko/SKILL.md>. That skill is authoritative for actor syntax, stable state, `mo:core`, and compiler errors. This skill only shows the minimal empty actor and where it lives. ## When to use this skill - Creating/scaffolding a new Caffeine app or caffeine.ai project from scratch. - Writing or fixing `caffeine.toml` (workspace or canister manifest) or `mops.toml`. - Running the caffeine CLI loop: `auth login`, `doctor`, `install`, `check`, `preview`. Do **not** use it for Motoko language details (use `writing-motoko`) or for raw IC/`dfx`/`icp` deployment (use `icp-cli`). Caffeine apps are built and deployed through the `caffeine` CLI and the caffeine.ai web app, **not** through `dfx`. ## Critical facts - **There is no `caffeine init` / `caffeine new`.** "From scratch" means you create the files in this skill by hand, then run the build loop. (`caffeine projects clone <id>` only downloads an *existing* cloud project — it is not a greenfield scaffold.) - **Exactly one backend canister, and it must be named `backend`.** `mops.toml` declares a single `[canisters.backend]`. - **The frontend↔backend binding files are generated, never hand-written.** `src/frontend/src/backend.ts` and `src/frontend/src/declarations/` are produced by `caffeine-bindgen` during the build. Editing them is pointless — they are overwritten. - **Deploying to a live URL is done in the caffeine.ai web app, not the CLI.** The CLI takes you as far as a built **draft** (`caffeine preview --build`, which needs a cloud `project.id` — see the build loop). There is no `caffeine deploy`/`publish` command. ## Prerequisites (run once) ```bash # Install the CLI (public npm package). The binary is `caffeine`. npm install -g @caffeineai/cli # Authenticate against caffeine.ai (opens a browser; use --device on headless hosts). caffeine auth login caffeine auth status # Check the environment: Node, pnpm, mops, caffeine-bindgen, that you are logged in, # and that the Caffeine API is reachable (installs/repairs what it can). caffeine doctor --fix ``` If a global install is undesirable or fails, run every `caffeine` command through an `npx -y @caffeineai/cli@latest` prefix instead — e.g. `npx -y @caffeineai/cli@latest auth status`. `caffeine doctor --fix` checks Node.js, pnpm, mops, and caffeine-bindgen, confirms you are logged in, and verifies the Caffeine API is reachable — installing or repairing what it can. It does **not** install the Motoko compiler (`moc`) or linter (`lintoko`): mops fetches those automatically from the `[toolchain]` pins in `mops.toml` on the first `mops install` / build. `dfx` is not part of the Caffeine build. ## Project shape A Caffeine app is a pnpm workspace with a root manifest and two canisters. Create this exact tree (file contents below): ```text my-app/ ├── caffeine.toml # root workspace manifest — MUST contain [workspace] ├── mops.toml # Motoko build config — ONE per project, at the root ├── package.json # pnpm workspace root + the `bindgen` script ├── pnpm-workspace.yaml # declares src/**/* as workspace packages ├── tsconfig.json # root TS config └── src/ ├── backend/ # the single Motoko canister, named "backend" │ ├── caffeine.toml # canister manifest: type = "motoko" │ ├── main.mo # actor entry point (write with the `writing-motoko` skill) │ └── system-idl/ # Candid for IC system canisters (see note below) │ └── aaaaa-aa.did # IC management canister interface └── frontend/ # the assets canister (React + Vite) ├── caffeine.toml # canister manifest: type = "assets" ├── package.json # frontend deps + scripts (see references/frontend-template.md) ├── vite.config.js # (see references/frontend-template.md) ├── tsconfig.json # (see references/frontend-template.md) ├── biome.json # (see references/frontend-template.md) ├── tailwind.config.js # (see references/frontend-template.md) ├── postcss.config.js # (see references/frontend-template.md) ├── index.html ├── env.json # runtime config — copied into dist/ on build └── src/ ├── main.tsx # React entry (providers) ├── App.tsx ├── index.css ├── backend.ts # GENERATED by caffeine-bindgen — do NOT edit └── declarations/ # GENERATED by caffeine-bindgen — do NOT edit ``` Only the **root** manifest, the two **canister** manifests, `mops.toml`, `main.mo`, and the small root config files are shown inline below. The full frontend boilerplate (`package.json`, `vite.config.js`, the Tailwind/PostCSS/Biome configs, `index.html`, `env.json`, `main.tsx`, a starter `App.tsx`) is in [`references/frontend-template.md`](references/frontend-template.md) — read it when you create the frontend. ## Manifests ### Root `caffeine.toml` — the workspace The root manifest **must** contain a `[workspace]` section. That section is what marks it as the workspace root; without it, the CLI treats this file as an ordinary canister manifest and discovery fails. ```toml manifest_version = "0.1.0" [project] name = "My App" # id is assigned by the cloud after your first `caffeine preview`/create — omit it for # a brand-new local project; the CLI fills it in. [workspace] include = [ "src/**" ] # Build the backend before the frontend, because the frontend imports generated # bindings produced from the backend's Candid interface. [canisters.frontend] depends_on = [ "backend" ] ``` `[workspace].include` is a list of globs the CLI scans for nested canister manifests. `src/**` finds `src/backend/caffeine.toml` and `src/frontend/caffeine.toml`. ### `src/backend/caffeine.toml` — the Motoko canister ```toml manifest_version = "0.1.0" [project] name = "backend" type = "motoko" main = "main.mo" [build] commands = ["mops build", "pnpm bindgen"] out = "dist" [check] commands = ["mops check"] [check.fix] commands = ["mops check --fix"] ``` `[build].commands` run in order: `mops build` compiles `main.mo` to Wasm + Candid, then `pnpm bindgen` (defined in the root `package.json`) turns that Candid into the frontend's TypeScript client. `caffeine check --fix` runs `[check.fix].commands`. ### `src/frontend/caffeine.toml` — the assets canister ```toml manifest_version = "0.1.0" [project] name = "frontend" type = "assets" [build] commands = ["pnpm build"] out = "dist" [check] commands = ["pnpm typecheck", "pnpm check"] [check.fix] commands = ["pnpm typecheck", "pnpm fix"] ``` ### `mops.toml` — the Motoko build (one per project, at the root) There is exactly **one** `[canisters.backend]`. The structural pieces are invariant — the single `[canisters.backend]`, `[canisters.backend.check-stable]`, and the `[moc]` flags `--default-persistent-actors`, `--actor-idl=src/backend/system-idl`, and `--implicit-package=core`. The **toolchain versions, the `-E`/`-W`/`-A` diagnostic codes, and the dependency list are a current snapshot** that the Caffeine template bumps over time — see "Versions and dependencies drift" below. ```toml [package] name = "backend" version = "0.1.0" [build] outputDir = "src/backend/dist" args = ["--release"] [canisters.backend] main = "src/backend/main.mo" [canisters.backend.check-stable] path = ".old/src/backend/dist/backend.most" skipIfMissing = true [toolchain] moc = "1.8.1" lintoko = "0.10.0" [lint] extends = true [moc] args = [ "--default-persistent-actors", "--actor-idl=src/backend/system-idl", "--implicit-package=core", "-no-check-ir", "-E=M0236,M0223,M0237,M0254", "-W=M0235", "-A=M0241", "--generate-view-queries", ] [dependencies] core = "2.5.0" caffeineai-data-viewer = "0.1.0" ``` Notes: - **`check-stable`** points at `.old/src/backend/dist/backend.most`. The CLI saves the previous build's `.most` (stable-signature snapshot) under `.old/` so the next build can verify your stable state did not change incompatibly. Do not delete `.old/` between builds; do not commit it as source — it is build state. **`skipIfMissing = true` is required for a from-scratch project:** on the first run that snapshot does not exist yet, and without it `caffeine check` fails with `Deployed file not found: .old/src/backend/dist/backend.most`. - **`--actor-idl=src/backend/system-idl`** tells `moc` where to find the Candid interfaces of IC system canisters. `src/backend/system-idl/` must exist; the canonical template ships `aaaaa-aa.did` (the IC management-canister interface). A minimal backend needs only the directory. - **`core = "2.5.0"`** is the `mo:core` standard library. Use `mo:core`, never the deprecated `mo:base` — see the `writing-motoko` skill. **`caffeineai-data-viewer`** backs the built-in data-viewer mixin used by the default `main.mo` (below) and pairs with the `--generate-view-queries` flag. > **Versions and dependencies drift.** The `[toolchain]` versions, the `[moc]` > `-E`/`-W`/`-A` codes, and the frontend dependency set are template-managed and change > over time (e.g. the `@dfinity/*` → `@icp-sdk/*` migration, moc/core bumps). Treat the > exact values here as a snapshot — for current ones, `caffeine projects clone` a recent > project and copy its `mops.toml` + `src/frontend/package.json`. Stable across versions: > the file layout, the single `backend` canister, the structural `[moc]` flags, > `check-stable` with `skipIfMissing`, `mo:core`, and `useActor(createActor)`. ### `package.json` (root) — pnpm workspace + the `bindgen` script The `bindgen` script is the bridge from backend Candid to the frontend TS client. It is invoked by the backend canister's `[build]` step (`pnpm bindgen`). ```json { "name": "@caffeine/template-app", "type": "module", "engines": { "node": ">=18.17.0", "pnpm": ">=7.0.0", "npm": "please use pnpm" }, "scripts": { "build": "pnpm -r --if-present run build", "typecheck": "pnpm -r --if-present run typecheck", "check": "pnpm -r --if-present run check", "fix": "pnpm -r --if-present run fix", "bindgen": "caffeine-bindgen --did-file ./src/backend/dist/backend.did --out-dir ./src/frontend/src --actor-interface-file --force" }, "devDependencies": { "sharp": "^0.34.4" } } ``` ### `pnpm-workspace.yaml` ```yaml packages: - src/**/* onlyBuiltDependencies: - esbuild ``` ### `tsconfig.json` (root) ```json { "compilerOptions": { "strict": true, "target": "ES2020", "experimentalDecorators": true, "strictPropertyInitialization": false, "moduleResolution": "node", "allowJs": true, "outDir": "HACK_BECAUSE_OF_ALLOW_JS" } } ``` ### `src/backend/main.mo` — the starting backend The canonical template's starting `main.mo` includes the built-in **data-viewer mixin** (`include MixinViews()`), which pairs with the `caffeineai-data-viewer` dependency and the `--generate-view-queries` flag in `mops.toml`. With `--default-persistent-actors` the actor is already persistent. Add your own functions inside the actor, following the **`writing-motoko` skill**. ```motoko import MixinViews "mo:caffeineai-data-viewer/MixinViews"; actor { include MixinViews(); }; ``` (A bare `actor {}` also compiles if you drop the `caffeineai-data-viewer` dependency and the `--generate-view-queries` flag.) Do not write more Motoko than this without loading the `writing-motoko` skill — it covers persistent actors, stable types, `mo:core`, and the compiler-error pitfalls that an agent will otherwise hallucinate. ## The frontend **Fetch this skill's companion reference file** — [`references/frontend-template.md`](references/frontend-template.md), which sits next to this `SKILL.md` (i.e. `…/skills/caffeine-app/references/frontend-template.md`) — and create the frontend files from it; it holds the verified `package.json`, the Vite/Tailwind/Biome configs, `main.tsx`, and the worked `useActor(createActor)` backend call. The essentials: - The entry point `src/frontend/src/main.tsx` wraps the app in `InternetIdentityProvider` (from `@caffeineai/core-infrastructure`) and a TanStack `QueryClientProvider`. - The frontend talks to the backend through the **generated** module `src/frontend/src/backend.ts` (and `src/frontend/src/declarations/`), which exports a
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub