Migrate documentation to Astro Starlight#1686
Conversation
Replaces the VuePress 1.x docs site with Astro 6 + Starlight 0.38. The previous `docs/.vuepress/` configuration stays in place for now since it's no longer wired into the build pipeline -- a separate cleanup will remove it. Migration highlights: - `docs/astro.config.mjs` configures Starlight with the Rapide theme, Expressive Code (line numbers + collapsible sections), a sitemap, and `starlight-page-actions` (Copy Markdown + Open in ChatGPT / Claude buttons on every page). - Guide pages, the homepage, and the 404 move from the legacy `docs/guide/*.md` + `docs/index.md` tree into `src/content/docs/` and are tracked in git. They were run through the VuePress preprocessor once at migration time, so they now contain Starlight-native asides (`:::tip[Title]`), HTML `<details>` accordions, fully resolved `@[code]` includes, and rewritten links with the `/docs` base prefix. - The TypeDoc-generated API reference is the only path that still passes through `scripts/generate-content.mjs` -- it normalizes TypeDoc's link forms and badge tokens. - The Netlify `_redirects` file (legacy `.html` URLs → clean URLs) is also generated by `generate-content.mjs`, now derived from the tracked content under `src/content/docs/guide/`. - Custom Starlight component overrides for `Head`, `Header`, `Footer`, and `ThemeSelect` reproduce the Handsontable docs look-and-feel (two-row header, sun/moon theme toggle, spreadsheet-style footer). - Root build orchestration (`docs:build` script chain, Netlify build command, GitHub Actions `build-docs.yml`) updated to invoke the Astro build via `npm ci && npm run build` inside `docs/`. Legacy `docs/guide/`, `docs/index.md`, and `docs/api-ref-readme.md` are deleted -- their content lives under `src/content/docs/` now.
Introduces four governance files under `docs/` so contributors -- and AI coding agents -- have a clear, self-contained reference for how to work on the docs site: - `docs/CLAUDE.md`: authoring standards. Diátaxis page-type taxonomy with folder-to-type mapping, voice and style rules with a banned-word list, four page-structure templates (tutorial / how-to / reference / explanation), example-data domain conventions, code-example rules (language tags, `licenseKey: 'gpl-v3'`, builder methods), the frontmatter schema with permanent 8-char IDs and the `| HyperFormula` metaTitle suffix, link conventions, the Excel / Google Sheets trademark notice text, the sidebar registration step, the Starlight-native asides / live-runner HTML pattern, and a PR checklist. - `docs/AGENTS.md`: symlink to `CLAUDE.md` so both naming conventions resolve to the same file. - `docs/README-EDITING.md`: practical reference -- frontmatter long-form, Starlight aside examples, the live-runner HTML pattern with file layout, line highlighting in code blocks, and sidebar registration. - `docs/README-DEPLOYMENT.md`: deployment reference -- Netlify build command, the `docs:build` pipeline (`bundle-all` → `typedoc:build-api` → `npm ci && npm run build`), GitHub Actions CI verification, and the auto-generated `_redirects` map.
The `starlight-page-actions` plugin defaults to rendering its action row directly under the page heading. Match the Handsontable docs UI by moving the actions (Copy Markdown, Open in ChatGPT, Open in Claude) into the right-hand sidebar, below the "On this page" table of contents. Adds two Starlight component overrides: - `PageTitle.astro`: renders only the default page title and drops the plugin's button row. The plugin's override is suppressed because user- configured overrides win over plugin-supplied ones in Starlight. - `PageSidebar.astro`: renders the default TOC, then appends a flat action list styled to match the right-sidebar typography. The Copy Markdown handler reuses the plugin's `.md` companion routes and shows a transient checkmark on success.
✅ Deploy Preview for hyperformula-dev-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
CI flagged two issues on PR #1686: - The `build-docs` GitHub Actions job and the Netlify deploy preview both failed because Astro 6 requires Node >=22.12.0, but every Node pin in the docs setup specified 20. Bump `.nvmrc`, the docs `engines.node` constraint, the `build-docs.yml` job matrix, the Netlify `NODE_VERSION`, and the "Node 20" mentions in the README / CLAUDE.md / README-DEPLOYMENT to 22 (22.12 for the engines pin). - CodeQL flagged `cleanTitleText()` in `vuepress-preprocessor.mjs` for incomplete multi-character sanitization (`js/incomplete-multi-character-sanitization`). A single pass of `/<[^>]+>/g` could leave a `<script>` substring behind for inputs like `<sc<script>ript>`. Iterate the strip to a fixed point so nested tags collapse fully. The downstream consumer (Starlight rendering a YAML `title:`) already escapes HTML, so this is defence-in-depth, but the warning is correct in principle.
Performance comparison of head (0509e26) vs base (79f2f15) |
The Netlify deploy preview for #1686 kept failing with "Node.js v18.20.8 is not supported by Astro" even after setting NODE_VERSION = "22" in netlify.toml's [build.environment]. The deploy log showed Netlify resolving Node from the root .nvmrc ("v18") rather than honoring the netlify.toml env var. Bump .nvmrc to 22 so both sources agree. The HyperFormula library is already exercised on Node 20/22/24 by .github/workflows/build.yml, so bumping the local-dev default to 22 is consistent with what CI already tests.
Astro builds the site with `base: '/docs'`, so generated HTML references `/docs/_astro/*`, `/docs/guide/*`, etc. In production the canonical URL `hyperformula.handsontable.com/docs/` is served by a reverse proxy that strips the `/docs` prefix before forwarding to the Netlify project, so the prefix in the HTML resolves to the right files. Netlify deploy previews (and the netlify.app subdomain in general) don't sit behind that proxy, so `/docs/`-prefixed paths 404 — only the home page rendered, and even then without styles or images because every `/docs/_astro/*` URL came back as a 404. Add a wildcard rewrite to netlify.toml so the preview mimics the production proxy: any `/docs/<path>` request is served from `<path>` in the publish directory. The Astro-generated `_redirects` file is processed first (so the legacy `.html` → clean URL redirects still match), then this catch-all rewrites everything else.
The version pill in the docs header rendered as "v0.0.0" on the Netlify deploy preview even though the same code returned the correct "3.3.0" locally. The cause was the brittle `../../..` arithmetic used to find the library root: in some build environments (apparently Astro's build container on Netlify), `import.meta.url` resolves through a location that's one directory deeper than expected, so three parent hops landed inside `docs/` instead of at the repo root. That made the fallback read `docs/package.json` (version `0.0.0`) instead of the library's `package.json`. Replace the path arithmetic with an upward walk that stops at the first `package.json` whose `name` is `hyperformula`. This is robust to any build-cache layout. While here, also fall back gracefully when the UMD bundle exists but is missing individual fields.
|
@sequba @sl01k , this is still a draft, but it's getting close. Here's the latest DP if you want to have a look: |
The toolbar's horizontal divider was constructed from `border-top` on each `.hf-nav__link` element, so it only rendered where the framed nav tabs sat. To the left of the first tab and to the right of the Support dropdown, the line broke off and left visible gaps. Mirror Handsontable's `.header-row-2::before` pattern: add a single full-viewport `::before` pseudo-element to `.hf-header__row--nav` so a continuous 1px line stretches edge-to-edge. The per-tab top borders sit at the same Y-coordinate and overlap the pseudo-element where tabs exist; the pseudo-element bridges the gaps elsewhere. The active-tab brand-blue frame and z-index stacking are unchanged.
Brings in `00e5c730a` "Clean up in-repo dev docs (HF-65) (#1682)" which adds root-level `DEV_DOCS.md`, `AGENTS.md`, `.cursor/rules/main.mdc`, and re-points root `CLAUDE.md` / `CONTRIBUTING.md` as symlinks. Those files live at the repo root and govern library development, separate from the docs-site governance files this PR adds under `docs/` (`docs/CLAUDE.md`, `docs/AGENTS.md`, `docs/README-EDITING.md`, `docs/README-DEPLOYMENT.md`). Git's rename detection auto-applied develop's edits to `docs/guide/building.md` to the migrated location at `docs/src/content/docs/guide/building.md` — no conflicts.
…border The continuous `::before` divider line was already in place, but two layout issues remained: 1. The per-tab `border-top` sat ~0.5rem below `::before` because `.hf-header__row` (the shared row class) applies `padding: 0.5rem 1rem` and `align-items: center` to every row. That offset rendered as a doubled line where the tabs were. 2. Inside `header.header`, Starlight's `padding-block` reserved ~0.75rem of dead space below `.hf-header`, so the per-tab vertical borders and hover backgrounds stopped short of the visible `border-bottom: 1px solid hairline-shade` boundary. Three targeted overrides — modeled on Handsontable's `.header-row-2` layout: - `.hf-header__row--nav` drops vertical padding, sets `align-items: stretch`, `gap: 0`, and `min-height: 0`. Nav links now sit flush against the row's top so their `border-top` overlaps `::before` perfectly (single line). - `.hf-header` changes `grid-template-rows` from `auto auto` to `auto 1fr` so row 2 absorbs the remaining vertical track height rather than leaving it empty. - `header.header` overrides Starlight's `padding-bottom` to `0` so `.hf-header__row--nav` reaches the header's actual bottom border. The per-tab vertical lines and hover backgrounds now extend the full height of the toolbar, matching Handsontable's design.
|
@qunabu @sequba , this is ready for review now |
Starlight constructs the "Edit this page" URL by appending `entry.filePath` (the source file path relative to the Astro project root, which is `docs/`) to `editLink.baseUrl`. With the previous value ending in `docs/content/`, the resulting URL would have been `.../edit/develop/docs/content/src/content/docs/guide/<slug>.md` — a path that does not exist in the repository. The `docs/content/` suffix was carried over from Handsontable's `astro.config.mjs`, where guides actually live at `docs/content/` via a symlink. In HyperFormula the sources live directly at `docs/src/content/docs/`, so the base needs to point at `docs/`. No "Edit on GitHub" link is currently rendered (my Footer / PageTitle / PageSidebar overrides don't include one, and `starlight-page-actions` doesn't expose an edit action), so the misconfigured URL was latent. This fix removes the trap before anyone adds the button back.
Brings in two content-only commits that landed on develop after the last sync: - 0e047ee docs: fix SSR section framing in React integration guide (#1688) - 79f2f15 docs: rewrite Vue integration guide around markRaw pattern (#1689) Both touch files we migrated from `docs/guide/` to `docs/src/content/docs/guide/`. Git's rename detection auto-applied the develop-side edits to the new locations — no conflicts. GitHub had flagged the PR as CONFLICTING because its mergeability check hadn't recomputed since develop's last push; pushing this merge clears that flag.
Co-authored-by: GreenFlux <GreenFlux@users.noreply.github.com>
Caught by Cursor Bugbot on PR #1686. `astro.config.mjs` gates the Google Tag Manager snippet on `process.env.BUILD_MODE === 'production'`, but nothing in the Netlify config or the GitHub Actions docs-build workflow was setting the variable — so the production deploy of the docs site would silently ship without GTM, dropping analytics that the previous VuePress site had always loaded. Setting `BUILD_MODE = "production"` under `[context.production.environment]` is the right Netlify-native pattern: it only applies to deploys from the production branch, leaving PR deploy previews and branch deploys with `BUILD_MODE` unset so analytics doesn't fire on non-canonical URLs.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 0509e26. Configure here.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #1686 +/- ##
========================================
Coverage 97.16% 97.16%
========================================
Files 176 176
Lines 15322 15322
Branches 3356 3356
========================================
Hits 14887 14887
Misses 427 427
Partials 8 8 🚀 New features to boost your workflow:
|
|
@sequba ready for review |

Status
Draft. Asking for an early structural look — happy to split this into separate PRs if reviewers prefer:
src/content/docs/)CLAUDE.md,README-EDITING.md,README-DEPLOYMENT.md)starlight-page-actionsfeature + the right-sidebar UI placementCurrently three logical commits, easiest to review per-commit:
e227a2479— Migrate documentation from VuePress to Astro Starlightec5c7d126— Add documentation authoring standards and editing/deployment guides510fb6d5a— Move page action buttons into the right sidebarSummary
Replaces the VuePress 1.x docs site with Astro 6 + Starlight 0.38. The previous
docs/.vuepress/configuration stays in place for now since it's no longer wired into the build pipeline — a separate cleanup will remove it.Site structure
docs/src/content/docs/and are tracked in git (no longer regenerated on every build).docs/src/content/docs/api/is the only path still processed byscripts/generate-content.mjs(it normalizes TypeDoc output)._redirectsmap preserves the legacy/docs/guide/<slug>.html→ clean URLs and is auto-generated.Custom Starlight component overrides
Head(Inter font, example-runner client script),Header(two-row HT-style nav with logo + version pill, search, GitHub stars, primary nav, support dropdown),Footer(link grid + social row),ThemeSelect(sun/moon toggle),PageTitle+PageSidebar(moves the Copy Markdown / Open in ChatGPT / Open in Claude buttons into the right sidebar under "On this page", matching the HT docs layout).Plugins
starlight-theme-rapide(typography + chrome) andstarlight-page-actions(page-action buttons + auto-generated.mdcompanions next to each.html).Authoring governance
docs/CLAUDE.md(symlinked fromdocs/AGENTS.md) — Diátaxis-based authoring rules, frontmatter schema with permanent 8-char IDs, code-example conventions (licenseKey: 'gpl-v3', builder methods), Excel/Google Sheets trademark callouts, and a PR checklist.docs/README-EDITING.md— practical reference for Starlight-native asides, the live-runner HTML pattern, and sidebar registration.docs/README-DEPLOYMENT.md— Netlify build chain,docs:buildpipeline, GitHub Actions CI verification.Build wiring
netlify.tomlrunsnpm run docs:buildfrom the repo root and publishesdocs/dist..github/workflows/build-docs.ymlruns the same command on PRs and pushes tomaster,develop,release/**.docs:buildscript chains:bundle-all→typedoc:build-api→cd docs && npm ci && npm run build.Test plan
::: exampleblock (e.g./docs/guide/basic-usage), and an API ref page (e.g./docs/api/classes/hyperformula).mdcompanion, Open in ChatGPT / Open in Claude prefill a prompt.htmlURL redirects in_redirectsresolve (e.g./docs/guide/basic-usage.html→/docs/guide/basic-usage)npm run docs:buildfrom the repo root completes without errorsKnown follow-ups (not in this PR)
docs/.vuepress/directoryCLAUDE.md§9Note
Medium Risk
Large docs-platform swap affects production URLs, build/CI (
docs:build, Node 22), and all published guide content; runtime library code is largely untouched but deploy breakage would impact every reader.Overview
This PR replaces the VuePress docs site with Astro 6 + Starlight under
docs/, served at/docswith Node 22 (root anddocs/.nvmrc).Content and build: Guide pages, homepage, and 404 move to
docs/src/content/docs/(tracked in git) with Starlight markdown, inlinehf-exampleblocks, and updated internal/docs/...links. Legacydocs/guide/*.mdVuePress sources (including::: example/@[code]blocks) are removed from that tree.scripts/generate-content.mjsnow mainly normalizes TypeDoc output intosrc/content/docs/api/and writespublic/_redirectsfor legacy.htmlURLs. Root.eslintignoreignores the wholedocs/package.Site UX:
astro.config.mjswires Rapide theme, sitemap, expressive code plugins, custom Header/Footer/Head/ThemeSelect, andstarlight-page-actionswith PageTitle/PageSidebar overrides so Copy Markdown / ChatGPT / Claude actions sit in the right sidebar.test-build.mjsadds post-build checks (link integrity, VuePress token leaks, examples, Pagefind).Governance: Adds
CLAUDE.md/AGENTS.md,README-EDITING.md,README-DEPLOYMENT.md, and rewritesdocs/README.mdfor the new workflow (npm run devindocs/,docs:buildfrom repo root). Removes the old VuePressapi-ref-readme.mdtemplate.Reviewed by Cursor Bugbot for commit 0509e26. Bugbot is set up for automated code reviews on this repo. Configure here.