StoryLark
← All guides

Getting Started

Get the StoryLark engine running locally under the neutral StoryLark base brand, then build a production bundle. This is the fastest path to seeing the app boot; standing up your own branded site is covered in deploy-your-own.md.

Prerequisites

Clone and install

git clone <your-fork-or-clone-url> storylark
cd storylark
npm install

This is an npm workspaces repo. A single npm install at the root installs the app site and the packages/* (storylark-core, storylark-worker, storylark-pipeline) workspaces together, linking the site against the local packages.

The commands (from the root package.json)

Command What it runs Notes
npm run dev npm run build -w app -- --mode storylark && wrangler dev --env storylark Builds the PWA for the storylark brand, then serves it (static assets + /api/*) through the Worker on a local port.
npm run build npm run build -w app -- --mode storylark Production build of the app into app/dist.
npm run deploy npm run build && wrangler deploy --env storylark Build, then deploy the Worker + assets to Cloudflare. See deploy-your-own.md.
npm run publish node packages/pipeline/publish.mjs --brand storylark Publish content to R2. This script needs extra flags — see the note below and content-pipeline.md.
npm run typecheck tsc over the site, core, and worker tsconfigs Type-checks the site, the engine, and the Worker.

Note on npm run publish: the root script passes only --brand storylark, but packages/pipeline/publish.mjs requires --source <path> and --parser <module> as well and will exit with a usage message otherwise. Treat the npm script as a shorthand and pass the remaining flags after --, e.g. npm run publish -- --source examples/demo --parser examples/demo/parser.mjs --no-audio --local app/dist. Full details in content-pipeline.md.

After npm run dev, open the URL Wrangler prints. The app boots as a branded but empty shelf — there is no bundled content. To see stories, publish some (the bundled examples/demo public-domain stories are the quickest way; see content-pipeline.md).

How the brand "mode" works

The Vite build mode is the brand id. The defineStorylarkConfig preset (from storylark-core/vite, used by app/vite.config.ts) reads --mode <brandId>, loads brands/<brandId>/brand.json + brands/<brandId>/theme.css, and bakes them into the bundle:

The built-in Vite modes (development, production, test) fall back to the storylark brand. Any other --mode value is treated as a brand id, so --mode acme builds brands/acme/. The root scripts all pin --mode storylark.

Project layout

brands/             per-brand config: brand.json, theme.css, assets/icons/ (and optional assets/covers/)
app/                the base SITE — a thin consumer of storylark-core (index.html, entry.ts, vite.config.ts)
packages/core/      storylark-core — the PWA engine (library / reader / player / settings + service worker)
                    plus the defineStorylarkConfig Vite preset that builds a site from a brand folder
packages/worker/    storylark-worker — Cloudflare Worker: Hono API (/api/*) over D1; SQL migrations
packages/pipeline/  storylark-pipeline — publish pipeline (markdown -> chapter JSON + TTS audio + word timings -> R2) + generators
docs/               these docs
examples/           demo content + a sample parser (public-domain stories) for trying the pipeline

Inside packages/core/src/:

Next steps


Found a gap? StoryLark is open source — improve these docs on GitHub.