Skill

/create-press

One trigger, two branches. If no workspace exists, bootstrap one from zero. If a workspace already exists, add another <Press> to it.

Command Impl

# /create-press

Detects whether the user is in a fresh directory or an existing OpenPress workspace, then runs the matching branch. Branch A scaffolds a workspace + first Press via @open-press/cli init. Branch B adds a second/third/Nth <Press> to an existing <Workspace>.

/create-press

Lives at skills/openpress-init/. The slash trigger /create-press is matched by the skill's description field; an AI tool that has loaded the OpenPress skill bundle will recognise it.

0. Environment preflight

Always runs first. Verify Node ≥20 via node -v; halt and instruct on install if missing.

1. Detect the branch

Branch decision
test -f press/index.tsx && grep -q "<Workspace" press/index.tsx && echo BRANCH_B || echo BRANCH_A
Name Type Default Description
BRANCH_A bootstrap No press/index.tsx, or it doesn't wrap children in <Workspace>. The agent treats this as a fresh project and bootstraps a workspace from zero.
BRANCH_B add press/index.tsx already default-exports a <Workspace> root. The agent adds a new <Press> child to it.

If press/index.tsx exists but is in the legacy v0.x shape (no <Workspace>), the skill tells the user to run npx open-press upgrade first, then re-invoke /create-press.

Branch A — bootstrap a fresh workspace

A.1 Target check

The CLI rejects non-empty targets automatically. A lone .git/, .gitignore, .gitkeep, or .DS_Store is fine. If the target has real content, the agent asks the user to clean it first — there is no --force flag.

A.2 Intake (one batch)

Required

Name Type Default Description
document type string Proposal / whitepaper / paper / teaching note / book / slide deck / social campaign — drives downstream skill selection.
audience string Who will read it. Often informs voice / level of detail.
primary language string Document language for writing skill routing (e.g. chinese-ai-writing-polish).
title string Written into <Press title="...">.
page geometry preset | custom Show the type's default page; let the user override. See table below.

Page geometry — default by document type

Name Type Default Description
report / paper / book default a4. Override examples: us-letter (custom), a5.
slide deck default slide-16-9. Override: slide-4-3 (custom).
social post default social-square. Override: story card (1080 × 1350 custom).
hybrid (mixed-format brief) default a4 — one geometry per Press. If the user truly needs two page sizes in the same project (A4 body + 16:9 cover), use a multi-Press <Workspace> with one Press per geometry. Per-<Frame> page override is not supported in 1.0.
Custom geometry intake
When the user opts for custom:
  - width  (e.g. 1080px)
  - height (e.g. 1350px)
  - units must match (mm / cm / in / pt / pc / px)
The agent builds { id, label, width, height } and passes via <Press page>.

The skill does not ask for subtitle / organization / author / version / footer. Those are rendered text — they live in the Cover JSX, not on Press props.

A.3 Run init

Init command
npx @open-press/cli init <target> --title "<title>"

A.4 Verify

Verify
npm run build
npm run dev -- --dry-run

A.5 Handoff report

  • Target path
  • Workspace name (if set on <Workspace name="...">)
  • The Press's title and page
  • Next-owner skill (writing / design / deploy)
  • Next editable paths: press/index.tsx, press/chapters/, press/theme/, press/components/

Branch B — add a Press to an existing workspace

B.1 Read the workspace

Open press/index.tsx, parse the <Workspace> block to identify existing Press children, their slugs, pages, and source roots. If only one Press exists and has no slug prop, the workspace is in implicit single-Press mode — adding a second Press promotes it to multi-Press, and the existing Press needs a slug too.

B.2 Intake (one batch)

Required

Name Type Default Description
slug string URL segment + per-Press directory name. Slug-shaped (a-z, 0-9, hyphens). The agent asks explicitly; it never autogenerates.
title string For the new <Press title="...">.
page geometry preset | custom Same intake as Branch A — defaults by document type, custom on request.
source layout own | shared Default own — new Press gets press/<slug>/chapters/. shared means it reuses a source already registered on another Press; the agent confirms which one.

B.3 Modify press/index.tsx

Add a Press child
<Workspace name="Series A launch">
  <Press
    slug="proposal"
    title="Series A 提案書"
    page="a4"
    sources={[mdxSource({ id: "proposal", preset: "section-folders", root: "proposal/chapters" })]}
  >
    {/* ...existing tree... */}
  </Press>

  {/* ↓ NEW — added by /create-press in Branch B */}
  <Press
    slug="pitch-deck"
    title="Investor pitch"
    page="slide-16-9"
    sources={[mdxSource({ id: "pitch-deck", preset: "section-folders", root: "pitch-deck/chapters" })]}
  >
    {/* skeleton frames go here */}
  </Press>
</Workspace>

Existing children are preserved exactly — the skill never reorders or rewrites siblings while adding a new one. If the previous single-Press had no slug, the skill adds one in the same edit.

B.4 Create per-Press folder structure

New folders
mkdir -p press/<slug>/chapters/01-intro/content
mkdir -p press/<slug>/components

Theme is shared at press/theme/ unless the user explicitly asked for per-Press theme override. In that case the agent adds theme="./<slug>/theme" to the new <Press> props and creates press/<slug>/theme/.

B.5 Verify

Verify
npm run build
# build output should show one bundle per Press;
# count must match the number of <Press> children

B.6 Handoff report

  • New slug + title + page
  • Folder structure created
  • Whether the prior Press received a slug as part of this operation
  • Next editable paths under press/<slug>/
  • Next owning skill

Boundary

  • Does not write document content. The first draft is the next skill's job.
  • Does not pick a brand / theme. Theme intake is /create-theme.
  • Does not deploy.
  • Does not ask for subtitle / organization / author — those belong in Cover JSX.
  • In Branch B, never modifies existing <Press> siblings except to add a missing slug when promoting single-Press → multi-Press.

Source