# 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…

- **Type:** Skill
- **Install:** `agentstack add skill-dfinity-icskills-caffeine-app`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [dfinity](https://agentstack.voostack.com/s/dfinity)
- **Installs:** 0
- **Category:** [Developer Tools](https://agentstack.voostack.com/c/developer-tools)
- **Latest version:** 0.1.0
- **License:** Apache-2.0
- **Upstream author:** [dfinity](https://github.com/dfinity)
- **Source:** https://github.com/dfinity/icskills/tree/main/skills/caffeine-app
- **Website:** https://skills.internetcomputer.org

## Install

```sh
agentstack add skill-dfinity-icskills-caffeine-app
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# 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 `motoko`
skill: . 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 `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 `
  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 `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 `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": ">=16.0.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
**`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 `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
  `createActor(...)` factory typed from your backend's Candid. You do not write these —
  they appear after the first build. Call the backend by passing that `createActor` to
  `useActor(createActor)` from `@caffeineai/core-infrastructure` (the same package provides
  the auth provider used in `main.tsx`); you do **not** hand-write the actor/config/storage
  glue. See the worked example in
  [`references/frontend-template.md`](references/frontend-template.md).
- `env.json` holds runtime config placeholders (`backend_host`, `backend_canister_id`,
  `project_id`, `ii_derivation_origin`, `storage_gateway_url`), all `"undefined"` locally;
  the frontend `build` script copies it into `dist/` (`cp env.json dist/`). Caffeine
  injects real values when it serves the app. Keep `env.json` and the `copy:env` step.

## The build loop

Run from the project root. Order matters.

```bash
# 1. Install dependencies. On a brand-new project, generate the pnpm lockfile FIRST
#    (first run only — see Common Pitfalls), then install the rest (pnpm + mops).
pnpm install
caffeine install

# 2. Write your backend in src/backend/main.mo using the `motoko` skill, and your
#    frontend in src/frontend/src/.

# 3. Build: compiles the backend, then `pnpm bindgen` regenerates the frontend client
#    (src/frontend/src/backend.ts + declarations/), then the frontend `pnpm build` runs.
#    Run this BEFORE check, so the frontend has the generated ./backend to typecheck
#    against. Artifacts land in src/backend/dist + src/frontend/dist (no cloud / no id).
caffeine build

# 4. Lint + typecheck + auto-fix (runs each canister's [check.fix] commands:
#    backend `mops check --fix`, frontend `pnpm typecheck` + `pnpm fix`).
caffeine check --fix

# 5. Upload a built draft (needs a cloud project id). For a brand-new app, create the
#    cloud project once to obtain an id, then preview:
caffeine projects create                 # reports a new project id
#    put that id in caffeine.toml [project] id = "...", OR pass --project-id:
caffeine preview --build --project-id 
```

**Generation ordering.** `src/frontend/src/backend.ts` does not exist until a build runs
`pnpm bindgen`. So if your frontend imports from `./backend`, you must run `caffeine build`
at least once before `caffeine check` can typecheck the frontend. A brand-new app whose
`App.tsx` does not yet import `./backend` typechecks fine before the first build.

**Going live.** `caffeine preview --build` (with a `project.id`) produces a *draft* and
returns its URL. Promote a draft to a live URL in the caffeine.ai web app (open it with
`caffeine chat open` or visit caffeine.ai). There is no CLI deploy command. Use
`caffeine projects show ` to see draft and live URLs.

### Alternative: let Caffeine's own AI build it

If you cannot run the CLI locally (no shell, no toolchain), drive Caffeine's hosted AI
instead: describe the app in natural language with `caffeine chat send ""` (or
the caffeine.ai web chat) and it scaffolds, builds, and deploys for you. This skill is
for the **local, hand-authored** path.

## Common

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [dfinity](https://github.com/dfinity)
- **Source:** [dfinity/icskills](https://github.com/dfinity/icskills)
- **License:** Apache-2.0
- **Homepage:** https://skills.internetcomputer.org

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-dfinity-icskills-caffeine-app
- Seller: https://agentstack.voostack.com/s/dfinity
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
