docs: reorganize the documentation around reader intent - #3016
Open
vmaerten wants to merge 21 commits into
Open
Conversation
The guide had grown to 2950 lines and 27 sections, a fifth of the whole documentation in one file, and it was where every new feature ended up. Each section is now its own page. Two sections were rearranged rather than moved verbatim. "Prevent unnecessary work" covered two different questions - whether the work is already done (fingerprints, status) and whether it should happen at all (preconditions, if, requires) - so it becomes three pages. "Running a remote Taskfile" is dropped entirely: its prose, its danger admonition and its three samples already appeared word for word in the Remote Taskfiles page. Every other heading keeps its exact text, so section anchors still resolve; only the page they live on changed.
/docs/guide keeps its URL and becomes a grouped index of the pages the guide was split into, so the many links to it in issues, blog posts and Stack Overflow answers still land somewhere useful. Their fragments need more than that. Netlify never receives the part of a URL after the #, so a _redirects rule cannot route an anchor; GuideRedirect.vue reads location.hash and resolves it in the browser against a table of the 72 anchors the old page defined. Every entry was checked against the anchors VitePress actually emits.
/docs was not a page: a Netlify rule caught it and sent visitors to /docs/guide, so the section had no entry point of its own for the nav, the sitemap or llms.txt to point at. It is now a short hub that routes by intent - install it, learn it, look something up, keep up - rather than a second copy of the sidebar. The _redirects rule stays as it is: Netlify only applies an unforced rule when no static file matches, so it goes quiet here while continuing to serve the released channel, which has no such page yet.
Eight pages were missing a title, a description or both. The description feeds two things at once: the meta tag the DocSearch crawler reads, and the entry a page gets in llms.txt. Without one, a page is indexed and listed with whatever text happens to come first. Every page under docs/ now carries both.
Three conventions were in use: relative with .md, absolute without an extension, and relative without one. Only the first is resolved and verified by VitePress at build time, which makes it the only form that cannot rot silently - and with no link checker in CI, that check is the only one there is. Also fixes two links that were already wrong: remote-taskfiles.md reached for ../docs/reference from inside docs/, and the security incident response plan pointed at ../security/ from inside security/.
Markdown link definitions are file-scoped. The three the guide used sat at the very bottom of the file, inside the last section, so the split handed all of them to watch.md - which uses none - and left dependencies.md and variables.md rendering [`.taskrc.yml`][config] and [templates][templating-reference] as literal text. Each definition now lives on the page that uses it. [gotemplate] is dropped: nothing referenced it, in the old guide either.
The nav is shared by both channels, so pointing Docs at /docs/ sent taskfile.dev to a page that only exists on next until cmd/release promotes it. The _redirects rule that used to catch this is written /docs, without the trailing slash the nav emits, so it would not have saved the link.
Chosen after building this grouping and a product-area one side by side and comparing them on the rendered site. The sidebar was a flat list of 16 entries in which contributor material sat at the same level as user material. It is now five groups named for what the reader is doing: Getting Started, Guide, Reference, Project, Contributing. The guide pages move under /docs/guide/ so the URLs say the same thing as the navigation. Only the pages created by the split are moved. Everything else keeps its URL, because src/public/_redirects is shared between the two channels and any rule added here would take effect on the released site, which still serves the old structure. The DocSearch crawler puts the active sidebar section into hierarchy.lvl0, so these five labels become the breadcrumbs on every search result.
The guide says how to declare each kind of variable but never says which
one wins, and that is what people file issues about: seven of them are
about precedence or evaluation order, one titled "Documentation: Clarify
dotenv file precedence when multiple files are specified".
The page states the order once, and guide/variables.md now links to it
instead of carrying its own list. Two owners of the same rules would
drift, and nothing in CI compares the docs to the Go code.
Every claim was checked by running the built binary, not read off the
source. Three are worth calling out because they contradict what people
expect:
- A task's own vars cannot be overridden from the command line;
`task greet NAME=x` loses to a `vars:` on the task.
- `vars:` on an `includes:` entry are defaults, not overrides: the
included Taskfile's own `vars:` are applied after them and win.
- Global variable names are shared across every Taskfile in a run, so
a name declared in both the entrypoint and an included file resolves
to the included one, even for entrypoint tasks.
Three issues ask about execution order (`the order of task under deps is random`, `Glob-based matching and sequential or parallel execution`, `Default concurrency`), and two of the four FAQ entries are really questions about the execution model rather than about a procedure. The guide is organised one feature per page, so nothing owns the part that cuts across them: what runs together, what waits, and in which order cleanup happens. Behaviour verified by running the built binary: deps start together and all finish before cmds; a task reference inside cmds runs at its position; `run: once` collapses a shared dependency from two executions to one; deferred commands run in reverse order of declaration.
vitepress-plugin-llms names its Markdown output by running the file through VitePress's own `rewrites`. On the object form it matches `<channel>/:path*`, gets `:path*` back as an array of segments, and compiles it without separators - so every page landed at the root as dist/docsreferencecli.md instead of dist/docs/reference/cli.md, and the relative links inside them pointed nowhere. Expressing the same rewrite as a function takes the plugin's other code path and keeps the segments. The Markdown mirror is now addressable by appending .md to a page's URL, which is what /llms.txt claims. It also fixes the table of contents as a side effect: with paths that match the sidebar again, llms.txt groups pages under their section instead of listing all of them under a single "Other".
/agents is a compact map of the documentation plus the ten semantics an agent is most likely to get wrong when writing a Taskfile: vars against env, what deps guarantee, that each command gets its own shell, status against preconditions, and the reverse order of defer. Each claim was checked by running the built binary. Two of them are counterintuitive enough to be worth stating outright - a task's own vars cannot be overridden from the command line, and vars on an includes entry are defaults rather than overrides. Links are relative so VitePress checks them at build; they resolve the same way for an agent reading the raw /agents.md.
The DocSearch crawler builds hierarchy.lvl0 - the breadcrumb shown on every search result - from whichever sidebar link is active in the DOM. That reads the navigation through the theme's markup, so it breaks quietly on a theme upgrade and cannot be reviewed from this repo, where the crawler configuration does not live. Each page now states its own section and documentary type, and the crawler can be pointed at meta[name="docsearch:section"] instead. The frontmatter is derived from sidebar/next.ts rather than written by hand, since the sidebar is what defines a section; the two cannot drift. 46 pages carry it. The only pages left without one are the two authoring templates, which are already kept out of llms.txt and the sitemap.
The clean task removed ./vitepress/dist. The build writes to ./.vitepress/dist, with a leading dot, so the task has never deleted anything since it was written.
"[Map Variables][map-variables]" had no matching definition, so it rendered as literal text with the brackets showing. The post shipped that way in 2024 and the same text is in both channels. Map support has landed since, so the reference now points at the section that documents it.
List entries of the form "[Link](x) — gloss" become "[Link](x): gloss". Prose uses were rewritten one at a time, since the right replacement depends on what the dash was standing in for: a colon before a list, a comma around an aside, a full stop between two sentences. Also removes the two that predate this branch, in the Nushell completions note and the remote variables table.
Both snippets referenced tasks they did not define, so copying either one and running it failed with "Task ... does not exist" and exit 201. Every other example in the docs defines what it references. The behaviour they describe was right; only the snippets were short.
Two claims were wrong, and one of them was dangerous.
The agent guidance said to keep credentials in `env:` and mark them
`secret: true` so they are masked. `secret: true` has no effect on
`env:` at all, and it never masks what a command itself prints -
testdata/secrets/Taskfile.yml has a case named for that limitation.
Following the advice would have produced Taskfiles that leak tokens into
CI logs while looking as though they did not.
The second claim was that a template sees any `env:` value. That holds
for `env:` at the root of the Taskfile, but a task's own `env:` is
assembled after the variable set is resolved, so `{{.FOO}}` renders
empty while `$FOO` works. Both pages now say which is which.
Two pages made a section of their own for subjects the guide already
owns, and gave Algolia a second set of records competing with Variables
and Dependencies for the same queries.
The resolution order, and what it means in practice, now sit in
guide/variables.md. Interleaved output, --concurrency, run: once and the
reverse order of defer join guide/dependencies.md. Nothing is dropped;
fail-fast and defer were already covered there and are not repeated.
Also quotes a command in the secret variables example. A plain YAML
scalar cannot contain ": ", so `curl -H "Authorization: {{.API_KEY}}"`
made the whole file unloadable - the example predates this branch and
was the only one of 115 Taskfile blocks in the docs that Task refuses to
parse. Quoted, it runs and prints the masked value the comment promises.
The crawler that fills the `taskfile` index has never been described
here: `git log --all -- '*algolia*' '*docsearch*'` returns nothing, so
the only copy lives in a web form. That is also why it still carries the
Docusaurus-era setup, years after the site moved to VitePress and every
selector and URL changed.
website/docsearch.config.js now holds it. It still has to be pasted into
the dashboard, which is where the crawler runs, but it can now be read,
reviewed and changed in a pull request. The write key is not in it.
Every selector was checked against the 46 built pages:
- lvl0 comes from meta[name="docsearch:section"] rather than from the
active sidebar link in the DOM, so the breadcrumbs no longer depend
on the theme's markup.
- Everything else is scoped to .vp-doc. VitePress renders the sidebar
section labels as <h2 class="text"> inside <aside class="VPSidebar">,
five per page, which an unscoped h2 selector would index 46 times.
- The hidden "Are you an LLM?" banner the llms plugin injects sits
inside .vp-doc and is stripped before extraction.
- Only taskfile.dev is crawled. next.taskfile.dev serves the same URLs
from the upcoming release into the same index, which would duplicate
every record.
- The changelog and the authoring templates are excluded, and
deprecation pages carry a negative pageRank so they stay findable
without outranking the page describing the replacement.
Safety and correctness settings that were missing from the first pass: saveBackup, and a safety check that refuses to publish an index which lost more than 10% of its records, so a crawl that breaks cannot empty search. url_without_anchor and type join attributesToRetrieve; the DocSearch client needs both to build a result link and group hits. startUrls goes back to the site root. /docs/ does not exist on the released site yet, so the crawler had no reachable entry point until the refactor is promoted. A section is inferred from the URL for the same reason, as a fallback for pages that do not carry the frontmatter yet. Code blocks are copied into crawler-only paragraphs so a search can find an exact Taskfile key or flag. Measured at +10% indexed content, and the level weighting still puts headings ahead of code. The two deprecation actions collapse into one, with pageRank computed from the path. The frontmatter field is renamed docsearch:doc_type to match what the extractor reads.
vmaerten
force-pushed
the
docs/redesign-whole-site
branch
from
September 3, 2026 12:24
ab23ead to
a1454db
Compare
vmaerten
marked this pull request as ready for review
September 3, 2026 12:26
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
guide.mdhad grown to 2950 lines and 27 sections.I tried to split it to make to more readable. I'll also edit our Algolia crawler to have better suggestion