Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0a530a9
Merge pull request #2 from homingos/dev
bucharitesh Jun 25, 2026
5c6544e
feat: enhance OpenAPI specification with additional environments and …
bucharitesh Jun 26, 2026
0a69e98
refactor: remove deprecated API URLs from OpenAPI specification
bucharitesh Jun 26, 2026
be2d023
feat: update API documentation to reflect input structure changes
prnvyellayi Jun 29, 2026
beb7813
~
prnvyellayi Jun 30, 2026
22c3bb4
feat: restructure documentation and enhance navigation
bucharitesh Jul 6, 2026
9a61b38
feat: enhance recording documentation and add new scripts
bucharitesh Jul 6, 2026
df57fd1
feat: update image tools documentation and add new scripts
bucharitesh Jul 6, 2026
f74616c
fix: update contact email for enterprise plan inquiries in billing do…
bucharitesh Jul 6, 2026
b48b6da
chore: more videos
crazyparadox Jul 8, 2026
333bdad
chore: one more video
crazyparadox Jul 8, 2026
ffe3b96
chore: remove Motion Path documentation and references
bucharitesh Jul 8, 2026
ab095c9
docs(api): generations, assets, account & workspace endpoints + MCP/C…
crazyparadox Jul 8, 2026
43079c3
docs(api): projects, nodes, brand kits, renders + audio/3d generation
crazyparadox Jul 8, 2026
fb006d7
docs(api): get-render endpoint; 20 MCP tools (poll_brandkit_extract, …
crazyparadox Jul 8, 2026
67b870a
feat: add new configuration and authentication files, and record raw …
bucharitesh Jul 8, 2026
5de4ad0
docs(api): group endpoints by resource in the API Reference nav
crazyparadox Jul 13, 2026
d8577e7
docs(api): add Update a brand kit (PATCH /v1/brandkits/{id}) page
crazyparadox Jul 13, 2026
fa22ce7
Merge branch 'main' into feat/docs-rewrite-videos
pabssen1 Jul 13, 2026
7ff1b40
Merge pull request #3 from homingos/feat/docs-rewrite-videos
pabssen1 Jul 13, 2026
ffdd04e
docs: rename the Apps API surface to Flows (create/list/get/run + per…
crazyparadox Jul 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
79 changes: 79 additions & 0 deletions .claude/skills/video-docs/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
name: video-docs
description: Build or extend this Mintlify docs site the Dub way — deeply nested navigation with a short screen-recorded demo video on every feature page. Use when asked to write/rewrite docs pages, add a new docs section, restructure the nav, add feature videos, or record product demo clips for the docs. Covers the docs.json nav shape, page/frontmatter conventions, the DemoVideo/VideoPlayer components, and the Playwright recording harness in scripts/record/.
---

# Building video docs

This repo is a **Mintlify** site (config `docs.json`, `aspen` theme). Its house
style, copied from [dubinc/docs](https://github.com/dubinc/docs): a deeply
nested nav and a **short demo video on every feature page** — a silent
autoplaying loop for most pages, a click-to-play walkthrough for the few long
flows. Videos are produced by an automated Playwright harness in
`scripts/record/`, not recorded by hand.

Follow this skill whenever you add or rewrite docs. Match what already exists —
read a neighbouring page before writing a new one.

## The four moving parts

1. **`docs.json`** — the nav tree (`tabs → groups → pages`, nesting allowed) plus
`redirects[]`. Adding a page means adding both the `.mdx` file and its path
string to the nav.
2. **Page `.mdx` files** — lede → hero video → sections. Conventions in
`references/conventions.md`.
3. **Video components** — `snippets/components/demo-video.jsx` (silent loop) and
`snippets/components/video-player.jsx` (click-to-play). Already built; import
and use them, don't reinvent.
4. **Recording harness** — `scripts/record/`, one clip script per video. See
`references/recording.md` and `scripts/record/RECORDING.md`.

## Workflow

**Adding one page**
1. Add the page path to the right group in `docs.json`.
2. Write the `.mdx` per `references/conventions.md`, embedding its final video
path (`/videos/<area>/<slug>.mp4` + poster `/images/posters/<area>/<slug>.jpg`)
even before the file exists.
3. Write a clip script `scripts/record/clips/<area>/<slug>.ts`, record it, and
verify the footage (see recording reference — always extract frames and LOOK).
4. `pnpm check` and `pnpm broken-links`.

**A larger rewrite / new section** — work in phases so nothing half-lands:
1. **Scaffold** — edit `docs.json` nav + `redirects[]`; create stub `.mdx` for
every new page (`title`/`description` frontmatter + one line) so
`pnpm check` passes; delete/redirect anything you're replacing.
2. **Write** — fill every page with real content, embedding final video paths.
Ground every UI claim, label, limit, and price in the app source — never
invent them. For breadth, fan out one writer agent per section.
3. **Record** — build the demo account once (`references/recording.md`), then
record clips in tiers: pure-UI first, one-generation next, hard/expensive last.
4. **Validate** — media audit (every referenced `/videos/*` + poster exists on
disk), `pnpm check`, `pnpm broken-links`, manual `pnpm dev` pass.

## Non-negotiables

- **Never break a URL.** Moved pages get a `redirects[]` entry. The app deep-links
into these paths (see `../../src/lib/docs.ts` equivalents / this repo's
`AGENTS.md`): `api/authentication`, `api/permissions`, `api/running-apps`,
`collaboration/{roles,workspaces,sharing}`, `billing/credits` — keep them live.
- **Every feature page ships a video + poster.** No GIFs, no `<iframe>`, no bare
`<img>` for motion.
- **Accuracy over completeness.** If the source doesn't confirm a detail, leave it
out. Don't document flagged/experimental features.
- **Captions must match the footage.** If a clip ends up showing something other
than planned, fix the one caption line, don't ship a lie.

## Gotchas (learned the hard way)

- Mintlify snippet `.jsx` files **cannot `import` from `react`** — hooks
(`useState`) are already in scope. Local imports only.
- `<2` (or any `<digit`) in Markdown is parsed as a JSX tag and breaks the build.
Write "under 2 MB".
- `docs.json` `redirects` are `{ "source", "destination" }`, root-relative, no
`.mdx`.
- `pnpm broken-links` does **not** check media paths — audit `/videos` + posters
separately with a grep-vs-`ls` diff.

`references/conventions.md` — page anatomy, frontmatter, components, video rules.
`references/recording.md` — the harness: auth, seeding, writing/verifying clips.
87 changes: 87 additions & 0 deletions .claude/skills/video-docs/references/conventions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Page & authoring conventions

Read a neighbouring page in the same section before writing — match its shape.

## Frontmatter

```yaml
---
title: "Image Node" # Title Case, ≤ 45 chars
description: "One benefit-led sentence." # shown in nav + search + og
sidebarTitle: "Image" # only when title is long
"og:image": "/images/hero.png" # hub/overview pages only (quotes required — the colon)
---
```

## Page anatomy (feature pages)

1. **Lede** — 1–2 sentences. No `#` heading; the title renders from frontmatter.
2. **Hero video** — immediately after the lede (Dub help-article shape: media
before prose).
3. **`##` sections** — focused. 300–800 words typical; longer only when the
feature genuinely warrants it.

Hub/overview pages are the exception: short intro → `<CardGroup>` of links, no
wall of text.

## Video embeds

Silent loop — the default, most pages:

```mdx
import { DemoVideo } from "/snippets/components/demo-video.jsx";

<DemoVideo
src="/videos/<area>/<slug>.mp4"
poster="/images/posters/<area>/<slug>.jpg"
caption="Present-tense description of what the clip shows"
/>
```

Click-to-play walkthrough — only for the few long (30–90s) flows:

```mdx
import { VideoPlayer } from "/snippets/components/video-player.jsx";

<VideoPlayer
src="/videos/<area>/<slug>.mp4"
poster="/images/posters/<area>/<slug>.jpg"
title="Watch: <what the walkthrough covers>"
/>
```

- Import line(s) go directly under the frontmatter, one blank line before the lede.
- Loops are recorded 1280×800 (`DemoVideo` aspect 16/10 — don't override).
- Walkthroughs are 1920×1080 (`VideoPlayer` aspect 16/9 — don't override).
- One hero per page. Secondary clips only for a genuinely different flow
(e.g. a second engine inside a `<Tab>`).
- Naming: video `/videos/<area>/<slug>[-variant].mp4`, poster mirrored at
`/images/posters/<area>/<slug>[-variant].jpg`, kebab-case. The path in the MDX
is the contract the recording harness fulfils — pick it before recording.

## Mintlify components — when to use which

| Component | Use for |
| --- | --- |
| `<Steps>` / `<Step>` | ≥3 sequential actions |
| `<Tabs>` / `<Tab>` | mutually exclusive variants (e.g. two engines, settings sections) |
| `<CardGroup>` / `<Card>` | hub/overview pages only — never mid-article |
| `<AccordionGroup>` / `<Accordion>` | FAQs only |
| `<Note>` / `<Tip>` / `<Warning>` | max 2 per page |
| `<Frame>` | still images (reuse existing `/images/*.png` where accurate) |
| tables + `<kbd>` | keyboard shortcuts |

## Voice

Second person, present tense, plain. No "simply / just / easily". No marketing
fluff. Remove every `{/* TODO */}` comment — nothing TODO-shaped ships.

## Links

Root-relative (`/canvas/nodes/image`). Never link a redirected legacy path.

## Accuracy

Every UI label, limit, price, model name, and shortcut must trace to the app
source (or the page being replaced). When the source doesn't confirm it, write
around it. Do not document flagged/experimental features.
117 changes: 117 additions & 0 deletions .claude/skills/video-docs/references/recording.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# The recording harness

Lives in `scripts/record/` — a self-contained nested package (own
`package.json`, gitignored `node_modules`), so it never disturbs Mintlify. It
drives a **local build of the app** with Playwright, injects a fake cursor,
records each flow, and transcodes to a docs-ready mp4 + poster. `RECORDING.md`
in that directory is the operator's cheat-sheet; this file is the "how it works
+ how to extend it" reference.

## One-time setup

1. **Run the app locally.** Prefer a production build (no dev overlay, no compile
stalls): in the app repo, `pnpm build && pnpm start` → serves `:3000`. The app
points at the hosted **dev** backend, so no local backend is needed.
2. **Install the harness.** In `scripts/record/`: `pnpm install` then
`npx playwright install chromium`. (esbuild's build script must be approved —
`pnpm-workspace.yaml` lists it under `onlyBuiltDependencies`.)
3. **Auth.** `run.ts` mints a stateless magic-link token (HMAC-SHA256 over the
app's `AUTH_SECRET`, read from the app repo's `.env.local`) and signs in —
fully scripted, no manual step. `lib/auth.ts` mirrors the app's
`src/lib/auth/magic-link.ts`; if that file changes, mirror it again.
4. **Onboard once.** `tsx setup/onboard.ts` completes the `/welcome` gate so
recorded sessions land straight on the dashboard.
5. **Seed once.** `tsx setup/seed.ts N` remixes N community templates into the
demo workspace so canvas clips open on rich, good-looking projects — never an
empty canvas. Project ids land in `clips/config.json`.

## Running

```bash
# from scripts/record/ — call tsx directly (pnpm 11's deps check breaks `pnpm record`)
./node_modules/.bin/tsx run.ts --list # list clips
./node_modules/.bin/tsx run.ts <substr> [...] # re-auth + record matching clips
./node_modules/.bin/tsx run.ts --no-auth <substr> # reuse saved session (fast iterate)
SCRATCH=<dir> ./node_modules/.bin/tsx probe-page.ts /url out # screenshot + aria snapshot
```

`probe-page.ts` is how you discover real role/name selectors before writing a
clip — always probe, don't guess CSS.

## Writing a clip

One file per clip in `clips/<area>/<slug>.ts`, default-exporting a `Clip`
(shape in `lib/runner.ts`). `name` maps to the output `/videos/<name>.mp4` and
poster — it **must** equal the path embedded in the MDX.

```ts
import type { Clip } from "../../lib/runner.ts";

const clip: Clip = {
name: "canvas/node-text",
url: "/dashboard", // or /editor/<id>/canvas from clips/config.json
// size: [1920, 1080], // walkthroughs only; default 1280x800
actions: async ({ page, h }) => {
await h.click(page.getByRole("button", { name: "Add a node" }));
await h.type(page.getByRole("textbox"), "A misty forest at dawn");
await h.skip(async () => waitForGeneration(page)); // jump-cut long waits in post
},
};
export default clip;
```

Use the `h` helpers (`click`, `moveTo`, `type`, `scroll`, `drag`, `beat`,
`skip`, `mark`) — never raw `locator.click()`, which teleports the cursor with no
visible motion. `h.skip(fn)` records the wall-clock span of a long wait
(generation, render, upload) so ffmpeg jump-cuts it, keeping ~1.5s of the loading
state then cutting to the reveal. `h.mark()` resets the visible start (trims
everything before it).

## Encoding (automatic, in `lib/runner.ts`)

webm → h264 mp4, `yuv420p`, `+faststart`, 30fps, CRF 24 (set `crf: 26` on a clip
if it exceeds budget), plus a poster JPG at ~1s. Loops target under 2 MB, hard
cap 8 MB.

## Verify EVERY clip

A green "done" is not proof. For each recorded clip:

```bash
ffprobe -v error -show_entries format=duration -of csv=p=0 ../../videos/<name>.mp4
ffmpeg -ss <t> -i ../../videos/<name>.mp4 -frames:v 1 <scratch>/f.png # then LOOK at it
```

A clip showing a sign-in page, an empty state, a stuck spinner, the wrong screen,
or a dev overlay is a **failure** — fix and re-record. A too-short duration
usually means a selector didn't match and the actions no-op'd.

## Tiers (record in this order)

- **T1 pure-UI** — dashboard, settings, project CRUD, canvas nav/toolbar/wiring,
context menus. Fully deterministic, cheap.
- **T2 one-generation** — image/audio/vector gen, image tools, AI-chat build.
Wrap the wait in `h.skip`, generous timeout, one retry. Costs credits — budget
per batch.
- **T3 hard** — video gen + render (minutes + credits; record once, trim hard),
multiplayer (two browser contexts, two accounts), voice
(`--use-fake-device-for-media-stream`), 3D/WebGL (headed GPU). Do last with
fallbacks.

## Rules for recording sessions

- Seeded projects (`clips/config.json`) may be opened/favorited/edited additively,
never deleted. For destructive demos (trash/restore) create a fresh project
in-clip.
- Never complete a payment — opening plan pickers and purchase dialogs is fine,
stop before any checkout confirm.
- Generations spend real workspace credits — keep to what the clip needs.
- Parallel recording agents work, but they share one login — pass `--no-auth` so a
fresh `run.ts` doesn't rotate the session out from under a sibling.

## Portability

To reuse this harness in another Mintlify + Next-app docs setup: keep
`lib/{runner,human,cursor,env}.ts` verbatim; re-point `env.ts` FE_ROOT; re-mirror
`lib/auth.ts` to the target app's auth flow; rewrite `setup/` for that app's
onboarding/seed; write new `clips/`.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules
node_modules
.DS_Store
68 changes: 45 additions & 23 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,55 @@
> **First-time setup**: Customize this file for your project. Prompt the user to customize this file for their project.
> For Mintlify product knowledge (components, configuration, writing standards),
> install the Mintlify skill: `npx skills add https://mintlify.com/docs`
# Flowy Docs — authoring guide

# Documentation project instructions
Mintlify site (`docs.json` schema, aspen theme, dark default, brand `#5C9987`). Deployed to docs.tryflowy.ai by the Mintlify GitHub app on push to `main`.

## About this project
## Structure

- This is a documentation site built on [Mintlify](https://mintlify.com)
- Pages are MDX files with YAML frontmatter
- Configuration lives in `docs.json`
- Use the Mintlify MCP server, `https://mcp.mintlify.com`, to edit content and settings via MCP
- Use the Mintlify docs MCP server, `https://www.mintlify.com/docs/mcp`, to query information about using Mintlify via MCP
- Three tabs in `docs.json`: **Documentation**, **Help Center**, **API Reference**.
- Navigation is nested: `tabs → groups → pages`, where a pages entry is a path string or a nested `{ "group", "pages" }` object. Moved pages get a `redirects[]` entry — never break an existing URL.
- These paths are deep-linked from the app (`FE-genstudio/src/lib/docs.ts`) and must keep resolving: `api/authentication`, `api/permissions`, `api/running-apps`, `collaboration/roles`, `collaboration/workspaces`, `collaboration/sharing`, `billing/credits`, `generators/overview` (redirect).

## Terminology
## Page conventions

{/* Add product-specific terms and preferred usage */}
{/* Example: Use "workspace" not "project", "member" not "user" */}
- Frontmatter: `title` (Title Case, ≤45 chars), `description` (one benefit-led sentence), `sidebarTitle` when the title is long, `"og:image"` only on hub pages.
- Feature-page shape: 1–2 sentence lede → **hero video** → `##` sections.
- `<Steps>` for ≥3 sequential actions; `<Tabs>` for mutually exclusive variants; `<CardGroup>` only on hub/overview pages; `<AccordionGroup>` for FAQs; max 2 callouts per page; shortcuts as tables with `<kbd>`.
- Internal links are root-relative (`/canvas/nodes/image`). Never link to redirected legacy paths (`/generators/*`, `/canvas/nodes`, `/canvas/ai-chat`).
- Voice: second person, present tense, plain. No "simply/just/easily". Every UI label, limit, and price must match the product — when unsure, verify against FE-genstudio source or leave it out.

## Style preferences
## Videos

{/* Add any project-specific style rules below */}
Two embed patterns, both from `/snippets/components/`:

- Use active voice and second person ("you")
- Keep sentences concise — one idea per sentence
- Use sentence case for headings
- Bold for UI elements: Click **Settings**
- Code formatting for file names, commands, paths, and code references
```mdx
import { DemoVideo } from "/snippets/components/demo-video.jsx";

## Content boundaries
<DemoVideo
src="/videos/<area>/<clip>.mp4"
poster="/images/posters/<area>/<clip>.jpg"
caption="Present-tense caption"
/>
```

{/* Define what should and shouldn't be documented */}
{/* Example: Don't document internal admin features */}
for silent 5–20s loops (1280×800, aspect 16/10), and

```mdx
import { VideoPlayer } from "/snippets/components/video-player.jsx";

<VideoPlayer src="…" poster="…" title="Watch: …" />
```

for 30–90s click-to-play walkthroughs (1920×1080, 16/9).

Rules: h264 mp4, `yuv420p`, `+faststart`, muted, no browser chrome; loops target under 2 MB (hard cap 8 MB); every video ships a poster JPG at the mirrored path under `/images/posters/`; **no GIFs**.

Videos are produced by the automation harness in `scripts/record/` — one clip script per video, recorded against a local FE-genstudio server (see the repo README).

## Checks

```bash
pnpm check # mintlify validate
pnpm broken-links # internal link check (does NOT check media paths)
pnpm dev # local preview on :3334
```

Media paths aren't validated by Mintlify — after adding pages or clips, diff MDX-referenced `/videos/*` + `/images/posters/*` against files on disk.
Loading