Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .oxfmtrc.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
{
"ignorePatterns": ["apps/web/src/routeTree.gen.ts", "packages/backend/convex/_generated/**"]
"ignorePatterns": [
"apps/web/src/routeTree.gen.ts",
"apps/fumadocs/src/routeTree.gen.ts",
"packages/backend/convex/_generated/**"
]
}
10 changes: 10 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@

Do not install `recharts` — it has CJS/ESM interop issues with this Vite + TanStack Start setup (causes `require_isUnsafeProperty is not a function` at runtime). Use pure CSS/SVG bar charts instead (see `proactivation-analytics-panel.tsx` for the pattern: flex columns with `height: pct%` + `bg-foreground`).

## Documentation Sync

**When you change a feature, update its docs in the same change.** The public docs live in `apps/fumadocs/content/docs/`. If your work changes what a user or integrating agent can observe — a customer-facing surface, an API route or SDK method, a CLI command, an automation rule, a config/env var, an auth scope, a setup or deploy step, or a workflow's behavior — the matching MDX page must be updated before the work is considered done.

This applies to **content only**. Do not touch the Fumadocs framework, routing, or build config as part of feature work.

- A pure internal refactor with no observable change does **not** require a docs edit.
- If a feature has **no** owning doc page yet, add a page (and register it in `content/docs/meta.json`) or flag the gap in your summary — do not silently leave it undocumented.
- The feature → doc-page map and detailed triggers live in `apps/fumadocs/AGENTS.md`. Read it before editing docs.

## SirPaul PR Workflow

SirPaul story work must go through a pull request. Do not treat "ship it" or similar language as permission to bypass a PR for SirPaul work unless the user explicitly says not to make a PR in the current turn.
Expand Down
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,15 @@ bun run dev:setup -- --expiration "in 2 days"
bun run dev:setup -- --worktree-name my-feature
```

Then it runs `convex dev --once --tail-logs disable`, seeds safe default Convex env vars for the
worktree-local URL, and writes `apps/web/.env` from the generated `packages/backend/.env.local`
`CONVEX_URL` and `CONVEX_SITE_URL`.
Then it runs `bun install`, `convex dev --once --tail-logs disable`, seeds safe default Convex env
vars for the worktree-local URL, and writes `apps/web/.env` from the generated
`packages/backend/.env.local` `CONVEX_URL` and `CONVEX_SITE_URL`.

If dependencies are already installed and you only want to refresh the Convex selection/env, use:

```bash
bun run dev:setup -- --skip-install
```

For local anonymous deployments instead of cloud dev deployments, run:

Expand Down
14 changes: 8 additions & 6 deletions apps/fumadocs/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@
# generated content
.source

# test & build
/coverage
/.next/
/out/
# tanstack start / vite / nitro build output
/.output
/.nitro
/.tanstack
/dist
/out
/build
/coverage
*.tsbuildinfo

# misc
Expand All @@ -22,5 +25,4 @@ yarn-error.log*

# others
.env*.local
.vercel
next-env.d.ts
.vercel
67 changes: 67 additions & 0 deletions apps/fumadocs/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Agent Guidelines — Docs (`apps/fumadocs`)

This is the canonical public documentation for Amend. When a feature changes, the docs change with it — see **Documentation Sync** in the repo-root `AGENTS.md` for the core rule. This file tells you _which page_ to update and _when_.

## Scope

- Edit **content** only: `content/docs/*.mdx` and `content/docs/meta.json`.
- Do **not** change the Fumadocs framework, `source.config.ts`, app routing, layouts, search, or build config as part of feature work. A docs migration is a separate, explicit task.
- New pages must be registered in `content/docs/meta.json` (the `pages` array is the sidebar order).

## When a docs edit is required

Update docs in the same change when your work alters anything a user or integrating agent can **observe**:

- A customer-facing surface (portal, feedback board, voting/comments/reactions, update feeds, embed panel)
- A REST route (`/api/v1/*`) or SDK method (`packages/sdk`, the `Amend` class)
- A CLI command or flag (`packages/cli`)
- An automation rule, AI drafting behavior, proactive-agent behavior, or delivery/safety gate
- A config value, env var, provider key, auth scope/token tier, or default
- A setup, onboarding, deploy, domain, or launch step
- The observable behavior or wording of any documented workflow

You do **not** need a docs edit for a pure internal refactor, rename, or perf change with no observable difference.

## Feature → doc-page map

The docs are organized by **job in the loop** (intake → evidence → review → publish), not by UI screen. Find the surface you touched and update the page(s) that own it.

| Feature / code area | Owning page(s) |
| ----------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| Feedback inbox, posts board, post composer, voting, comments, reactions | `feedback/triaging.mdx`, `feedback/collecting.mdx` (+ `api-reference.mdx`) |
| Feedback intake — portal form + `feedbackMode`, SDK `submitRequest`, imports | `feedback/collecting.mdx` (+ `customer-surfaces.mdx`) |
| Embed panel — `createAmendPanel`, `packages/sdk` `embed.ts` | `customer-surfaces.mdx` |
| Roadmap board, drag/drop, priorities, item detail; status values + API mapping | `roadmap/managing.mdx`, `roadmap/index.mdx` (+ `source-trace.mdx`) |
| Public roadmap visibility (`roadmapVisibility`), voting, `GET /roadmap` | `roadmap/public.mdx` |
| Changelog editor, statuses, categories, versions, publish + email toggles | `changelog/writing.mdx` |
| AI changelog drafting (`draftChangelog`, `POST /drafts`, CLI `changelog draft`) | `changelog/ai-drafting.mdx` (+ `automation.mdx` for provider keys) |
| Source events — GitHub / Slack / Discord / Linear / CSV imports, event kinds, idempotency | `source-events.mdx` |
| Automation rules, proactive agent, build briefs, decisions, delivery safety | `automation.mdx` |
| SDK surface (`Amend` class methods) | `api-reference.mdx` (+ `customer-surfaces.mdx` for client read/write methods) |
| REST HTTP actions (Convex `/api/v1`), webhooks, auth tiers | `api-reference.mdx`, `integration.mdx` |
| CLI commands (`packages/cli`) | `source-events.mdx` (imports) — no dedicated CLI page yet; see Gaps |
| Settings UI (general, services, portal, automation, accounts) | `integration.mdx` (portal/services), `self-hosting.mdx` (env) |
| Onboarding / project-setup wizard | `quickstart.mdx` |
| Env vars, provider keys, model policy, deployment pieces | `self-hosting.mdx` |
| Domains, Vercel proxy, `amend.sh/docs` routing, `llms.txt`, schemas | `production-routing.mdx` |
| Auth scopes / token tiers (public / webhook / owner) | `integration.mdx`, `api-reference.mdx` |
| Pre-launch gates (typecheck, smoke, DNS, billing, email) | `launch.mdx` |
| Local dev loop (`bun run dev:setup`, prove one full loop) | `quickstart.mdx` |

## Gaps — built but undocumented

These features ship in the app but have no owning page. If you touch one, add a page (and register it in `meta.json`) rather than wedging it into an unrelated page:

- **Analytics workspace** (`analytics-workspace*.tsx`) — no public page
- **Full CLI reference** — every `packages/cli` subcommand; only import-related usage is covered today
- **Full SDK method reference** — the `Amend` class has ~25+ methods; only a subset is documented
- **Settings UI walkthrough** — services, portal settings, automation rules as configured in the dashboard

Internal-only surfaces (brand guidelines page, brand menu, admin sidebar) are **not** public docs — do not document them here.

## Style

- Match the existing voice: terse, source-linked, written for a maintainer or coding agent verifying what actually runs.
- Keep the loop framing (intake / evidence / review / publish) — don't reorganize docs around UI screens.
- Use relative links between pages (e.g. `[Source events](source-events.mdx)`), Fumadocs `<Cards>`/`<Card>` for hubs, and tables for surface/route/auth maps, as existing pages do.
- Don't hardcode the docs origin in product code — that's `VITE_DOCS_URL`.
46 changes: 46 additions & 0 deletions apps/fumadocs/content/docs/changelog/ai-drafting.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
title: AI drafting
description: Turn source evidence into a first-draft changelog entry from the SDK, REST, or CLI.
---

Writing a changelog entry from scratch is the part people skip, which is how shipped work goes unannounced. Drafting closes that gap: hand Amend the evidence for a change and get back a draft entry you can edit and publish, instead of a blank editor.

## What you need first

Drafting calls a language model, so it needs a provider key configured for the workspace. That is set up alongside the rest of your [automation](/docs/automation) settings. Without a key, the draft endpoints have nothing to call.

## Draft from code

The SDK turns input into a draft entry:

```ts
const draft = await amend.draftChangelog({
title: "Bulk CSV export", // required
body: "Rough notes or context for the model to expand on.",
kind: "added",
sourceLinks: [{ url: "https://github.com/acme/app/pull/482" }],
dryRun: true, // preview without saving a draft
});
```

Only `title` is required. `body`, `kind`, and `sourceLinks` give the model more to work with, and `dryRun` returns the draft without persisting it.

The matching REST route is `POST /api/v1/your-workspace/drafts`, which takes an owner token. Both return a draft you then review, adjust, and save through the normal [writing and publishing](/docs/changelog/writing) flow. Nothing is published automatically.

## Draft from the CLI

The CLI is handy when you want a draft as part of a release script:

```bash
amend changelog draft --title "Bulk CSV export"
```

It prints the draft as JSON and supports a dry run, so you can see what you would get before anything is written.

## The editor's assistant panel

The changelog editor has an assistant rail down the right side with quick actions like improve writing, add a summary, and suggest tags. The panel is in place, but it needs a model provider wired up before it returns suggestions. Until then, use the drafting calls above, which run through the same provider configuration.

## Where drafts fit

Drafting does not replace the loop, it speeds up the last step of it. The strongest drafts come from entries that already have source evidence attached, since the model is summarizing real work rather than guessing. Connect the roadmap item to its PRs and issues, and the draft has something concrete to describe.
32 changes: 32 additions & 0 deletions apps/fumadocs/content/docs/changelog/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
title: Changelog
description: Write and publish shipped-work announcements that trace back to the feedback and roadmap behind them.
---

The changelog is the end of the loop: the public record of what you shipped. An entry is the announcement a customer reads, but because it carries the same source evidence as the roadmap item it came from, it is also the proof that a request actually got answered. Someone who asked for a thing can be told, by name, that it landed.

<Screenshot caption="The changelog list: entries with a category, version, status, and publish date." />

## What an entry holds

Each entry has:

- A `title` and `body`, plus a `summary` for the list view. The editor fills the summary from the first line of the body so you do not write it twice; over the API you pass `summary` yourself.
- A category: `added` ("New"), `changed` ("Improved"), `fixed` ("Fixed"), or `removed` ("Removed").
- A status that moves through `draft`, `in_review`, `scheduled`, and `published`.
- An optional `version` like "2.4.0", plus free-form tags and the `sourceLinks` that tie it to the work.

## How an entry travels

An entry is a draft until you decide otherwise. You write it, set a category and maybe a version, then move it along: `in_review` when it needs a second set of eyes, `scheduled` if it should go out later, `published` when it is live. Publishing with the portal toggle on is what puts it in front of customers, and you can have publishing email your subscribers at the same time.

## Where to go next

<Cards>
<Card title="Writing and publishing" href="/docs/changelog/writing">
The editor, categories and versions, the draft-to-published path, and notifying subscribers.
</Card>
<Card title="AI drafting" href="/docs/changelog/ai-drafting">
Turn source evidence into a first-draft entry from the SDK, REST, or CLI.
</Card>
</Cards>
4 changes: 4 additions & 0 deletions apps/fumadocs/content/docs/changelog/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"title": "Changelog",
"pages": ["index", "writing", "ai-drafting"]
}
67 changes: 67 additions & 0 deletions apps/fumadocs/content/docs/changelog/writing.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---
title: Writing and publishing
description: Use the changelog editor, set category and version, move an entry from draft to published, and notify subscribers.
---

The editor is a focused writing surface with the controls you need and not much else. You write in the middle, and the things that decide where the entry goes live in a settings popover.

## Write the entry

Start a new entry from "Write changelog" on the empty state or "New changelog" in the header. You get a blank draft, category `added`, status `draft`, ready to type into.

The body is a rich-text editor with a toolbar. As you write, the summary is taken from the first line, and the editor shows word count, character count, and an estimated read time so you can keep entries tight.

<Screenshot
caption="The changelog editor, with the body on the left and settings to the right."
ratio="16 / 10"
/>

Saving is explicit. Cmd/Ctrl+S or the Save button writes the entry, and a small indicator tells you the state: an amber dot for unsaved changes, a green check once saved. If you try to close with unsaved edits, you get a "Discard unsaved changes?" prompt rather than losing the work.

## Category and version

Two fields shape how an entry reads in the list:

- Category sorts the entry into New, Improved, Fixed, or Removed. Pick the one that matches the change.
- Version is optional. Set something like "2.4.0" when an entry maps to a release; leave it blank when it does not.

## Draft to published

An entry's status is how you control its life:

| Status | Use it when |
| ----------- | -------------------------- |
| `draft` | Still writing |
| `in_review` | Ready for someone to check |
| `scheduled` | Approved, going out later |
| `published` | Live |

You can set the status in the settings popover, or flip the quick toggle in the header between draft and published. Two checkboxes in that popover decide what publishing actually does:

- Show on public portal — whether customers see the entry. A published entry with this on appears in the portal's changelog feed.
- Email subscribers on publish — whether publishing also notifies the people subscribed to updates.

Leave both off and a published entry is effectively an internal record. Turn them on and publishing becomes the customer-facing announcement.

<Screenshot
caption="The settings popover: status, category, version, and the publish toggles."
ratio="4 / 3"
/>

## Save from code

If you generate entries elsewhere, upsert them directly. The call creates or updates on `stableKey`:

```ts
await amend.upsertChangelog({
title: "Bulk CSV export is live",
body: "You can now export a month of reports in one download.",
summary: "Export a month of reports in one download.",
category: "added",
status: "published",
version: "2.4.0",
stableKey: "changelog-bulk-export",
});
```

The editor derives `summary` from your first line for you, but over the API you set it yourself, as shown above. The matching route is `POST /api/v1/your-workspace/changelog`. To draft an entry from source evidence instead of writing it cold, see [AI drafting](/docs/changelog/ai-drafting).
Loading
Loading