Commit 2938057
docs: rewrite user-facing documentation (#2074)
## Summary
Rebuilds `/documentation` against the docs overhaul spec: new
task-oriented IA, redirect map for every old slug, new home, callouts,
code-block copy buttons, mobile drawer, softened WIP banner. The five
highest-leverage pages (Connect Notion, How sync works, Card options,
Limits, Common problems) are rewritten with claims verified against
`src/`. The other new pages in the IA ship as honest stubs, each with a
tracking GitHub issue.
## What's in this PR
**Structural / visual**
- New `sidebar.ts` with the Designer's IA (Start here / Make better
cards / Sync with Notion / When something breaks / Reference / Links)
plus a `redirects` map covering every retired slug.
- `loader.ts` honours redirects on miss; `DocContent.tsx` issues a
301-style React Router `<Navigate replace>` so legacy URLs land on the
new slug.
- `DocsPage.tsx` swaps the inline mobile menu for a slide-in drawer
(`DocsDrawer.tsx`) with body-scroll lock, Escape-to-close, and backdrop
click.
- `DocsSidebar.tsx` reuses one component for desktop and drawer mode,
adds an active-group left-border indicator.
- `DocsHome.tsx` rewritten per the ASCII mock — hero with two CTAs, four
Start-here cards, popular pages list, footer line. Mascot dropped from
the docs landing.
- `DocContent.tsx` adds `:::note`, `:::tip`, `:::warning` callout
directives via a small remark-equivalent regex transform that emits raw
HTML, plus a `CodeBlock` slot with a copy button.
- New components: `Callout.tsx`, `CodeBlock.tsx`, `DocsDrawer.tsx`
(~30–60 lines each).
- CSS deltas in `DocsPage.module.css`: callouts, steps list,
code-wrapper + copy button, drawer, home cards, slimmer WIP banner. H2
top margin tightened to 2.5rem; `pre` gets a 1px border. Old hero
classes removed.
- `WipBanner.tsx` softened — drops the WIP pill, single short sentence,
smaller padding.
- File moves preserve existing prose where slugs map cleanly
(`features/markdown.md` → `cards/markdown.md`, `features/html.md` →
`cards/html.md`, `features/notion-support.md` →
`cards/notion-blocks.md`, `troubleshooting/contact.md` →
`help/contact.md`, `troubleshooting/bug-report.md` →
`help/bug-report.md`, `advanced/napi.md` → `reference/api.md`,
`advanced/self-hosting.md` → `reference/self-hosting.md`,
`misc/privacy-policy.md` → `reference/privacy.md`,
`misc/terms-of-service.md` → `reference/terms.md`).
**Content rewritten in this PR**
- `start-here/connect-notion` — full rewrite around the Notion
integration. The load-bearing first-touch page.
- `sync/how-it-works` — new page covering the Ankify sync flow. Notes
the private-alpha allowlist truthfully (see Risks).
- `cards/card-options` — reference table built from
`src/controllers/CardOptionsController/supportedOptions.ts`. Internal
keys listed at the bottom for bug reports.
- `help/limits` — every unbacked number dropped (21 files, 100
flashcards/deck, 2,100 files, "no concurrent job limit"). Now lists only
what `src/lib/misc/getUploadLimits.ts`,
`src/infrastracture/adapters/fileConversion/convertPDFToImages.ts`, and
`src/lib/constants.ts` actually back.
- `help/common-problems` — 9 entries, each with the exact error string
from `getUploadValidationError.ts`, `convertPDFToImages.ts`,
`ClaudeService.ts`, plus Notion permission + missing-images cases.
- `reference/glossary` — merged from `domain.md` + `terminology.md`,
alphabetised, plain language.
- `reference/self-hosting` — corrected to the canonical `2anki/server`
monorepo (the page used to imply two repos; `web/` is a workspace). Kept
short — the audit explicitly says don't grow this.
- `cards/markdown` — fixed "Markdonw" typo, retitled to match sidebar.
- `cards/notion-blocks`, `help/contact`, `help/bug-report` — fixed stale
`2anki/2anki.net` GitHub links and old slug references.
**What's intentionally stubbed**
Each stub is a single short paragraph in the voice from the Designer's
section 8, plus a link to its tracking issue:
- `start-here/what-is-2anki` — issue
[#2066](#2066)
- `start-here/upload-a-file` — issue
[#2067](#2067)
- `start-here/open-in-anki` — issue
[#2068](#2068)
- `cards/card-types` — issue
[#2069](#2069)
- `sync/review-export` — issue
[#2070](#2070)
- `sync/troubleshooting` — issue
[#2071](#2071)
- `reference/file-formats` — issue
[#2072](#2072)
- `reference/self-hosting` — short summary now; full guide tracked in
[#2073](#2073)
`reference/privacy` and `reference/terms` keep their existing copy. The
audit's `MISSING-CONTEXT` finding is recorded as a `todo:` line in each
file's frontmatter so Alexander can pick them up. See Risks.
## Verified against code
| Claim | Source of truth |
|---|---|
| 100 MB free upload, ~10 GB paid | `src/lib/misc/getUploadLimits.ts` |
| 100 PDF pages on free, no fixed cap on paid |
`src/infrastracture/adapters/fileConversion/convertPDFToImages.ts` |
| 2-hour file deletion | `CLEANUP_AGE_SECONDS = 7200` in
`src/lib/constants.ts` (also matches the upload UI footer text) |
| All `help/common-problems` error strings |
`src/lib/upload/getUploadValidationError.ts`, `convertPDFToImages.ts`,
`src/lib/claude/ClaudeService.ts` |
| Card option labels and descriptions |
`src/controllers/CardOptionsController/supportedOptions.ts` (exact key
match) |
| Self-hosting target is `2anki/server` monorepo | `package.json`,
`web/package.json` (`"name": "2anki-web"`), `web/CLAUDE.md` |
| Sync is currently allowlisted | `src/lib/constants.ts`
`ANKIFY_ALLOWLIST_EMAILS = ['alexander@alemayhu.com']`, enforced in
`src/routes/middleware/RequireAnkifyAccess.ts` |
**Audit corrections worth flagging**
1. The audit said the `/upload` UI claims a 24-hour cleanup window
contradicting the 2-hour limits page. As of this PR, the upload UI in
`web/src/pages/UploadPage/UploadPage.tsx:60` reads "All files uploaded
here are automatically deleted after 2 hours." — consistent with
`CLEANUP_AGE_SECONDS`. No UI change needed.
2. The audit asked us to confirm whether `2anki/web` standalone is still
the deployment target. It isn't — `web/` is a workspace inside this
monorepo (`web/CLAUDE.md` is explicit, package name is `2anki-web`).
`reference/self-hosting` now reflects that.
3. The audit flagged the privacy policy as missing Stripe / SendGrid /
Anthropic / Vertex AI and listing ChatGPT despite `src/` having no
OpenAI integration. Confirmed: `grep -rn -i "ChatGPT\|OpenAI" src/`
returns nothing. Stripe, SendGrid, Anthropic, and Vertex AI are all
imported in `src/`. Defer the actual policy rewrite to Alexander per
spec — but the contradiction is real and the `todo:` frontmatter records
it.
## Risks
- **Sync alpha framing**: `sync/how-it-works` is honest about private
alpha (allowlisted in code). If Alexander would rather the doc imply
broader availability ahead of opening sync up, soften the callout. I'd
lean on accuracy.
- **Redirects map**: Legacy slugs that aren't in the map (e.g. anyone
deep-linked an old anchor) will hit "Not found". The map covers every
previous file in the content directory, so this should only catch typos
and external broken links.
- **Callout transform**: implemented as a regex transform that emits raw
`<aside>` HTML rather than pulling in `remark-directive`. Trade-off
note: less moving parts and zero new deps, at the cost of being a string
transform rather than an AST one. If the directive syntax grows beyond
the three callout variants, swap in `remark-directive`.
- **`Callout.tsx` is currently unused** (kept for forward-compat with
the design spec; the in-doc callouts go through the regex transform).
Considered removing it but the Designer's hand-off explicitly listed it
as a deliverable. Easy to delete in a follow-up if we don't need it.
Rollback plan: revert this single commit. No DB migrations, no env vars,
no server code touched.
## Goal alignment
Aligned with the 300K-user goal in `CLAUDE.md`. The single
highest-leverage doc change — rewriting the load-bearing first-touch
page (`start-here/connect-notion`) around the actual happy path —
addresses the audit's #1 finding ("the docs describe the 2022-era
product"). New users currently hit a guide that pushes them down a
Notion-export-then-zip flow that's slower and more error-prone than the
integration. The new IA puts the fast path first, the paid feature
(sync) gets its own visible group, and `help/common-problems` should
reduce inbound support email by being indexable on real error strings.
## Test plan
Before merging, please:
- [ ] Run `pnpm dev` and visit `/documentation`. Hero, four start-here
cards, and popular-pages list render. CTAs go to Connect Notion / Upload
a file.
- [ ] Visit `/documentation/guides/getting-started` — should redirect to
`/documentation/start-here/connect-notion`.
- [ ] Visit `/documentation/troubleshooting/limits` — should redirect to
`/documentation/help/limits`.
- [ ] Visit `/documentation/misc/privacy-policy` — should redirect to
`/documentation/reference/privacy`.
- [ ] Open dev tools, set viewport to 375 px wide. Hit Menu — drawer
slides in from the left, no horizontal scroll, hero CTAs stack. Esc
closes the drawer; clicking the backdrop closes it.
- [ ] On `cards/card-options`, scan the table — every option in the
upload screen's settings modal should have a row.
- [ ] On `help/common-problems`, hover or click a code block — Copy
button appears top-right and copies the snippet.
- [ ] Verify the `:::warning` callout on `sync/how-it-works` renders
with the warning palette.
- [ ] Sidebar: navigate into `Sync with Notion` group — the active-group
left border should appear on that group's items only.
CI checks already passing locally:
- `pnpm --filter 2anki-web typecheck` — clean
- `pnpm --filter 2anki-web lint` — clean
- `pnpm --filter 2anki-web test` — 70/70 passing (sidebar, loader,
DocsHome added)
- `pnpm --filter 2anki-web build` — clean
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 7ba1f15 commit 2938057
55 files changed
Lines changed: 1365 additions & 759 deletions
File tree
- web/src/pages/DocsPage
- content
- advanced
- cards
- features
- guides
- help
- links
- reference
- start-here
- sync
- troubleshooting
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
3 | 8 | | |
4 | 9 | | |
5 | 10 | | |
6 | 11 | | |
7 | | - | |
8 | | - | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
9 | 16 | | |
10 | 17 | | |
11 | 18 | | |
| |||
58 | 65 | | |
59 | 66 | | |
60 | 67 | | |
61 | | - | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
62 | 121 | | |
63 | 122 | | |
64 | 123 | | |
65 | | - | |
| 124 | + | |
66 | 125 | | |
67 | 126 | | |
68 | 127 | | |
69 | 128 | | |
| 129 | + | |
70 | 130 | | |
71 | 131 | | |
72 | 132 | | |
| |||
78 | 138 | | |
79 | 139 | | |
80 | 140 | | |
81 | | - | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
82 | 149 | | |
83 | 150 | | |
84 | 151 | | |
| |||
94 | 161 | | |
95 | 162 | | |
96 | 163 | | |
| 164 | + | |
97 | 165 | | |
98 | 166 | | |
99 | 167 | | |
| |||
112 | 180 | | |
113 | 181 | | |
114 | 182 | | |
115 | | - | |
| 183 | + | |
116 | 184 | | |
117 | 185 | | |
118 | 186 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
0 commit comments