This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user