Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
e608c4d
chore(scripts): add extract-public-api.js for cross-repo contract che…
marcin-kordas-hoc May 28, 2026
34c32d5
fix(scripts): make extract-public-api.js lint-clean under project ESL…
marcin-kordas-hoc May 28, 2026
760ab4a
docs(specs): add HF-154 agent-friendly docs design spec
marcin-kordas-hoc May 31, 2026
25a4097
docs(specs): harden HF-154 spec after brutal-honesty review
marcin-kordas-hoc May 31, 2026
7ff9263
docs(plans): add HF-154 implementation plan
marcin-kordas-hoc May 31, 2026
c43e81a
feat(docs): add md-companions plugin for .md exports and llms-full.txt
marcin-kordas-hoc May 31, 2026
88827ee
feat(docs): add Copy Markdown button global component
marcin-kordas-hoc May 31, 2026
9613c94
feat(docs): add Set up your coding agent page and interactive wizard
marcin-kordas-hoc May 31, 2026
c8f3d5d
docs: add llms.txt and link llms-full.txt from robots.txt
marcin-kordas-hoc May 31, 2026
4e8a008
fix(docs): handle :::example and any unknown container types in md-co…
marcin-kordas-hoc May 31, 2026
d3fff0c
feat(docs): wire md-companions plugin, Copy Markdown button, and setu…
marcin-kordas-hoc May 31, 2026
89f27b2
fix(docs): address code-review findings in HF-154 components
marcin-kordas-hoc May 31, 2026
5bb49aa
Merge remote-tracking branch 'upstream/develop' into feat/hf-154-agen…
marcin-kordas-hoc Jun 2, 2026
c429eeb
docs(hf-154): add context7.json + GitMCP/Context7 agent doc-access se…
marcin-kordas-hoc Jun 8, 2026
f49d15b
test(docs): run md-companions strip test in CI (HF-154)
marcin-kordas-hoc Jun 22, 2026
062625f
docs: remove internal HF-154 plan/spec from public docs
marcin-kordas-hoc Jul 1, 2026
516d5ad
docs(hf-154): drop out-of-scope extract-public-api.js + its eslint ca…
marcin-kordas-hoc Jul 9, 2026
d47ac0f
Merge remote-tracking branch 'upstream/develop' into feat/hf-154-agen…
marcin-kordas-hoc Jul 9, 2026
ddfa8f0
docs(hf-154): point CHANGELOG entry at upstream PR #1703
marcin-kordas-hoc Jul 9, 2026
c0cc9c5
ci(docs): bump Netlify deploy Node 18 -> 22 to match docs CI
marcin-kordas-hoc Jul 9, 2026
01072d5
docs(hf-154): honest Copy-Markdown label + drop inert robots.txt comm…
marcin-kordas-hoc Jul 9, 2026
f0b5b28
fix(hf-154): strip inline Vue components (e.g. <Badge/>) from .md corpus
marcin-kordas-hoc Jul 9, 2026
c0f1ac6
refactor(hf-154): dedupe clipboard helper + strip paired block-compon…
marcin-kordas-hoc Jul 9, 2026
f609b42
fix(hf-154): address review findings (strip edge-cases, corpus comple…
marcin-kordas-hoc Jul 9, 2026
76c3f14
fix(hf-154): make copyToClipboard fallback truly non-throwing
marcin-kordas-hoc Jul 10, 2026
daed5f4
docs(hf-154): clarify per-page .md wording (page URL, not any URL)
marcin-kordas-hoc Jul 10, 2026
c41eed6
fix(hf-154): address Cursor Bugbot review (corpus fidelity + root dis…
marcin-kordas-hoc Jul 12, 2026
72b07f6
Merge remote-tracking branch 'upstream/develop' into feat/hf-154-agen…
marcin-kordas-hoc Jul 12, 2026
c7502f7
fix(hf-154): keep {{ }} interpolations verbatim instead of wiping them
marcin-kordas-hoc Jul 12, 2026
6412a33
fix(hf-154): exclude docs/.vuepress from Context7 indexing
marcin-kordas-hoc Jul 12, 2026
861c816
fix(hf-154): strip inline [[toc]] markers too
marcin-kordas-hoc Jul 12, 2026
c84f78f
fix(hf-154): point llms.txt Guide link at /docs/ (static, resolves)
marcin-kordas-hoc Jul 12, 2026
12204f8
fix(hf-154): readable wizard snippet (dark text, wrap long URLs)
marcin-kordas-hoc Jul 12, 2026
59698ab
fix(hf-154): drop dangling empty heading + normalise blank lines in c…
marcin-kordas-hoc Jul 12, 2026
1836e1e
test(hf-154): add corpus-level invariant tests for the stripper
marcin-kordas-hoc Jul 12, 2026
2fca6ee
style(hf-154): match wizard snippet to VuePress code blocks (dark)
marcin-kordas-hoc Jul 13, 2026
e22dbaf
docs(hf-154): correct MCP mechanism wording (GitMCP=repo, Context7=do…
marcin-kordas-hoc Jul 13, 2026
f154a05
fix(hf-154): rebase root-relative links + fence-aware container close
marcin-kordas-hoc Jul 13, 2026
789a2ed
fix(hf-154): make link rebase fence-aware
marcin-kordas-hoc Jul 13, 2026
ba78f3f
fix(hf-154): absolutize links in llms-full.txt corpus
marcin-kordas-hoc Jul 13, 2026
f68804a
fix(hf-154): run container bodies through inline cleanup too
marcin-kordas-hoc Jul 13, 2026
bcb08da
Merge branch 'develop' into feat/hf-154-agent-friendly-docs
sequba Jul 15, 2026
363a5e2
Remove tests/docs
sequba Jul 15, 2026
c66c64b
Add guidelines about docs to DEV_DOCS
sequba Jul 15, 2026
e63c344
Revert eslint config changes
sequba Jul 15, 2026
765a5a5
Add DOCS_CONTENT_GUIDE
sequba Jul 15, 2026
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
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,6 @@ module.exports = {
rules: {
'@typescript-eslint/no-non-null-assertion': 'off',
}
}
},
],
}
5 changes: 5 additions & 0 deletions DEV_DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Canonical reference for everyone working on the HyperFormula source code: mainta
- **[Test suite](test/README.md)** &mdash; smoke tests and how to attach the private test suite
- **[Public docs portal](https://hyperformula.handsontable.com/docs)** &mdash; main documentation
- **[Docs README](docs/README.md)** &mdash; how to run the docs portal locally
- **[Docs content guide](DOCS_CONTENT_GUIDE.md)** &mdash; how to create and edit docs content
- **[Changelog](CHANGELOG.md)**
- **[Pull request template](.github/pull_request_template.md)**

Expand Down Expand Up @@ -90,6 +91,10 @@ A single pull request should contain an atomic self-contained functional change
- All changes to the production code must be covered by automatic tests kept in the `test/` directory.
- Each test case must be very simple and focused on a single assertion. Don't use loops, conditionals, or other control flow statements in test cases.

## Documentation

- Follow the [documentation content guide](DOCS_CONTENT_GUIDE.md) when creating or editing docs (writing style, language, and how to structure guides).

## How to add a new function

Adding a built-in function is similar to adding a [custom function](docs/guide/custom-functions.md), so that guide is a useful reference for the function-implementation patterns (argument metadata, return types, array handling). The built-in flow on top of that is:
Expand Down
262 changes: 262 additions & 0 deletions DOCS_CONTENT_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
# Documentation content guide

## The one principle

**Every page and every section is retrieved and read in isolation, out of order,
by a reader with zero prior context.** RAG systems pull one chunk at a time; a
search result or an AI answer may show only part of a page. So:

> If the answer to a question is not present on a single page, in plain text, in a
> self-contained place — it effectively does not exist.

Write so any one page fully answers one real question. Everything below serves this.

The good news: this is just *good documentation*. The same clarity that helps the AI
helps humans and search. You are not gaming an algorithm — you are writing clearly.

---



## Project context

- **Product:** HyperFormula — an open-source, headless spreadsheet and formula
engine written in TypeScript. It parses and evaluates ~400 Excel/Google
Sheets–compatible functions. It has **no UI**. It runs in the browser or Node.js.
- **Sibling product:** Handsontable (the data grid). HyperFormula is maintained by
the same team but is a **separate product** — do not blur the two.
- **Docs source:** Markdown in the `docs/` folder of the `handsontable/hyperformula`
repo. Guide pages live at `docs/guide/<slug>.md`; the landing page is
`docs/index.md`; API reference under `docs/api/` is **generated from source code
TSDoc — do not hand-edit it**, improve the code comments instead.
- **Toolchain:** VuePress 1.9.10 (static site generator). Pages support YAML
frontmatter, `::: tip / warning / danger` containers, and fenced code blocks.
- **Runnable demos:** hosted on StackBlitz (`handsontable/hyperformula-demos`),
linked per version branch (e.g. `3.3.x`).

---



## What to write (coverage & gap prioritization)

Optimization cannot recover a page that doesn't exist. Coverage comes first.

1. **Write the "obvious" pages.** The journeys teams skip because they feel too
basic are the ones users ask first: installation (client- and server-side), basic
usage, configuration options, the **license key** (a top gotcha), a first working
formula, reading/writing cell values, named expressions, custom functions.
2. **Prioritize by real demand, not intuition.** Rank what to write next using:
- Support tickets and GitHub issues from the last quarter — each recurring one
should map to a single findable page. If it doesn't, that's your next page.
- The docs AI assistant / search logs — repeated questions signal a missing or
hard-to-find page; questions that span sections signal an organization problem;
requests for examples signal thin practical guidance.
- Start with the boring, high-traffic paths before advanced/edge topics.
3. **Prefer less, but better.** Quality beats coverage for retrieval. Delete or
archive outdated tutorials, deprecated-feature guides, near-duplicate pages, and
thin placeholder stubs. Stale content competes with correct content and the model
cannot tell which is current.
4. **Never contradict yourself across pages.** Two pages that disagree are worse than
one correct page, because retrieval may surface either. When you add or change a
fact, grep the docs for the old statement and fix every occurrence.
5. **Document errors with their exact text.** Users (and assistants) search by
pasting the literal error string. For each common error, use the exact message as
a heading, then give the cause and the fix:
`### Error: "Named expression 'X' already exists"` → why it happens → how to
resolve. Reference HyperFormula's error types (`#REF!`, `#VALUE!`, `#NAME?`, etc.)
by their real symbols.

---



## How to structure a page

Treat **every page as page one.**

1. **Open with scope and prerequisites.** The first lines state what the page covers,
which version it applies to, and what the reader must already have done. Example
opener: "This guide covers custom functions in HyperFormula. You need HyperFormula
installed and a working instance (see Basic usage)."
2. **Name the subject in the body, not just the title.** Write "HyperFormula's
`buildFromArray` method…", not "the `buildFromArray` method…". A retrieved chunk
must carry a clear signal of what product/feature it belongs to, because the title
and breadcrumb may be stripped away. Don't overdo it — once per section is enough.
3. **Front-load the essential context**, then the details. A reader who sees only the
first chunk should still get the core answer.
4. **Self-containment beats DRY — resolve the tension deliberately.** RAG wants
repetition; engineering instinct wants "don't repeat yourself." For docs content,
**self-containment wins**:
- Repeat the small essential context a reader needs to act here (e.g. that an
instance is created with a `licenseKey`), even if it appears on other pages.
- **Link** to another page for *depth* or *related* topics — never make the reader
leave this page to understand or complete *this* task.
- Rule of thumb: if removing a link would make the current task impossible to
finish, that information belongs on the page, not behind the link.
5. **Author the frontmatter.** Every page gets a specific `title` and a one-sentence
`description` that names the concept (this becomes the meta description and helps
scoping). Titles describe the *thing*, not the category: "WebSocket configuration"
→ good; "Configuration" → bad. Give the file a meaningful slug
(`custom-functions.md`, not `page3.md`).

---



## How to structure sections (chunking)

1. **One purpose per section.** Each `##`/`###` answers exactly one question. Don't
mix installation, configuration, and troubleshooting under one heading — split
them so each chunk retrieves cleanly. Keep procedures ("how to…") separate from
reference ("what the options are").
2. **Keep related facts physically close.** A constraint and its consequence go in
the same paragraph or adjacent ones, so chunking can't separate them. Bad: state
a limit in section 1 and its handling in section 4. Good: state both together.
3. **Kill backward references.** Delete "as mentioned above," "now that you've done
X," "with everything configured." These break the moment the section is read
alone. Replace with the explicit context.
4. **Use a real heading hierarchy.** `#` once (page title), then `##` → `###`, in
order, reflecting true topic structure. Headings are descriptive and specific.
Never skip levels or use a heading purely for visual size.
5. **Never leave long, undivided prose — make it granular.** Break any long stretch
of text into smaller, focused pieces under their own `##` or `###` headings. A
wall of text buries several distinct answers in one chunk and retrieves poorly.
Each subsection should be short enough that its heading accurately describes
everything beneath it. If a section runs past a few paragraphs, or starts drifting
into a second idea, split it and give the new part its own descriptive H2/H3.
Prefer more, well-labeled subsections over fewer long ones.
6. **Give each variation its own section.** When documenting multiple methods,
modes, or versions (e.g. `buildFromArray` vs `buildFromSheets` vs `buildEmpty`),
write a labeled section per variation rather than interleaving them.

---



## Language & terminology

1. **Write plainly.** Aim for a ~6th–7th-grade reading level: short sentences, one
idea each. Simple prose reduces both human confusion and AI misinterpretation.
2. **Use active voice.** "HyperFormula evaluates the formula," not "the formula is
evaluated."
3. **One term per concept, everywhere.** Pick the canonical term and never drift.
HyperFormula-specific vocabulary to keep consistent: *instance* (not "object"),
*sheet*, *cell address*, *named expression*, *formula*, *custom function*,
*config/options object*. Don't alternate "config" / "settings" / "options" for
the same thing.
4. **Keep a glossary and spell out acronyms on first use** on each page — "Abstract
Syntax Tree (AST)", "Cyclic Reference (CREF)". Link related glossary terms.
5. **One language per page.** Write docs in English; do not interleave other natural
languages. (This is about prose, not about supporting HyperFormula's 17 formula
locales — those are a documented feature.)
6. **State everything explicitly; assume no prior knowledge.** List prerequisites
inside the procedure instead of assuming setup. If a step depends on an external
tool or concept, give one line of context or a link. The AI cannot infer what you
didn't write.

---



## Code examples

Code is the primary content of these docs. Models reproduce complete examples well
and hallucinate the parts you omit.

1. **Make every example complete and runnable.** Include imports, instance creation
with the `licenseKey` (a required, commonly-missed step —
`HyperFormula.buildEmpty({ licenseKey: 'gpl-v3' })`), the data setup, the call,
and how to read the result. No fragments that assume invisible surrounding code.
2. **Show where code lives when structure matters** — a filename comment
(`// src/calc.ts`) or a short file tree for multi-file examples, so the reader can
place it correctly.
3. **Tag every code block with its language** (````javascript`, ````ts`,
````bash`). Never use an untagged fence.
4. **Use consistent, correct API shapes.** Cell addresses use a fixed property order
every time — `{ sheet, row, col }` — don't reorder it between examples. Prefer the
real method names (`setCellContents`, `getCellValue`, `addSheet`, `getSheetId`,
`addNamedExpression`). When a runnable demo exists, link the StackBlitz for the
matching version branch.
5. **Show the correct way; show a wrong way only when it prevents a frequent
mistake.** If you include an anti-pattern, label it clearly ("Don't do this —
it throws because…") so it can't be mistaken for a recommendation.

---



## Visuals, tables & the "why"

1. **Never put information only in an image, diagram, or video.** Assistants can't
read pixels reliably. Put the same information in text next to the visual. Add a
descriptive caption to every image.
2. **Write UI/interactive flows as numbered, literal steps** — name the exact method,
option, or button and what it does at each step, so the steps stand without the
screenshot.
3. **Keep diagrams simple:** one diagram per concept, readable labels, no vertical
text, and represent multi-step workflows as a numbered list *in addition to* any
flowchart.
4. **Tables: simple and self-describing.** Real header rows, one fact per cell, each
row understandable on its own. Avoid merged cells or layouts where meaning comes
from visual position — convert those to structured lists or sub-sections. If a
table is only decorative grouping, use headings instead.
5. **Explain the "why," not just the "what."** Document intent, design decisions, and
when to use a pattern — the context source code alone doesn't convey. Call out
edge cases, gotchas, and common mistakes with their resolution (e.g. why
`buildEmpty` needs a `licenseKey`, when to use named expressions vs. cell
references, precision/rounding caveats).

---



## VuePress conventions (so your output fits the site)

- Start each page with frontmatter:
```yaml
---
title: Custom functions
description: Register and use your own functions in HyperFormula.
---
```
- Use containers for asides: `::: tip`, `::: warning`, `::: danger` … `:::`. Put
essential steps in the body, not hidden inside a tip.
- Use **relative links** between guide pages (`./named-expressions.md`) and link to
API symbols under `/docs/api/`.
- Leave the auto-generated "Help us improve this page" edit link and sidebar to
VuePress — don't hand-write navigation.
- Don't hand-edit `docs/api/**` — it's generated from TSDoc in the source.

---




## Self-review checklist (run before finishing any page)

- [ ] **Stands alone:** a reader who lands here cold, seeing only this page, can
```
finish the task without opening another page.
```
- [ ] **One question per section**, descriptive headings, hierarchy in order.
- [ ] **No walls of text:** long prose is broken into granular H2/H3 subsections,
```
each short enough that its heading covers everything under it.
```
- [ ] **Product named** in the body; no bare "the library/the method/the grid."
- [ ] **No backward references** ("as above," "now that you've…").
- [ ] **Prerequisites stated explicitly**; nothing assumed.
- [ ] **Terminology consistent** with the canonical terms; acronyms expanded once.
- [ ] **Every code block** is language-tagged, complete, includes the `licenseKey`,
```
and would actually run; cell-address property order is `{ sheet, row, col }`.
```
- [ ] **No info trapped in images/tables**; visuals have text equivalents and captions.
- [ ] **Frontmatter** has a specific `title` and a one-sentence `description`.
- [ ] **No contradiction** with other pages; old facts updated everywhere.
- [ ] **"Why" is covered:** intent, when-to-use, and known gotchas — not just syntax.
- [ ] Would an AI assistant quoting *only this page* give a correct, complete answer?
```
If not, fix the page.
```
14 changes: 14 additions & 0 deletions context7.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"$schema": "https://context7.com/schema/context7.json",
"projectTitle": "HyperFormula",
"description": "Headless, Excel-compatible spreadsheet engine in TypeScript — parses and evaluates ~400 functions in the browser or Node.js. In-process library (no REST API).",
"folders": ["docs"],
"excludeFolders": ["docs/.vuepress", "docs/api"],
"rules": [
"HyperFormula is an in-process library, not a REST API — there is no HTTP endpoint or base URL.",
"Public API cell addresses are 0-indexed: { sheet, col, row }.",
"There is no #CALC! error type.",
"EmptyValue is exported as a Symbol, not null/undefined.",
"A license key is required when constructing the engine (use 'gpl-v3' for open-source use)."
]
}
Loading
Loading