152 lines
5.8 KiB
Markdown
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.
|