diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..51bd3bc0 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,52 @@ +name: Docs Lint + +on: + pull_request: + paths: + - '**.mdx' + - '.vale.ini' + - '.vale/**' + - 'docs.json' + - 'audit.csv' + - '.github/workflows/lint.yml' + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + vale: + name: Vale (style guide) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + # Week 1–5: minAlertLevel=warning, fail-on-error=false → annotations only. + # Week 6 cutover: flip to minAlertLevel=error AND fail_on_error=true (PRD §WS-6b). + - name: Vale + uses: errata-ai/vale-action@reviewdog + with: + version: 3.7.0 + fail_on_error: false + filter_mode: nofilter + reporter: github-pr-check + vale_flags: "--minAlertLevel=warning" + + audit-csv: + name: audit.csv freshness + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - run: npm ci + + - name: Verify audit.csv is in sync with docs/ + run: npm run audit:check diff --git a/.vale.ini b/.vale.ini index f2fb6d71..e2196a8c 100644 --- a/.vale.ini +++ b/.vale.ini @@ -13,7 +13,7 @@ mdx = md # MDX support [*.mdx] -BasedOnStyles = Vale +BasedOnStyles = Vale, Helius Vale.Terms = NO # Enforces really harsh capitalization rules, keep off # `import ...`, `export ...` diff --git a/.vale/styles/Helius/Hyperbole.yml b/.vale/styles/Helius/Hyperbole.yml new file mode 100644 index 00000000..ac7f29d7 --- /dev/null +++ b/.vale/styles/Helius/Hyperbole.yml @@ -0,0 +1,16 @@ +extends: existence +message: "'%s' is filler — usually means the sentence reads fine without it. Cut it." +link: https://www.helius.dev/docs/CONTRIBUTING.md#voice +level: suggestion +ignorecase: true +tokens: + - easily + - effectively + - essentially + - just + - leverage + - merely + - quickly + - really + - simply + - very diff --git a/.vale/styles/Helius/MarketingFluff.yml b/.vale/styles/Helius/MarketingFluff.yml new file mode 100644 index 00000000..a655968e --- /dev/null +++ b/.vale/styles/Helius/MarketingFluff.yml @@ -0,0 +1,24 @@ +extends: existence +message: "Avoid marketing language: '%s'. Be concrete — describe what it does, not how great it is." +link: https://www.helius.dev/docs/CONTRIBUTING.md#voice +level: warning # Flip to `error` at the week-6 cutover (PRD §WS-6b) +ignorecase: true +tokens: + - blazing + - blazing(?:[ -]fast)? + - best[ -]in[ -]class + - cutting[ -]edge + - demand excellence + - effortless + - effortlessly + - industry[ -]leading + - lightning[ -]fast + - powerful + - revolutionary + - robust + - seamless + - seamlessly + - state[ -]of[ -]the[ -]art + - unleash + - unlock(?:s|ed|ing)?(?: the power) + - world[ -]class diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 789c1652..54024291 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -39,11 +39,52 @@ mint dev - Ensure headings are descriptive and keyword-rich. - Add ``, ``, ``, `` where applicable. +### Voice + +Docs are reference material, not marketing copy. Be concrete. Describe what something does, not how great it is. + +Banned words (Vale enforces — see `.vale/styles/Helius/`): + +- `blazing`, `lightning-fast`, `world-class`, `industry-leading`, `best-in-class`, `cutting-edge`, `state-of-the-art`, `revolutionary` +- `powerful`, `robust`, `seamless`, `effortless`, `unleash`, `unlock the power`, `demand excellence` + +Filler to cut on review: `simply`, `easily`, `just`, `merely`, `leverage`, `essentially`, `effectively`, `very`, `really`, `quickly`. + +Marketing belongs on `helius.dev`, not `/docs`. + ## Linting and formatting - Keep Markdown and MDX clean and readable. - Ensure code blocks include a language tag and, when relevant, filenames. - No real secrets. Use environment variables or placeholders like `YOUR_API_KEY`. +- Vale runs on every PR via [`.github/workflows/lint.yml`](.github/workflows/lint.yml). Install locally with `brew install vale` (macOS) and run `vale .` from the repo root to preview violations before pushing. + +## Page audit + +[`audit.csv`](audit.csv) is the page inventory used to plan the documentation redesign. It maps every English `.mdx` page to its Diátaxis type, persona, action (Keep/Rewrite/Split/Merge/Delete), and target URL. + +Regenerate after adding or moving a page: + +```bash +npm run audit # rewrites audit.csv (preserves hand-edited columns) +npm run audit:check # CI: fails if audit.csv is stale +``` + +Hand-edited columns (`diataxis_type`, `jtbd`, `persona_override`, `action`, `new_url`, `pageviews_30d`, `helpful_yes_no_30d`, `notes`, `owner`, `status`) are merged on `url` across runs — they survive regeneration. + +## Redesign-branch workflow + +When working on rename-heavy redesign PRs (URL changes, file moves, large nav restructures), the husky `pre-commit` hook will re-run translations on every commit. To iterate locally without that overhead: + +```bash +HUSKY=0 git commit -m "..." # skip the hook entirely +# or +git commit --no-verify -m "..." # same effect +``` + +CI ([`.github/workflows/i18n.yml`](.github/workflows/i18n.yml)) re-runs the translation pipeline on push to `main` and opens an auto-translation PR. Don't worry about ZH parity during redesign-branch iteration — settle the EN tree first, then merge the auto-translation PR. + +Batch redirects and renames into a single PR per phase to keep the translation cost bounded. ## Analytics diff --git a/SPIKE-NOTES.md b/SPIKE-NOTES.md new file mode 100644 index 00000000..3d58374b --- /dev/null +++ b/SPIKE-NOTES.md @@ -0,0 +1,50 @@ +# Documentation redesign — week-1 spike notes + +Snapshot of findings while exploring Mintlify capabilities for the redesign workstreams. Drives the WS-3, WS-4, WS-5, WS-6 implementation choices. Keep this file alongside the work; delete after week 6 cutover. + +## 6.2 — "Was this page helpful?" feedback widget + +**Built-in:** Yes. Mintlify ships thumbs up/down, plus contextual feedback, edit suggestions, "raise issues" (GitHub), code-snippet feedback, and agent feedback (beta). + +**How to enable:** Dashboard → Add-ons. Not configurable via `docs.json` directly. + +**Gating constraint:** Disabled if telemetry is off in `docs.json`. Our telemetry is on (PostHog at [docs.json:50–55](docs.json:50)) — feedback works. + +**PostHog routing — open question:** Mintlify's docs don't say feedback events forward to PostHog. They surface in Mintlify's own feedback dashboard. To meet PRD §WS-6d ("'Was this helpful: No' with optional free-text reason" captured in our analytics), we likely need a custom helpful widget that emits `docs_helpful_yes` / `docs_helpful_no` PostHog events directly — or a periodic export from Mintlify's dashboard if it exists. + +**Decision:** Enable Mintlify's native widget for UX; build a custom PostHog-emitting wrapper (`scripts/telemetry.js`) for the analytics requirement. Both can coexist. + +## 6.3 — Diátaxis page-type badges + +**Frontmatter→meta passthrough:** Undocumented in Mintlify's published docs. Must verify against a deployed page's rendered HTML. Until confirmed, do not rely on a single global `scripts/diataxis-badge.js` reading ``. + +**Custom scripts:** Mintlify auto-includes `.js` files from the content directory on every page. The `scripts[]` array in [docs.json:56–60](docs.json:56) is the official way to register external scripts (already in use for `structured-data.js`). + +**Decision (revised from plan §6.3):** Default to importing `snippets/diataxis-badge.mdx` on every page (reliable, more boilerplate). Keep a global-script alternative as a stretch goal: spike on a deploy preview to read frontmatter from the rendered DOM. If frontmatter is exposed (in a `