All recipes

WordPress + Zero

A magazine whose articles come from a public WordPress REST API at build time and render to static pages, with a Zero server behind them for realtime emoji reactions and server-side search over a build-time index.

View the source

Questions your agent will ask

Your agent will ask for a few details to adapt this recipe to you and what you’re making.

  • Which WordPress site should the articles come from (any public site URL or /wp-json REST root, e.g. https://wordpress.org/news)?
  • What should the publication be called?
  • What's the accent color (a hex like #d9410b)?

The whole prompt

Paste this into Claude, ChatGPT, Codex, Cursor, or another coding agent. It will build the project and publish it as a Space.

wp-zero.prompt.md
Use the connected tools for the task below. If they're missing, fetch https://incspark.com/setup.md and offer the official plugin or MCP server for my client. Show the install card when available. Skip the offer if I ask to work anonymously or without installing anything, and continue with the task where possible.

Build me a **magazine whose articles come from WordPress but whose interactivity comes
from a server** — headless WordPress rendered to static pages at build time, plus a
Zero capsule behind them for realtime reactions and search. One project, one
`inc.jsonc`, one publish.

**Before you build, ask me these questions in one message and wait for my answers. If I
skip anything, choose a sensible default and tell me what you chose:**

1. Which WordPress site should the articles come from? Any public site URL or `/wp-json`
   REST root works — default to `https://wordpress.org/news`.
2. What should the publication be called?
3. What's the accent color (a hex like `#d9410b`)?

**Build time — pull WordPress, render flat HTML:**

- Read posts with the `@incspark/wordpress` client
  (`createWordPressClient({ url })`, then `posts.list({ perPage, orderBy: "date", _embed: true })`).
  `_embed` returns the author, featured image, and terms in the same request, so there is
  no N+1. Fall back to plain `fetch` against `/wp-json/wp/v2` if the package is
  unavailable.
- Normalize the messy CMS shapes once: rendered titles carry HTML entities, excerpts carry
  markup, a post may have no featured image, and terms arrive as a nested array of
  taxonomies.
- Render a magazine index (lead story plus a card grid) and one static page per post.
  Article bodies are the post's own WordPress HTML, so handle what a real editor ships:
  lazy-loaded images with captions, responsive iframe embeds, blockquotes, tables that can
  scroll on a phone, and `<pre><code>` blocks that do not blow out the column.
- Emit a search index (JSON) of every post's slug, title, excerpt, and plain-text body, and
  compile it into the capsule so the server can search it.

**Runtime — one Zero capsule:**

- Declare `"runtime": { "kind": "zero", "server": "server/index.ts", "client": "client/index.tsx" }`
  in `inc.jsonc`.
- A `reactions` table keyed by post slug, emoji, and `ctx.auth.userId`. The built-in guest
  session is the identity — nobody signs in to press an emoji.
- A `reactions` query returning per-emoji counts and which one the current visitor picked,
  and a `toggleReaction` mutation that adds, switches, or removes. The Zero client
  subscribes, so a reaction in one browser moves the count in another through Cast.
- `GET /api/search?q=` searching the build-time index server-side and returning JSON.
- `GET /api/reactions?slug=` and `POST /api/react` so the same behavior is reachable with
  `curl`, not only from the page.

**Wiring the two halves together:**

- The generated app shell owns `/index.html`, so serve the magazine index from
  `home.html` and set `"index": "home.html"` in `inc.jsonc`. Turn on `cleanUrls` so
  articles live at `/posts/<slug>`.
- Each static page mounts the reaction island into a `<div id="root" data-slug="…">`
  placed exactly where the reaction bar belongs, loads `/client.js`, and carries the
  platform import map that `inc build` writes into the generated shell — read it out of
  `.incspark/zero/public/index.html` and inline it. That means the build runs `inc build`
  once to materialize the shell, renders the pages, and lets the real `inc build` publish
  them.
- The search box is plain `fetch` against `/api/search` — no framework needed for an HTTP
  endpoint.

**Design & content notes:**

- Magazine, not blog template: a real masthead, a strong editorial serif for headlines, a
  narrow measure for body copy, generous white space, one accent color used sparingly.
- Responsive and accessible: semantic landmarks, a labeled search input, visible focus
  rings, `aria-pressed` on the reaction buttons, live-region announcements for counts, and
  contrast that survives the accent color.
- The images and words are real — they come from WordPress. Never invent post content.
- Say plainly, in the footer, which half of each page is static and which half is the
  runtime.

**Add this exact line right before `</body>` on every page so the site carries its badge:**

```html
<script src="https://incspark.com/badge.js" data-example="wp-zero"></script>
```

**Run it, then publish:**

```sh
cd site
bun install
bun run build            # fetches WordPress, generates the index, renders the pages
sf dev                   # previews the Zero server and client
sf publish --skip-build  # the capsule and the static tree, in one version
```

`--skip-build` matters: a Zero project with a `build` script sends `inc publish`
down the static-site path, where it reruns the build and then fails looking for a
`dist/` a capsule never produces. Everything is already built by this point.

Check `GET /api/search?q=<something>` returns results, post a reaction and read the count
back, then open two browsers on the same article and confirm one reaction moves both
counts.

Launch a firm overseas.

Set it up yourself

Login

Enter your email. New here? We’ll create your account automatically.

By continuing you agree to our Terms and confirm you have read our Privacy Policy.