uniweb 1.20.3 → 1.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +145 -113
- package/package.json +5 -5
- package/partials/agents.md +19 -8
- package/partials/start.md +126 -0
- package/src/backend/app-changes.js +153 -0
- package/src/backend/client.js +3 -3
- package/src/backend/foundation-bring-along.js +1 -1
- package/src/backend/payment-handoff.js +25 -2
- package/src/commands/clone.js +2 -0
- package/src/commands/doctor.js +41 -10
- package/src/commands/pull.js +17 -2
- package/src/commands/register.js +15 -15
- package/src/commands/start.js +60 -0
- package/src/commands/status.js +712 -254
- package/src/commands/update.js +1 -23
- package/src/index.js +80 -2
- package/src/utils/code-upload.js +27 -27
- package/src/utils/flag-guard.js +17 -2
- package/src/utils/git.js +91 -1
- package/src/utils/registry-auth.js +15 -5
- package/src/utils/scaffold.js +4 -0
- package/src/utils/status-next.js +47 -0
- package/src/utils/update-check.js +8 -6
- package/src/utils/workspace.js +26 -0
- package/starter/foundation/sections/Section/index.jsx +6 -6
- package/starter/site/pages/home/1-welcome.md.hbs +1 -1
- package/templates/site/site.yml.hbs +4 -5
- package/templates/workspace/README.md.hbs +132 -50
- package/partials/adding-pages.hbs +0 -77
- package/partials/ai-assistance.hbs +0 -28
- package/partials/components-docs.hbs +0 -13
- package/partials/config-reference.hbs +0 -66
- package/partials/deployment.hbs +0 -13
- package/partials/learn-more.hbs +0 -6
- package/partials/quick-start.hbs +0 -8
- package/partials/search-docs.hbs +0 -110
|
@@ -1,87 +1,169 @@
|
|
|
1
1
|
# {{projectName}}
|
|
2
2
|
|
|
3
|
-
A website
|
|
3
|
+
A website made with [Uniweb](https://uniweb.io): an open-source React framework and a connected
|
|
4
|
+
visual authoring platform.
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
**Developers define the vocabulary. Authors compose with it. Uniweb keeps both sides in sync.**
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
This project and the Uniweb app are two interfaces to the same website. Here, in code and git,
|
|
9
|
+
you build its **foundation**: React components, called section types, and the schemas of its
|
|
10
|
+
structured content. In the app, authors compose pages from those section types and manage records
|
|
11
|
+
through those schemas: visually, with live previews, and with no markdown, YAML or git to learn.
|
|
12
|
+
You build the components. Uniweb builds the authoring experience.
|
|
13
|
+
{{#if cloned}}
|
|
8
14
|
|
|
15
|
+
This project was cloned from a site in the Uniweb app (`uniweb clone`), so it is already in sync
|
|
16
|
+
with it. Its foundation is a registered one, not a folder of this project.
|
|
17
|
+
{{/if}}
|
|
18
|
+
|
|
19
|
+
## Quick start
|
|
20
|
+
|
|
21
|
+
{{#if packages.length}}
|
|
22
|
+
```bash
|
|
23
|
+
pnpm install
|
|
24
|
+
pnpm dev # prints the address it serves the site at
|
|
9
25
|
```
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
│ │ ├── page.yml
|
|
21
|
-
│ │ └── 1-welcome.md
|
|
22
|
-
│ ├── site.yml # Site configuration (foundation: src)
|
|
23
|
-
│ └── vite.config.js # defineSiteConfig()
|
|
24
|
-
│
|
|
25
|
-
└── AGENTS.md # Developer guide (human + AI)
|
|
26
|
+
|
|
27
|
+
Edit a page or a section type and the page updates as you save. With npm, use `npm install`,
|
|
28
|
+
`npm run dev` and `npx uniweb`.
|
|
29
|
+
{{else}}
|
|
30
|
+
This workspace started empty. Add a foundation and a site, then run them:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npx uniweb add project <name> # a foundation in <name>/src, a site in <name>/site
|
|
34
|
+
pnpm install
|
|
35
|
+
pnpm uniweb dev # prints the address it serves the site at
|
|
26
36
|
```
|
|
37
|
+
{{/if}}
|
|
27
38
|
|
|
28
|
-
|
|
39
|
+
## What's here
|
|
29
40
|
|
|
30
|
-
|
|
41
|
+
| Folder | What it holds |
|
|
42
|
+
|---|---|
|
|
43
|
+
{{#each packages}}
|
|
44
|
+
| `{{path}}/` | {{#if foundation}}a foundation: section types in `sections/`, written in React, and any data schemas in `schemas/`{{/if}}{{#if extension}}an extension: more section types, loaded beside a foundation{{/if}}{{#if site}}a site: its pages in `pages/`, with `site.yml` and `theme.yml`{{/if}} |
|
|
45
|
+
{{/each}}
|
|
46
|
+
| `AGENTS.md` | the manual for this project and its version of Uniweb, for you and for AI agents |
|
|
31
47
|
|
|
32
|
-
|
|
48
|
+
Each markdown file in a site's `pages/` is one section of a page. Its frontmatter names a
|
|
49
|
+
section type, and the component receives the content already parsed. For example:
|
|
33
50
|
|
|
34
51
|
```markdown
|
|
35
52
|
---
|
|
36
|
-
type:
|
|
37
|
-
theme: light
|
|
53
|
+
type: Hero
|
|
38
54
|
---
|
|
39
55
|
|
|
40
|
-
#
|
|
41
|
-
|
|
42
|
-
Your content here.
|
|
56
|
+
# Build something great
|
|
43
57
|
|
|
44
|
-
|
|
58
|
+
Edit this text, not the component.
|
|
45
59
|
```
|
|
46
60
|
|
|
47
|
-
{{> adding-pages}}
|
|
48
|
-
|
|
49
|
-
## Component Development
|
|
50
|
-
|
|
51
|
-
Section types live in `src/sections/`. Each is a folder with an `index.jsx` and a `meta.js`:
|
|
52
|
-
|
|
53
61
|
```jsx
|
|
54
|
-
//
|
|
62
|
+
// sections/Hero/index.jsx
|
|
55
63
|
import { H1, P } from '@uniweb/kit'
|
|
56
64
|
|
|
57
65
|
export default function Hero({ content }) {
|
|
58
|
-
const { title, paragraphs = [] } = content || {}
|
|
59
|
-
|
|
60
66
|
return (
|
|
61
|
-
<div className="max-w-4xl
|
|
62
|
-
<H1 text={title} className="text-
|
|
63
|
-
<P text={paragraphs} className="text-body
|
|
67
|
+
<div className="mx-auto max-w-4xl px-6">
|
|
68
|
+
<H1 text={content.title} className="text-4xl font-bold text-heading" />
|
|
69
|
+
<P text={content.paragraphs} className="mt-4 text-body" />
|
|
64
70
|
</div>
|
|
65
71
|
)
|
|
66
72
|
}
|
|
67
73
|
```
|
|
68
74
|
|
|
69
|
-
|
|
75
|
+
`text-heading` and `text-body` are theme tokens. A site's `theme.yml` sets their colors, so one
|
|
76
|
+
component works in light and dark sections, and on every site that uses it.
|
|
70
77
|
|
|
71
|
-
|
|
78
|
+
## Connect the authoring app
|
|
72
79
|
|
|
73
|
-
|
|
80
|
+
Start with a normal project, and connect the app when you want visual authoring:
|
|
74
81
|
|
|
75
82
|
```bash
|
|
76
|
-
#
|
|
77
|
-
|
|
83
|
+
pnpm uniweb login # sign in to your Uniweb account
|
|
84
|
+
pnpm uniweb sync # the first sync brings the site and its foundation into the app
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
From then on, the CLI is the bridge between the two workflows:
|
|
88
|
+
|
|
89
|
+
| Command | What it does |
|
|
90
|
+
|---|---|
|
|
91
|
+
| `pnpm uniweb push` | sends your section types, schemas and content to the app: a draft, not live |
|
|
92
|
+
| `pnpm uniweb pull` | brings authors' edits into your files, as a git merge |
|
|
93
|
+
| `pnpm uniweb sync` | takes your teammates' commits and the authors' edits, then pushes yours |
|
|
94
|
+
| `pnpm uniweb publish` | pushes, then takes the site live on Uniweb hosting, a paid service |
|
|
95
|
+
|
|
96
|
+
Authors never need to think about synchronization: in the app, their changes appear live. On
|
|
97
|
+
your side, edits to different sections combine, and nothing overwrites an author's edit. When
|
|
98
|
+
the same section changed on both sides, `sync` stops at a git conflict for you to settle. Like
|
|
99
|
+
git, a push sends what you have committed; `--commit` commits the site's content first.
|
|
100
|
+
|
|
101
|
+
### Structured content, editable without an admin app
|
|
102
|
+
|
|
103
|
+
A section type declares the data it shows, by schema, in its `meta.js`:
|
|
78
104
|
|
|
79
|
-
|
|
80
|
-
|
|
105
|
+
```js
|
|
106
|
+
export default {
|
|
107
|
+
data: {
|
|
108
|
+
people: '@std/person', // a standard schema, from @uniweb/schemas
|
|
109
|
+
events: '@/event' // this foundation's own, in schemas/event.yml
|
|
110
|
+
}
|
|
111
|
+
}
|
|
81
112
|
```
|
|
82
113
|
|
|
83
|
-
|
|
114
|
+
A standard schema needs `@uniweb/schemas` as a dependency of the foundation. In the app, authors
|
|
115
|
+
get forms and records for those schemas. No separate admin application is needed to make the
|
|
116
|
+
data editable.
|
|
117
|
+
|
|
118
|
+
## Other ways to use it
|
|
119
|
+
|
|
120
|
+
The framework works on its own, too.
|
|
121
|
+
|
|
122
|
+
- **Content in files only.** If you manage the content yourself, the site needs no Uniweb account.
|
|
123
|
+
`pnpm build` makes each site's `dist/`, a static site for any host, and `pnpm uniweb deploy`
|
|
124
|
+
ships it to GitHub Pages, Cloudflare Pages, Netlify, Vercel or S3 + CloudFront.
|
|
125
|
+
- **Foundations for your clients' sites.** If the sites belong to your clients, who make and edit
|
|
126
|
+
them in the app, this project is where you build and test the foundation.
|
|
127
|
+
`pnpm uniweb register` publishes it to Uniweb for their sites.
|
|
128
|
+
|
|
129
|
+
## Working with AI agents
|
|
130
|
+
|
|
131
|
+
A Uniweb project gives an agent a system to work within, its section types, schemas and content
|
|
132
|
+
conventions, instead of a blank canvas. What an agent builds here, authors can use in the app
|
|
133
|
+
after the next sync.
|
|
134
|
+
|
|
135
|
+
[AGENTS.md](./AGENTS.md) is written for developers and AI agents alike. Many coding agents read it
|
|
136
|
+
on their own when they start in this folder; point any other agent at it first.
|
|
137
|
+
`npx uniweb@latest update` moves the project to the latest release of Uniweb, and AGENTS.md with
|
|
138
|
+
it.
|
|
139
|
+
|
|
140
|
+
Some prompts to try:
|
|
141
|
+
|
|
142
|
+
**Converting an existing design:**
|
|
143
|
+
```
|
|
144
|
+
I have a landing page design in `homepage.jsx`. Convert it into this Uniweb
|
|
145
|
+
project. Decompose each visual section into a section type in the foundation,
|
|
146
|
+
and extract all text content into markdown files in the site's pages/home/.
|
|
147
|
+
The final page should render identically to the original. See AGENTS.md.
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Adding a section type:**
|
|
151
|
+
```
|
|
152
|
+
Create a Pricing section type with 3-column cards. It should work in light and
|
|
153
|
+
dark sections. Use content.items for the pricing tiers — each item has a title,
|
|
154
|
+
a paragraph (the price), and a link (the call to action).
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**Adding a page:**
|
|
158
|
+
```
|
|
159
|
+
Add a /contact page with a hero section and a contact details section. Reuse
|
|
160
|
+
the Hero section type from the homepage.
|
|
161
|
+
```
|
|
84
162
|
|
|
85
|
-
|
|
163
|
+
## Learn more
|
|
86
164
|
|
|
87
|
-
|
|
165
|
+
- [Documentation](https://uniweb.io/docs): guides and reference. For AI agents, its index is
|
|
166
|
+
https://uniweb.io/llms.txt
|
|
167
|
+
- [Uniweb app](https://uniweb.app): the visual authoring platform
|
|
168
|
+
- `pnpm uniweb <command> --help`: every command's options
|
|
169
|
+
- `pnpm uniweb doctor`: checks the project's configuration
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
### Adding a New Page
|
|
2
|
-
|
|
3
|
-
1. Create a folder: `site/pages/my-page/`
|
|
4
|
-
2. Add `page.yml`:
|
|
5
|
-
```yaml
|
|
6
|
-
title: My Page
|
|
7
|
-
```
|
|
8
|
-
3. Add section files: `1-hero.md`, `2-content.md`, etc.
|
|
9
|
-
|
|
10
|
-
### Section Ordering
|
|
11
|
-
|
|
12
|
-
By default, sections are discovered from `.md` files and sorted by numeric prefix (`1-`, `2-`, `3-`).
|
|
13
|
-
|
|
14
|
-
**Decimal prefixes** allow inserting sections without renumbering: `2.5-` sorts between `2-` and `3-`.
|
|
15
|
-
|
|
16
|
-
For explicit control, use the `sections` property in `page.yml`:
|
|
17
|
-
|
|
18
|
-
```yaml
|
|
19
|
-
title: My Page
|
|
20
|
-
sections:
|
|
21
|
-
- hero
|
|
22
|
-
- features
|
|
23
|
-
- pricing
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
This makes reordering easy (move lines) and allows commenting out sections temporarily.
|
|
27
|
-
|
|
28
|
-
**Options:**
|
|
29
|
-
- `sections: *` or omit — auto-discover and sort `.md` files by prefix (default)
|
|
30
|
-
- `sections: [hero, features]` — explicit ordering, no prefixes needed
|
|
31
|
-
- `sections: []` — pure route with no content sections
|
|
32
|
-
|
|
33
|
-
### Section Hierarchy (Subsections)
|
|
34
|
-
|
|
35
|
-
For parent-child relationships, use the explicit array with nesting:
|
|
36
|
-
|
|
37
|
-
```yaml
|
|
38
|
-
sections:
|
|
39
|
-
- hero
|
|
40
|
-
- features:
|
|
41
|
-
- logocloud
|
|
42
|
-
- stats
|
|
43
|
-
- pricing
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
This is clearer than prefix notation and easier to restructure.
|
|
47
|
-
|
|
48
|
-
**Advanced:** Comma prefixes (`1,1-`, `1,2-`) also denote hierarchy, but explicit arrays are recommended for readability.
|
|
49
|
-
|
|
50
|
-
### Page Ordering and Index Pages
|
|
51
|
-
|
|
52
|
-
Parent controls which page is the "index" for its route. The index page gets the parent's route.
|
|
53
|
-
|
|
54
|
-
**In `site.yml`** (for top-level pages):
|
|
55
|
-
```yaml
|
|
56
|
-
name: My Site
|
|
57
|
-
pages: [home, about, features] # First (home) is homepage at /
|
|
58
|
-
# Or just name the homepage:
|
|
59
|
-
index: home
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
**In `page.yml`** (for child pages):
|
|
63
|
-
```yaml
|
|
64
|
-
title: Documentation
|
|
65
|
-
pages: [getting-started, installation, config] # First is index for /docs
|
|
66
|
-
# Or just name the index:
|
|
67
|
-
index: getting-started
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
**How it works:**
|
|
71
|
-
- `pages: [a, b, c]` — Explicit order, first item gets parent route
|
|
72
|
-
- `index: name` — Just set the index, auto-discover the rest
|
|
73
|
-
- Omit both — Sort by `order` prop, lowest becomes index
|
|
74
|
-
|
|
75
|
-
**Example:** If `getting-started` is the index for `/docs`:
|
|
76
|
-
- `pages/docs/getting-started/` → route `/docs`
|
|
77
|
-
- `pages/docs/installation/` → route `/docs/installation`
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
## Developer Guide
|
|
2
|
-
|
|
3
|
-
[AGENTS.md](./AGENTS.md) is a comprehensive guide to building with Uniweb — content authoring, component development, theming, configuration, and the kit API. Despite the name, it's written for developers and AI assistants alike. Read it to get productive fast.
|
|
4
|
-
|
|
5
|
-
### AI Prompts
|
|
6
|
-
|
|
7
|
-
AI coding assistants (Claude Code, Cursor, Copilot, etc.) read AGENTS.md automatically. Some prompts to try:
|
|
8
|
-
|
|
9
|
-
**Converting an existing design:**
|
|
10
|
-
```
|
|
11
|
-
I have a landing page design in `homepage.jsx`. Convert it into this Uniweb
|
|
12
|
-
project. Decompose each visual section into a foundation component and extract
|
|
13
|
-
all text content into markdown files in site/pages/home/. The final page
|
|
14
|
-
should render identically to the original. See AGENTS.md for the full guide.
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
**Adding a new component:**
|
|
18
|
-
```
|
|
19
|
-
Create a Pricing component with 3-column cards. It should support light and
|
|
20
|
-
dark themes. Use content.items for the pricing tiers — each item has a title,
|
|
21
|
-
paragraph (price), and links (CTA button).
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
**Adding a new page:**
|
|
25
|
-
```
|
|
26
|
-
Add a /contact page with a hero section and a form section. Reuse the Hero
|
|
27
|
-
component from the homepage. Create a new ContactForm component for the form.
|
|
28
|
-
```
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
## Component Documentation
|
|
2
|
-
|
|
3
|
-
Generate up-to-date documentation for all foundation components:
|
|
4
|
-
|
|
5
|
-
```bash
|
|
6
|
-
# From foundation directory
|
|
7
|
-
uniweb docs
|
|
8
|
-
|
|
9
|
-
# Or from site directory (auto-detects linked foundation)
|
|
10
|
-
cd site && uniweb docs
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
This creates `COMPONENTS.md` with details on each component's parameters, presets, and content elements. The documentation is generated from component `meta.js` files, so it's always current.
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
## Configuration Reference
|
|
2
|
-
|
|
3
|
-
### site.yml
|
|
4
|
-
|
|
5
|
-
Site-wide configuration in `site/site.yml`:
|
|
6
|
-
|
|
7
|
-
```yaml
|
|
8
|
-
name: My Site # Site name
|
|
9
|
-
defaultLanguage: en # Default locale code
|
|
10
|
-
foundation: foundation # Foundation package name
|
|
11
|
-
|
|
12
|
-
# Page ordering (controls top-level navigation)
|
|
13
|
-
pages: [home, about, features] # First is homepage at /
|
|
14
|
-
# Or just name the homepage:
|
|
15
|
-
index: home
|
|
16
|
-
|
|
17
|
-
# Internationalization
|
|
18
|
-
i18n:
|
|
19
|
-
locales: [es, fr] # Non-default locales to build
|
|
20
|
-
localesDir: locales # Translation files directory
|
|
21
|
-
|
|
22
|
-
# Build options
|
|
23
|
-
build:
|
|
24
|
-
prerender: true # Enable static site generation
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
### page.yml
|
|
28
|
-
|
|
29
|
-
Page-level configuration in `site/pages/[page]/page.yml`:
|
|
30
|
-
|
|
31
|
-
```yaml
|
|
32
|
-
title: About Us # Page title (used in <title> and nav)
|
|
33
|
-
description: Learn about us # Meta description
|
|
34
|
-
label: About # Short nav label (optional)
|
|
35
|
-
order: 2 # Navigation sort order
|
|
36
|
-
|
|
37
|
-
# Child page ordering
|
|
38
|
-
pages: [intro, guide, reference] # First is index for this route
|
|
39
|
-
index: intro # Or just name the index
|
|
40
|
-
|
|
41
|
-
# Navigation visibility
|
|
42
|
-
hidden: true # Hide from all navigation
|
|
43
|
-
hideIn: [header] # Hide from named nav areas only (header, footer, sidebar, …)
|
|
44
|
-
|
|
45
|
-
# Layout overrides
|
|
46
|
-
layout:
|
|
47
|
-
header: false # Don't render header
|
|
48
|
-
footer: false # Don't render footer
|
|
49
|
-
|
|
50
|
-
# Section ordering
|
|
51
|
-
sections: # Explicit section order
|
|
52
|
-
- hero
|
|
53
|
-
- features: # Nested = subsections
|
|
54
|
-
- logocloud
|
|
55
|
-
- stats
|
|
56
|
-
- pricing
|
|
57
|
-
|
|
58
|
-
# SEO
|
|
59
|
-
seo:
|
|
60
|
-
noindex: true
|
|
61
|
-
image: /og-image.png
|
|
62
|
-
changefreq: monthly
|
|
63
|
-
priority: 0.8
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
Run `uniweb docs site` or `uniweb docs page` for complete reference.
|
package/partials/deployment.hbs
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
## Deployment
|
|
2
|
-
|
|
3
|
-
Build and deploy the `site/dist` folder:
|
|
4
|
-
|
|
5
|
-
```bash
|
|
6
|
-
pnpm build
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
**Supported platforms:**
|
|
10
|
-
- **Vercel**: `cd site && vercel`
|
|
11
|
-
- **Netlify**: Build command `pnpm build`, publish `site/dist`
|
|
12
|
-
- **GitHub Pages**: Use GitHub Actions
|
|
13
|
-
- **Cloudflare Pages**: Connect repo, set `pnpm build` and `site/dist`
|
package/partials/learn-more.hbs
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
## Learn More
|
|
2
|
-
|
|
3
|
-
- [AGENTS.md](./AGENTS.md) — comprehensive guide to building with Uniweb
|
|
4
|
-
- [Uniweb Documentation](https://github.com/uniweb/docs) — full reference docs
|
|
5
|
-
- [Uniweb CLI](https://github.com/uniweb/cli) — project scaffolding and build tools
|
|
6
|
-
- [Tailwind CSS v4](https://tailwindcss.com)
|
package/partials/quick-start.hbs
DELETED
package/partials/search-docs.hbs
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
## Search Functionality
|
|
2
|
-
|
|
3
|
-
Uniweb sites support full-text search out of the box. Search indexes are generated automatically at build time.
|
|
4
|
-
|
|
5
|
-
### Enabling Search in Your Foundation
|
|
6
|
-
|
|
7
|
-
To add search to your site, your foundation needs the **Fuse.js** library:
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
cd foundation
|
|
11
|
-
pnpm add fuse.js
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
Then use the search helpers from `@uniweb/kit`:
|
|
15
|
-
|
|
16
|
-
```jsx
|
|
17
|
-
import { useSearch } from '@uniweb/kit'
|
|
18
|
-
|
|
19
|
-
function SearchComponent({ website }) {
|
|
20
|
-
const { query, results, isLoading, clear } = useSearch(website)
|
|
21
|
-
|
|
22
|
-
return (
|
|
23
|
-
<div>
|
|
24
|
-
<input
|
|
25
|
-
type="search"
|
|
26
|
-
placeholder="Search..."
|
|
27
|
-
onChange={e => query(e.target.value)}
|
|
28
|
-
/>
|
|
29
|
-
{isLoading && <span>Searching...</span>}
|
|
30
|
-
<ul>
|
|
31
|
-
{results.map(result => (
|
|
32
|
-
<li key={result.id}>
|
|
33
|
-
<a href={result.href}>{result.title}</a>
|
|
34
|
-
<p dangerouslySetInnerHTML=\{{ __html: result.snippetHtml }} />
|
|
35
|
-
</li>
|
|
36
|
-
))}
|
|
37
|
-
</ul>
|
|
38
|
-
</div>
|
|
39
|
-
)
|
|
40
|
-
}
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
### Search Configuration
|
|
44
|
-
|
|
45
|
-
Search is enabled by default. To customize, add to `site/site.yml`:
|
|
46
|
-
|
|
47
|
-
```yaml
|
|
48
|
-
search:
|
|
49
|
-
enabled: true
|
|
50
|
-
exclude:
|
|
51
|
-
routes: [/admin, /private] # Don't index these routes
|
|
52
|
-
components: [Debug] # Don't index these component types
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### How It Works
|
|
56
|
-
|
|
57
|
-
1. **Build time**: Uniweb extracts text from all pages and sections
|
|
58
|
-
2. **Output**: A `search-index.json` file is generated in `dist/`
|
|
59
|
-
3. **Runtime**: Components fetch and search the index client-side
|
|
60
|
-
4. **Multi-locale**: Each locale gets its own search index
|
|
61
|
-
|
|
62
|
-
### Search API
|
|
63
|
-
|
|
64
|
-
The `website` object provides these methods:
|
|
65
|
-
|
|
66
|
-
```javascript
|
|
67
|
-
// Check if search is available
|
|
68
|
-
website.isSearchEnabled() // Returns boolean
|
|
69
|
-
|
|
70
|
-
// Get the URL for the search index
|
|
71
|
-
website.getSearchIndexUrl() // "/search-index.json" or "/es/search-index.json"
|
|
72
|
-
|
|
73
|
-
// Get full search configuration
|
|
74
|
-
website.getSearchConfig() // { enabled, indexUrl, locale, include, exclude }
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### Search Result Format
|
|
78
|
-
|
|
79
|
-
Results from `useSearch()` include:
|
|
80
|
-
|
|
81
|
-
| Field | Description |
|
|
82
|
-
|-------|-------------|
|
|
83
|
-
| `id` | Unique result identifier |
|
|
84
|
-
| `type` | `"page"` or `"section"` |
|
|
85
|
-
| `route` | Page route |
|
|
86
|
-
| `href` | Full link including anchor |
|
|
87
|
-
| `title` | Result title |
|
|
88
|
-
| `pageTitle` | Parent page title (for sections) |
|
|
89
|
-
| `snippetHtml` | Excerpt with `<mark>` highlighted matches |
|
|
90
|
-
| `snippetText` | Plain text excerpt |
|
|
91
|
-
|
|
92
|
-
### Without @uniweb/kit
|
|
93
|
-
|
|
94
|
-
If you prefer not to use the kit helpers, you can fetch the index directly:
|
|
95
|
-
|
|
96
|
-
```javascript
|
|
97
|
-
// Fetch the search index
|
|
98
|
-
const response = await fetch(website.getSearchIndexUrl())
|
|
99
|
-
const index = await response.json()
|
|
100
|
-
|
|
101
|
-
// Use with Fuse.js directly
|
|
102
|
-
import Fuse from 'fuse.js'
|
|
103
|
-
const fuse = new Fuse(index.entries, {
|
|
104
|
-
keys: ['title', 'content'],
|
|
105
|
-
threshold: 0.35,
|
|
106
|
-
includeMatches: true
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
const results = fuse.search('your query')
|
|
110
|
-
```
|