Files
documentation-docusaurus/references/dedicated-homepage-local-search.md
T
2026-08-14 12:32:08 +00:00

152 lines
5.8 KiB
Markdown

# Dedicated Docusaurus Homepage + Native Local Search
Use this pattern when a docs-only Docusaurus site needs a product/showcase homepage and search that runs entirely from static build artifacts.
## Route separation
A docs plugin with `routeBasePath: '/'` can coexist with `src/pages/index.tsx`, but no doc may also claim `/`.
```md
---
id: intro
title: Documentation overview
slug: /overview
---
```
After moving the intro, re-check Markdown links. A link such as `./methodology` from `/overview/` resolves under `/overview/`; use `../methodology`, a Docusaurus doc link, or an explicit base-path URL.
Keep footer/navbar links explicit:
```ts
{label: 'Home', to: '/'},
{label: 'Overview', to: '/overview'},
```
## Local search without hosted services
Install at the root of a root-only pnpm workspace:
```bash
pnpm add -w @easyops-cn/docusaurus-search-local
```
Configure it as a **theme**, not a plugin:
```ts
themes: [
[
require.resolve('@easyops-cn/docusaurus-search-local'),
{
hashed: true,
indexDocs: true,
indexBlog: false,
indexPages: true,
docsRouteBasePath: ['/', 'clients'],
language: ['en'],
highlightSearchTermsOnTargetPage: true,
explicitSearchResultPath: true,
searchResultLimits: 12,
searchResultContextMaxLength: 120,
},
],
],
```
`docsRouteBasePath` must cover every docs plugin whose content should be searchable. Do not add Algolia credentials, crawler configuration, Ask AI, or another network service when the requirement is browser-local search.
### One SearchBar only
The theme supplies the navbar `@theme/SearchBar`. Avoid importing and rendering another `SearchBar` on the homepage: duplicate instances can contend for the singleton autocomplete/index lifecycle and leave the UI with input text but no fetched index or result overlay.
Use a landing-page trigger instead:
```tsx
const openSearch = () => {
const input = document.querySelector<HTMLInputElement>('.navbar__search-input');
if (input) {
input.focus();
return;
}
document.dispatchEvent(
new KeyboardEvent('keydown', {key: 'k', ctrlKey: true, bubbles: true}),
);
};
<button type="button" onClick={openSearch}>
Search documentation <kbd>Ctrl/⌘ + K</kbd>
</button>
```
Keep the navbar field itself as the sole search implementation.
## Generated homepage metrics
Do not hard-code changing registry statistics into JSX. Extend the canonical content generator to emit an ignored TypeScript module:
```python
summary = ROOT / "src" / "generated" / "registrySummary.ts"
summary.parent.mkdir(parents=True, exist_ok=True)
summary.write_text(
"export const registrySummary = "
+ json.dumps({"total": total, "researched": researched}, separators=(",", ":"))
+ " as const;\n",
encoding="utf-8",
)
```
Add `/src/generated` to `.gitignore`, run generation before both `tsc` and `docusaurus build`, and import from `@site/src/generated/registrySummary`.
## Government-portal visual adaptation
When adapting an official public-sector site, copy the visual grammar rather than cloning its page:
- derive a small token set from the real site (navy, action blue, pale neutral background, white surfaces, restrained borders);
- use a locally installed font package to avoid runtime font dependencies;
- reuse only appropriate official marks with clear provenance;
- reproduce hierarchy: narrow institutional strip, white utility navigation, large editorial hero, evidence/status blocks, and dark institutional footer;
- preserve the user's established geometry preference (for Lego, globally force `border-radius: 0` even if the source site uses pills);
- provide dark-mode equivalents without replacing the light-first official character.
For the VSSA pattern, the useful observed tokens were approximately navy `#091a5a`, action blue `#0b66e4`, pale background `#f3f6f9`, and Public Sans. The official coat-of-arms SVG was suitable as a local navbar asset.
## Public page unchanged: distinguish an untriggered workflow from a failed workflow
When a user cannot see locally completed changes, do not begin with runner debugging. Establish the publication chain in order:
1. `git status --short --branch` — are the changes still uncommitted?
2. `git rev-list --left-right --count HEAD...origin/main` — were they pushed?
3. Read the newest Actions run and compare its `head_sha` to the intended commit.
4. If the newest run still points to the previous SHA, Actions did not fail; the new workflow was never triggered. Commit and push.
5. Wait for the run attached to the intended SHA to reach `completed success`.
6. Fetch the public page with `Cache-Control: no-cache` and a query marker such as `?verify=<short-sha>`; assert a distinctive new heading or asset, not only HTTP 200.
7. Verify the public `search-index.json` contains representative searchable terms, then run a real browser query and open a result.
This sequence prevents two common false diagnoses: treating a successful local build as a deployment, and treating an old successful Actions run as evidence that a new change was published.
## Verification gate
Run all of these before declaring completion:
```bash
pnpm validate
pnpm build
test -s build/search-index.json
```
Then programmatically inspect the index for representative terms from:
1. the main docs plugin;
2. every secondary docs plugin;
3. the custom homepage when `indexPages: true`.
Finally, serve the production build and verify in a browser:
- desktop and mobile homepage layout;
- navbar search and keyboard shortcut;
- a query produces visible results;
- opening a result reaches the expected dossier route;
- square geometry and responsive navigation remain intact.
Publication is complete only after commit/push, a successful Gitea Actions run, and HTTP/content verification of the public homepage, overview, representative result route, and search index.