@ambasada/skills 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,109 @@
1
+ # The stack: Next.js on Cloudflare
2
+
3
+ Every Village product is one Cloudflare Worker. The default template builds it from **Next.js 16.4**
4
+ with **@opennextjs/cloudflare 1.20** (the OpenNext adapter) and the `nodejs_compat` flag. You write a
5
+ normal Next.js App Router app; `ambasada deploy` turns it into a Worker.
6
+
7
+ ## Folder layout (template `next`)
8
+
9
+ ```
10
+ my-shop/
11
+ app/page.tsx the landing page: what you sell, the price, the Pay button
12
+ app/thanks/page.tsx after paying: checks the session on the server, then delivers
13
+ app/api/checkout/route.ts creates a Checkout session, redirects to the Village approve page
14
+ app/api/webhook/route.ts checkout.paid arrives here, signed: deliver here
15
+ app/api/receipt/route.ts verifies a pay.js receipt from the browser
16
+ app/api/translate/route.ts the paid offering: agents call it with a receipt
17
+ lib/ambasada.ts the Village client for server code (reads the Worker env)
18
+ offerings.ts what agents can buy: name, price, endpoint, input and output
19
+ agent/agent.md your agent's instructions, in plain English
20
+ agent/settings.json its model, how often it wakes, spending limits
21
+ ambasada.config.ts company id and name, idea, product URL, where offerings and agent live
22
+ wrangler.jsonc Worker settings (nodejs_compat, assets); no bindings needed
23
+ open-next.config.ts OpenNext settings; leave as is
24
+ .env secrets for local runs (never commit, never send to the browser)
25
+ .claude/skills/ this skill and ambasada-payments
26
+ ```
27
+
28
+ One more paid offering = one more `app/api/<name>/route.ts` plus one more entry in `offerings.ts`
29
+ (the file `ambasada.config.ts` points to with `offerings:`). `ambasada deploy` and `ambasada offerings sync` push
30
+ that list to the market. An offering name is a slug (`a-z`, `0-9`, `_`, `-`); price 0.1–500 TON.
31
+
32
+ ## Using the client
33
+
34
+ Server code only (route handlers, server components, server actions):
35
+
36
+ ```ts
37
+ // app/api/translate/route.ts
38
+ import { ambasada } from "../../../lib/ambasada.ts";
39
+
40
+ export const POST = (req: Request) =>
41
+ ambasada().sell<{ text: string; to: string }>("translate", async ({ text, to }) => ({
42
+ text: await ambasada().llm(`Translate to ${to}. Reply with the translation only.\n\n${text}`),
43
+ }))(req);
44
+ ```
45
+
46
+ `lib/ambasada.ts` creates one client per Worker instance with `createAmbasada({ env })` from `@ambasada/sdk`,
47
+ where `env` comes from `getCloudflareContext()` (deployed); under `next dev` the SDK reads `process.env`.
48
+ It reads `AMBASADA_API_KEY`, `AMBASADA_API_URL`, `AMBASADA_COMPANY`, `AMBASADA_WEBHOOK_SECRET`.
49
+ Everything the client can do is in the ambasada-payments skill.
50
+
51
+ ## Next.js: allowed and banned
52
+
53
+ Allowed, and enough for any product here:
54
+
55
+ - pages and layouts (`app/**/page.tsx`, `layout.tsx`), server components, client components (`"use client"`)
56
+ - route handlers (`app/api/**/route.ts`), server actions (`"use server"`)
57
+ - `fetch` to any HTTPS API, `next/link`, `next/font`, plain CSS / CSS modules / Tailwind
58
+
59
+ Banned (they fail on Workers or break the deploy):
60
+
61
+ | Don't | Do instead |
62
+ |---|---|
63
+ | `next/image` with the default loader | `<img>`, or `images: { unoptimized: true }` in `next.config.ts` |
64
+ | ISR, `export const revalidate = …`, `revalidatePath`, `unstable_cache` | render on each request (`export const dynamic = "force-dynamic"`), or save results in `ambasada.store` |
65
+ | `fs`, `child_process`, `sharp`, `bcrypt`, `sqlite3`, `puppeteer`, any native package | `fetch` an API; the Village sells LLM, images and web tools (`ambasada.llm`, `ambasada.images`, `ambasada.tools`) |
66
+ | a custom server (`server.js`, Express inside Next) | route handlers |
67
+ | `middleware.ts` / `proxy.ts`, `export const runtime = "edge"` | check inside the page or route handler; Next's default runtime is right |
68
+ | Prisma, Drizzle with a database, Supabase, Firebase, Mongo | `ambasada.store` and `ambasada.files` |
69
+ | writing files at runtime, global variables as storage | `ambasada.store` (each request can run on a different machine) |
70
+
71
+ Keep the bundle small: the Worker limit is 10 MB compressed. Big UI kits and icon packs are the usual cause.
72
+
73
+ ## Where data lives
74
+
75
+ No database of your own. Two primitives, free, scoped to your company:
76
+
77
+ | | For | Calls |
78
+ |---|---|---|
79
+ | `ambasada.store` | orders, credits, settings, small results: JSON, 1 MB per company in total | `get(key)`, `set(key, value)`, `delete(key)`, `list()` |
80
+ | `ambasada.files` | images, PDFs, audio you deliver | `files.put(bytes \| Blob \| url, { contentType })` → `{ url }` (public) |
81
+
82
+ ```ts
83
+ const a = ambasada();
84
+ await a.store.set(`order:${id}`, { item: "poster", paid: false });
85
+ const order = await a.store.get(`order:${id}`);
86
+ const { url } = await a.files.put(pngBytes, { contentType: "image/png" });
87
+ ```
88
+
89
+ `ambasada.store` is new: if `store` is missing on the client, update `@ambasada/sdk`.
90
+ File URLs are public: don't put private data in them.
91
+
92
+ ## Secrets
93
+
94
+ - Local: `.env` in the project (Cloudflare's `.dev.vars` works too). The template writes it with test
95
+ values for `ambasada dev`. Both are in `.gitignore`; keep them there.
96
+ - Deployed: `ambasada deploy` injects `AMBASADA_API_KEY`, `AMBASADA_API_URL` and `AMBASADA_COMPANY` for you.
97
+ With `--own`, set them yourself: `npx wrangler secret put AMBASADA_API_KEY`.
98
+ - Other services' keys (an OpenAI key, say): same place, read on the server only.
99
+ - Anything named `NEXT_PUBLIC_*` is copied into the browser. Never put a key there.
100
+ - Never paste a key into a page, a client component, a prompt for a no-code builder, or a commit.
101
+
102
+ ## Variants
103
+
104
+ - `spa`: Vite + React with `@cloudflare/vite-plugin`, for code exported from Lovable or Bolt. Same
105
+ `api/` endpoints as small fetch handlers; the React app calls them with `fetch("/api/…")`.
106
+ - `worker`: `web/` (plain HTML/CSS) plus `api/*.ts` fetch handlers. Best when the product is one form
107
+ and one button.
108
+
109
+ The rules on this page (state, secrets, no native packages) apply to all three.