uniweb 0.2.32 → 0.2.36
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 +1 -1
- package/package.json +6 -5
- package/partials/adding-pages.hbs +29 -0
- package/partials/ai-assistance.hbs +3 -0
- package/partials/claude-md.hbs +226 -0
- package/partials/components-docs.hbs +15 -0
- package/partials/deployment.hbs +13 -0
- package/partials/exports-js.hbs +14 -0
- package/partials/learn-more.hbs +5 -0
- package/partials/quick-start.hbs +8 -0
- package/src/commands/build.js +41 -1
- package/src/templates/processor.js +1 -1
- package/templates/_shared/CLAUDE.md.hbs +1 -148
- package/templates/multi/CLAUDE.md.hbs +1 -100
- package/templates/multi/README.md.hbs +6 -17
- package/templates/multi/foundations/default/package.json.hbs +2 -1
- package/templates/multi/foundations/default/src/_entry.generated.js +13 -0
- package/templates/multi/foundations/default/src/exports.js.hbs +11 -0
- package/templates/single/README.md.hbs +7 -21
- package/templates/single/foundation/package.json.hbs +2 -2
- package/templates/single/foundation/src/_entry.generated.js +13 -0
- package/templates/single/foundation/src/exports.js.hbs +11 -0
- package/templates/template/template/CLAUDE.md.hbs +1 -1
- package/templates/template/template/foundation/src/_entry.generated.js +14 -0
- package/templates/multi/foundations/default/src/index.js +0 -32
- package/templates/single/foundation/scripts/generate-entry.js +0 -15
- /package/{src/partials → partials}/search-docs.hbs +0 -0
package/README.md
CHANGED
|
@@ -324,7 +324,7 @@ my-project/
|
|
|
324
324
|
└── src/
|
|
325
325
|
├── styles.css # Tailwind CSS v4
|
|
326
326
|
├── meta.js # Foundation metadata
|
|
327
|
-
├──
|
|
327
|
+
├── exports.js # (optional) Custom Layout, props
|
|
328
328
|
└── components/
|
|
329
329
|
└── Section/
|
|
330
330
|
├── index.jsx
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uniweb",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.36",
|
|
4
4
|
"description": "Create structured Vite + React sites with content/code separation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"src",
|
|
11
|
-
"templates"
|
|
11
|
+
"templates",
|
|
12
|
+
"partials"
|
|
12
13
|
],
|
|
13
14
|
"keywords": [
|
|
14
15
|
"uniweb",
|
|
@@ -36,9 +37,9 @@
|
|
|
36
37
|
"js-yaml": "^4.1.0",
|
|
37
38
|
"prompts": "^2.4.2",
|
|
38
39
|
"tar": "^7.0.0",
|
|
39
|
-
"@uniweb/build": "0.1.
|
|
40
|
-
"@uniweb/runtime": "0.2.
|
|
41
|
-
"@uniweb/core": "0.1.
|
|
40
|
+
"@uniweb/build": "0.1.19",
|
|
41
|
+
"@uniweb/runtime": "0.2.10",
|
|
42
|
+
"@uniweb/core": "0.1.8",
|
|
42
43
|
"@uniweb/kit": "0.1.4"
|
|
43
44
|
}
|
|
44
45
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
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-`, `2.5-`).
|
|
13
|
+
|
|
14
|
+
For more control, use the `sections` property in `page.yml`:
|
|
15
|
+
|
|
16
|
+
```yaml
|
|
17
|
+
title: My Page
|
|
18
|
+
sections:
|
|
19
|
+
- hero
|
|
20
|
+
- features
|
|
21
|
+
- pricing
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
This approach makes reordering easy (just move lines) and allows temporarily removing sections by commenting them out.
|
|
25
|
+
|
|
26
|
+
**Options:**
|
|
27
|
+
- `sections: *` or omit — auto-discover and sort `.md` files (default)
|
|
28
|
+
- `sections: [hero, features]` — explicit ordering, no numeric prefixes needed
|
|
29
|
+
- `sections: []` or no `.md` files — pure route with no content sections
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance for AI assistants working with this Uniweb project.
|
|
4
|
+
|
|
5
|
+
## Project Structure
|
|
6
|
+
|
|
7
|
+
Uniweb projects have two structures. A single project can be converted to multi-site:
|
|
8
|
+
|
|
9
|
+
**Single (one foundation, one site):**
|
|
10
|
+
```
|
|
11
|
+
project/
|
|
12
|
+
├── foundation/ # Purpose-built component library (React)
|
|
13
|
+
├── site/ # Content (markdown pages)
|
|
14
|
+
└── pnpm-workspace.yaml
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Multi-site (multiple foundations and sites):**
|
|
18
|
+
```
|
|
19
|
+
project/
|
|
20
|
+
├── foundations/ # Purpose-built component libraries
|
|
21
|
+
│ └── marketing/
|
|
22
|
+
├── sites/ # Content sites
|
|
23
|
+
│ └── my-org/
|
|
24
|
+
└── pnpm-workspace.yaml
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
- **Foundation**: React components. Components with `meta.js` are *exposed* to content authors.
|
|
28
|
+
- **Site**: Markdown content. Each section references a component via `type:` in frontmatter.
|
|
29
|
+
|
|
30
|
+
## Commands
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pnpm install # Install dependencies
|
|
34
|
+
pnpm dev # Start dev server (runs default/main site)
|
|
35
|
+
pnpm build # Build for production
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Multi-site also supports:
|
|
39
|
+
```bash
|
|
40
|
+
pnpm dev:all # Start all sites in parallel
|
|
41
|
+
pnpm build:all # Build all sites
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Discovering Components
|
|
45
|
+
|
|
46
|
+
Exposed components live in `foundation/src/components/` (or `foundations/*/src/components/`).
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# List exposed components (those with meta.js)
|
|
50
|
+
ls foundation/src/components/*/meta.js
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Understanding a component:**
|
|
54
|
+
|
|
55
|
+
1. **`meta.js`** - Defines the component's interface:
|
|
56
|
+
- `title`, `description` - What the component does
|
|
57
|
+
- `elements` - What content it expects (title, paragraphs, links, items, etc.)
|
|
58
|
+
- `properties` - Configurable parameters (theme, layout, etc.)
|
|
59
|
+
- `hidden: true` - Component exists but isn't selectable from frontmatter
|
|
60
|
+
|
|
61
|
+
2. **`index.jsx`** - The React implementation
|
|
62
|
+
|
|
63
|
+
3. **Existing content** - See how the component is used in `site/pages/`
|
|
64
|
+
|
|
65
|
+
**Note:** Components without `meta.js` are internal helpers used by other components.
|
|
66
|
+
|
|
67
|
+
## Content Authoring
|
|
68
|
+
|
|
69
|
+
### Section Format
|
|
70
|
+
|
|
71
|
+
Each section is a markdown file with YAML frontmatter:
|
|
72
|
+
|
|
73
|
+
```markdown
|
|
74
|
+
---
|
|
75
|
+
type: ComponentName # Must match an exposed component
|
|
76
|
+
theme: dark # Parameter from meta.js properties
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
### Eyebrow Text # H3 before H1 → pretitle
|
|
80
|
+
|
|
81
|
+
# Main Headline # H1 → title
|
|
82
|
+
|
|
83
|
+
## Subtitle # H2 after H1 → subtitle
|
|
84
|
+
|
|
85
|
+
Description paragraph.
|
|
86
|
+
|
|
87
|
+
[Call to Action](#link)
|
|
88
|
+
|
|
89
|
+

|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Content Structure
|
|
93
|
+
|
|
94
|
+
The semantic parser extracts markdown into:
|
|
95
|
+
|
|
96
|
+
- **`content.main.header`** - title, pretitle, subtitle
|
|
97
|
+
- **`content.main.body`** - paragraphs, links, imgs, lists
|
|
98
|
+
- **`content.items`** - Groups created by H3 headings (each with its own header/body)
|
|
99
|
+
|
|
100
|
+
### Page Organization
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
site/pages/ # or sites/*/pages/
|
|
104
|
+
├── @header/ # Rendered on all pages
|
|
105
|
+
├── @footer/ # Rendered on all pages
|
|
106
|
+
└── [page-name]/
|
|
107
|
+
├── page.yml # title, description, order
|
|
108
|
+
└── 1-section.md # Numbered for ordering
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**page.yml options:**
|
|
112
|
+
```yaml
|
|
113
|
+
title: About Us
|
|
114
|
+
description: Learn about our company
|
|
115
|
+
order: 2 # Sort order in navigation
|
|
116
|
+
|
|
117
|
+
# Section ordering (optional)
|
|
118
|
+
sections:
|
|
119
|
+
- hero
|
|
120
|
+
- features
|
|
121
|
+
- pricing
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Section ordering:**
|
|
125
|
+
- Default: `.md` files discovered and sorted by numeric prefix (`1-`, `2-`, `2.5-`)
|
|
126
|
+
- Explicit: Use `sections: [hero, features]` — no prefixes needed, easy reordering
|
|
127
|
+
- Empty: `sections: []` or no `.md` files — pure route with no content
|
|
128
|
+
- Wildcard: `sections: *` — explicitly use default behavior
|
|
129
|
+
|
|
130
|
+
## Component Development
|
|
131
|
+
|
|
132
|
+
### Props Interface
|
|
133
|
+
|
|
134
|
+
```jsx
|
|
135
|
+
function MyComponent({ content, params, block, website }) {
|
|
136
|
+
const { title, pretitle } = content.main?.header || {}
|
|
137
|
+
const { paragraphs = [], links = [] } = content.main?.body || {}
|
|
138
|
+
const items = content.items || []
|
|
139
|
+
// ...
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Using @uniweb/kit
|
|
144
|
+
|
|
145
|
+
```jsx
|
|
146
|
+
import { H1, P, Link, Image, Section, cn } from '@uniweb/kit'
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
- `H1, H2, H3, P, Span` - Typography (handles arrays, filters empty)
|
|
150
|
+
- `Link` - Smart routing
|
|
151
|
+
- `Image` - Optimized images
|
|
152
|
+
- `Section` - Layout wrapper
|
|
153
|
+
- `cn()` - Tailwind class merging
|
|
154
|
+
|
|
155
|
+
### Creating a New Component
|
|
156
|
+
|
|
157
|
+
1. Create `foundation/src/components/NewComponent/index.jsx`
|
|
158
|
+
2. Create `foundation/src/components/NewComponent/meta.js`
|
|
159
|
+
3. Export from `foundation/src/index.js`
|
|
160
|
+
4. Rebuild: `cd foundation && pnpm build`
|
|
161
|
+
|
|
162
|
+
### meta.js Structure
|
|
163
|
+
|
|
164
|
+
```javascript
|
|
165
|
+
export default {
|
|
166
|
+
title: 'Component Name',
|
|
167
|
+
description: 'What it does',
|
|
168
|
+
// hidden: true, // Uncomment to hide from content authors
|
|
169
|
+
elements: {
|
|
170
|
+
title: { label: 'Headline', required: true },
|
|
171
|
+
paragraphs: { label: 'Description' },
|
|
172
|
+
links: { label: 'Call to Action' },
|
|
173
|
+
},
|
|
174
|
+
properties: {
|
|
175
|
+
theme: {
|
|
176
|
+
type: 'select',
|
|
177
|
+
label: 'Theme',
|
|
178
|
+
options: [
|
|
179
|
+
{ value: 'light', label: 'Light' },
|
|
180
|
+
{ value: 'dark', label: 'Dark' },
|
|
181
|
+
],
|
|
182
|
+
default: 'light',
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Parameter Philosophy
|
|
189
|
+
|
|
190
|
+
Design parameters that describe **intent**, not implementation:
|
|
191
|
+
|
|
192
|
+
| Good | Bad |
|
|
193
|
+
|------|-----|
|
|
194
|
+
| `theme: "dark"` | `backgroundColor: "#1a1a1a"` |
|
|
195
|
+
| `layout: "split"` | `gridTemplateColumns: "1fr 1fr"` |
|
|
196
|
+
| `size: "large"` | `fontSize: "2rem"` |
|
|
197
|
+
|
|
198
|
+
## Tailwind CSS v4
|
|
199
|
+
|
|
200
|
+
Theme is defined in `foundation/src/styles.css`:
|
|
201
|
+
|
|
202
|
+
```css
|
|
203
|
+
@import "tailwindcss";
|
|
204
|
+
@source "./components/**/*.{js,jsx}";
|
|
205
|
+
|
|
206
|
+
@theme {
|
|
207
|
+
--color-primary: #3b82f6;
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Use with: `bg-primary`, `text-primary`, `bg-primary/10` (10% opacity)
|
|
212
|
+
|
|
213
|
+
## Troubleshooting
|
|
214
|
+
|
|
215
|
+
**"Could not load foundation"**
|
|
216
|
+
- Single: Check `site/package.json` has `"foundation": "file:../foundation"`
|
|
217
|
+
- Multi: Check `sites/*/package.json` has `"default": "file:../../foundations/default"`
|
|
218
|
+
|
|
219
|
+
**Component not appearing**
|
|
220
|
+
1. Verify `meta.js` exists and doesn't have `hidden: true`
|
|
221
|
+
2. Check it's exported from `foundation/src/index.js`
|
|
222
|
+
3. Rebuild: `cd foundation && pnpm build`
|
|
223
|
+
|
|
224
|
+
**Styles not applying**
|
|
225
|
+
1. Verify `@source` in styles.css includes your component path
|
|
226
|
+
2. Check custom color names match `@theme` definitions
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
## Component Documentation
|
|
2
|
+
|
|
3
|
+
Generate up-to-date documentation for all foundation components:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
# From within the foundation directory
|
|
7
|
+
pnpm docs
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
This creates `COMPONENTS.md` with full details on each component's:
|
|
11
|
+
- Content elements (title, paragraphs, links, images, items)
|
|
12
|
+
- Parameters (theme, layout, columns, etc.)
|
|
13
|
+
- Presets (pre-configured parameter combinations)
|
|
14
|
+
|
|
15
|
+
The documentation is generated from component `meta.js` files, so it's always current.
|
|
@@ -0,0 +1,13 @@
|
|
|
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`
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Foundation Exports
|
|
3
|
+
*
|
|
4
|
+
* Optional file to export foundation-level capabilities to the runtime:
|
|
5
|
+
* - Layout: Custom page layout component (receives header, body, footer, sidebars)
|
|
6
|
+
* - props: Foundation-wide props accessible via website.foundationProps
|
|
7
|
+
*
|
|
8
|
+
* The Layout component receives pre-rendered page areas as props:
|
|
9
|
+
* - page, website: Runtime context
|
|
10
|
+
* - header, body, footer: Core page regions (pre-rendered React elements)
|
|
11
|
+
* - left/leftPanel, right/rightPanel: Sidebar panels
|
|
12
|
+
*
|
|
13
|
+
* If this file is not provided, the runtime uses a default layout (header -> body -> footer).
|
|
14
|
+
*/
|
package/src/commands/build.js
CHANGED
|
@@ -279,6 +279,46 @@ async function generateLocalizedHtml(projectDir, i18nConfig) {
|
|
|
279
279
|
}
|
|
280
280
|
}
|
|
281
281
|
|
|
282
|
+
/**
|
|
283
|
+
* Resolve foundation directory based on site config and project structure
|
|
284
|
+
*
|
|
285
|
+
* For single projects: ../foundation
|
|
286
|
+
* For multi projects: ../../foundations/{name}
|
|
287
|
+
*/
|
|
288
|
+
function resolveFoundationDir(projectDir, siteConfig) {
|
|
289
|
+
const foundationName = siteConfig?.foundation
|
|
290
|
+
|
|
291
|
+
// Check if we're in a multi-site structure (site is under sites/)
|
|
292
|
+
const parentDir = join(projectDir, '..')
|
|
293
|
+
const grandParentDir = join(projectDir, '..', '..')
|
|
294
|
+
const isMultiSite = parentDir.endsWith('/sites') || parentDir.endsWith('\\sites')
|
|
295
|
+
|
|
296
|
+
if (isMultiSite && foundationName) {
|
|
297
|
+
// Multi-site: look for foundations/{name}
|
|
298
|
+
const multiFoundationDir = join(grandParentDir, 'foundations', foundationName)
|
|
299
|
+
if (existsSync(multiFoundationDir)) {
|
|
300
|
+
return multiFoundationDir
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Single site: ../foundation
|
|
305
|
+
const singleFoundationDir = join(projectDir, '..', 'foundation')
|
|
306
|
+
if (existsSync(singleFoundationDir)) {
|
|
307
|
+
return singleFoundationDir
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Fallback: try to find by foundation name in parent
|
|
311
|
+
if (foundationName) {
|
|
312
|
+
const namedFoundationDir = join(parentDir, foundationName)
|
|
313
|
+
if (existsSync(namedFoundationDir)) {
|
|
314
|
+
return namedFoundationDir
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Ultimate fallback
|
|
319
|
+
return singleFoundationDir
|
|
320
|
+
}
|
|
321
|
+
|
|
282
322
|
/**
|
|
283
323
|
* Build a site
|
|
284
324
|
*/
|
|
@@ -330,7 +370,7 @@ async function buildSite(projectDir, options = {}) {
|
|
|
330
370
|
const { prerenderSite } = await import('@uniweb/build/prerender')
|
|
331
371
|
|
|
332
372
|
const result = await prerenderSite(projectDir, {
|
|
333
|
-
foundationDir: foundationDir ||
|
|
373
|
+
foundationDir: foundationDir || resolveFoundationDir(projectDir, siteConfig),
|
|
334
374
|
onProgress: (msg) => log(` ${colors.dim}${msg}${colors.reset}`)
|
|
335
375
|
})
|
|
336
376
|
|
|
@@ -58,7 +58,7 @@ export function clearMissingVersions() {
|
|
|
58
58
|
function registerPartials() {
|
|
59
59
|
if (partialsRegistered) return
|
|
60
60
|
|
|
61
|
-
const partialsDir = path.join(__dirname, '..', 'partials')
|
|
61
|
+
const partialsDir = path.join(__dirname, '..', '..', 'partials')
|
|
62
62
|
|
|
63
63
|
if (!existsSync(partialsDir)) {
|
|
64
64
|
partialsRegistered = true
|
|
@@ -1,148 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
This file provides guidance for AI assistants working with this Uniweb project.
|
|
4
|
-
|
|
5
|
-
## Project Overview
|
|
6
|
-
|
|
7
|
-
This is a **Uniweb** project - a component web platform that separates content from code.
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
{{projectName}}/
|
|
11
|
-
├── foundation/ # React component library (code)
|
|
12
|
-
├── site/ # Content and pages (markdown)
|
|
13
|
-
├── package.json # Root workspace config
|
|
14
|
-
└── pnpm-workspace.yaml
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
## Quick Commands
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
# Install dependencies
|
|
21
|
-
pnpm install
|
|
22
|
-
|
|
23
|
-
# Start development server (site with foundation)
|
|
24
|
-
pnpm dev
|
|
25
|
-
|
|
26
|
-
# Build foundation (generates dist/foundation.js and schema.json)
|
|
27
|
-
cd foundation && pnpm build
|
|
28
|
-
|
|
29
|
-
# Build site for production (outputs to site/dist/)
|
|
30
|
-
cd site && pnpm build
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## Key Files
|
|
34
|
-
|
|
35
|
-
**Site:**
|
|
36
|
-
- `site/vite.config.js` - 3-line config using `defineSiteConfig()` from `@uniweb/build/site`
|
|
37
|
-
- `site/main.js` - Entry point using `start()` from `@uniweb/runtime`
|
|
38
|
-
- `site/site.yml` - Site configuration (foundation path, title, i18n)
|
|
39
|
-
- `site/pages/` - Content pages (file-based routing)
|
|
40
|
-
|
|
41
|
-
**Foundation:**
|
|
42
|
-
- `foundation/vite.config.js` - 3-line config using `defineFoundationConfig()` from `@uniweb/build`
|
|
43
|
-
- `foundation/src/styles.css` - Tailwind CSS v4 theme
|
|
44
|
-
- `foundation/src/components/*/meta.js` - Component metadata (makes component exposed)
|
|
45
|
-
- `foundation/src/runtime.js` - (optional) Custom Layout and foundation props
|
|
46
|
-
- `foundation/src/_entry.generated.js` - Auto-generated at build/dev time
|
|
47
|
-
|
|
48
|
-
## Architecture
|
|
49
|
-
|
|
50
|
-
### Foundation Package (`/foundation`)
|
|
51
|
-
|
|
52
|
-
The **foundation** is a React component library. Components with a `meta.js` file are **exposed** (available to content creators via `type:` in frontmatter). Exposed components:
|
|
53
|
-
|
|
54
|
-
1. Receive structured content parsed from markdown
|
|
55
|
-
2. Have configurable parameters (theme, layout, etc.)
|
|
56
|
-
3. Render content according to their design
|
|
57
|
-
|
|
58
|
-
Internal components (no `meta.js`) are regular React components used within exposed components.
|
|
59
|
-
|
|
60
|
-
**Key directories:**
|
|
61
|
-
- `src/components/*/` - Component implementations
|
|
62
|
-
- `src/components/*/meta.js` - Component metadata (makes component exposed)
|
|
63
|
-
- `src/styles.css` - Global Tailwind styles
|
|
64
|
-
|
|
65
|
-
### Site Package (`/site`)
|
|
66
|
-
|
|
67
|
-
The **site** contains content written in markdown. The runtime loads the foundation and renders content based on component selections.
|
|
68
|
-
|
|
69
|
-
**Key directories:**
|
|
70
|
-
- `pages/` - Content pages organized in folders
|
|
71
|
-
- `pages/[page-name]/page.yml` - Page metadata
|
|
72
|
-
- `pages/[page-name]/*.md` - Content sections
|
|
73
|
-
|
|
74
|
-
## Content Authoring
|
|
75
|
-
|
|
76
|
-
### Section File Format
|
|
77
|
-
|
|
78
|
-
```markdown
|
|
79
|
-
---
|
|
80
|
-
type: ComponentName
|
|
81
|
-
theme: dark
|
|
82
|
-
layout: center
|
|
83
|
-
---
|
|
84
|
-
|
|
85
|
-
# Main Headline
|
|
86
|
-
|
|
87
|
-
Description paragraph.
|
|
88
|
-
|
|
89
|
-
[Call to Action](#link)
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### Content Structure
|
|
93
|
-
|
|
94
|
-
The semantic parser extracts content into:
|
|
95
|
-
|
|
96
|
-
- **`content.main.header`**: title, pretitle, subtitle
|
|
97
|
-
- **`content.main.body`**: paragraphs, links, imgs, lists
|
|
98
|
-
- **`content.items`**: Content groups from H3 headings
|
|
99
|
-
|
|
100
|
-
## Component Development
|
|
101
|
-
|
|
102
|
-
### Component Interface
|
|
103
|
-
|
|
104
|
-
```jsx
|
|
105
|
-
function MyComponent({ content, params, block, website }) {
|
|
106
|
-
const { title } = content.main?.header || {}
|
|
107
|
-
const { paragraphs = [] } = content.main?.body || {}
|
|
108
|
-
// ...
|
|
109
|
-
}
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
### Using @uniweb/kit
|
|
113
|
-
|
|
114
|
-
```jsx
|
|
115
|
-
import { H1, P, Link, cn } from '@uniweb/kit'
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
### Component Metadata (`meta.js`)
|
|
119
|
-
|
|
120
|
-
```javascript
|
|
121
|
-
export default {
|
|
122
|
-
title: 'Component Name',
|
|
123
|
-
description: 'What the component does',
|
|
124
|
-
category: 'Content',
|
|
125
|
-
elements: { /* content elements */ },
|
|
126
|
-
properties: { /* configurable params */ },
|
|
127
|
-
}
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
## Tailwind CSS v4
|
|
131
|
-
|
|
132
|
-
This project uses Tailwind CSS v4 with the Vite plugin.
|
|
133
|
-
|
|
134
|
-
**Theme customization** (`foundation/src/styles.css`):
|
|
135
|
-
|
|
136
|
-
```css
|
|
137
|
-
@import "tailwindcss";
|
|
138
|
-
@source "./components/**/*.{js,jsx}";
|
|
139
|
-
@theme {
|
|
140
|
-
--color-primary: #3b82f6;
|
|
141
|
-
}
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
## Resources
|
|
145
|
-
|
|
146
|
-
- [Uniweb Documentation](https://github.com/uniweb/uniweb)
|
|
147
|
-
- [@uniweb/kit Documentation](https://www.npmjs.com/package/@uniweb/kit)
|
|
148
|
-
- [Tailwind CSS v4](https://tailwindcss.com/docs)
|
|
1
|
+
{{> claude-md}}
|
|
@@ -1,100 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
This file provides guidance for AI assistants working with this Uniweb multi-site workspace.
|
|
4
|
-
|
|
5
|
-
## Project Overview
|
|
6
|
-
|
|
7
|
-
This is a **Uniweb multi-site workspace** - supporting multiple sites and foundations.
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
{{projectName}}/
|
|
11
|
-
├── foundations/ # Shared component libraries
|
|
12
|
-
│ └── default/ # Default foundation
|
|
13
|
-
├── sites/ # Content sites
|
|
14
|
-
│ └── main/ # Main site
|
|
15
|
-
├── package.json # Root workspace config
|
|
16
|
-
└── pnpm-workspace.yaml
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Quick Commands
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
# Install dependencies
|
|
23
|
-
pnpm install
|
|
24
|
-
|
|
25
|
-
# Start main site development
|
|
26
|
-
pnpm dev
|
|
27
|
-
|
|
28
|
-
# Start all sites in parallel
|
|
29
|
-
pnpm dev:all
|
|
30
|
-
|
|
31
|
-
# Build main site
|
|
32
|
-
pnpm build
|
|
33
|
-
|
|
34
|
-
# Build all sites
|
|
35
|
-
pnpm build:all
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Adding New Sites
|
|
39
|
-
|
|
40
|
-
1. Copy an existing site directory:
|
|
41
|
-
```bash
|
|
42
|
-
cp -r sites/main sites/newsite
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
2. Update `sites/newsite/package.json` with a unique name
|
|
46
|
-
|
|
47
|
-
3. Update `sites/newsite/site.yml` with site configuration
|
|
48
|
-
|
|
49
|
-
4. Run `pnpm install` to link the new site
|
|
50
|
-
|
|
51
|
-
## Adding New Foundations
|
|
52
|
-
|
|
53
|
-
1. Copy an existing foundation:
|
|
54
|
-
```bash
|
|
55
|
-
cp -r foundations/default foundations/newfoundation
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
2. Update `foundations/newfoundation/package.json` with a unique name
|
|
59
|
-
|
|
60
|
-
3. In your site's `site.yml`, reference the foundation:
|
|
61
|
-
```yaml
|
|
62
|
-
foundation: newfoundation
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
4. In your site's `package.json`, add the dependency:
|
|
66
|
-
```json
|
|
67
|
-
"dependencies": {
|
|
68
|
-
"newfoundation": "file:../../foundations/newfoundation"
|
|
69
|
-
}
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
## Key Files
|
|
73
|
-
|
|
74
|
-
**Sites:**
|
|
75
|
-
- `sites/*/vite.config.js` - 3-line config using `defineSiteConfig()` from `@uniweb/build/site`
|
|
76
|
-
- `sites/*/main.js` - Entry point using `start()` from `@uniweb/runtime`
|
|
77
|
-
- `sites/*/site.yml` - Site configuration (foundation reference, title, i18n)
|
|
78
|
-
- `sites/*/pages/` - Content pages (file-based routing)
|
|
79
|
-
|
|
80
|
-
**Foundations:**
|
|
81
|
-
- `foundations/*/vite.config.js` - 3-line config using `defineFoundationConfig()` from `@uniweb/build`
|
|
82
|
-
- `foundations/*/src/styles.css` - Tailwind CSS v4 theme
|
|
83
|
-
- `foundations/*/src/components/*/meta.js` - Component metadata (makes component exposed)
|
|
84
|
-
- `foundations/*/src/runtime.js` - (optional) Custom Layout and foundation props
|
|
85
|
-
|
|
86
|
-
## Architecture
|
|
87
|
-
|
|
88
|
-
### Foundations (`/foundations/*`)
|
|
89
|
-
|
|
90
|
-
Each foundation is a React component library. Sites can share foundations or have their own.
|
|
91
|
-
|
|
92
|
-
### Sites (`/sites/*`)
|
|
93
|
-
|
|
94
|
-
Each site contains content in markdown. A site references one foundation for its components.
|
|
95
|
-
|
|
96
|
-
## Resources
|
|
97
|
-
|
|
98
|
-
- [Uniweb Documentation](https://github.com/uniweb/uniweb)
|
|
99
|
-
- [@uniweb/kit Documentation](https://www.npmjs.com/package/@uniweb/kit)
|
|
100
|
-
- [Tailwind CSS v4](https://tailwindcss.com/docs)
|
|
1
|
+
{{> claude-md}}
|
|
@@ -1,15 +1,8 @@
|
|
|
1
1
|
# {{projectName}}
|
|
2
2
|
|
|
3
|
-
A multi-site workspace built with [Uniweb](https://github.com/uniweb/
|
|
3
|
+
A multi-site workspace built with [Uniweb](https://github.com/uniweb/cli) — a component web platform that separates content from code.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
pnpm install # Install dependencies
|
|
9
|
-
pnpm dev # Start main site development
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
Visit `http://localhost:5173` to see your site.
|
|
5
|
+
{{> quick-start}}
|
|
13
6
|
|
|
14
7
|
## Project Structure
|
|
15
8
|
|
|
@@ -33,6 +26,8 @@ Visit `http://localhost:5173` to see your site.
|
|
|
33
26
|
└── README.md # This file
|
|
34
27
|
```
|
|
35
28
|
|
|
29
|
+
{{> components-docs}}
|
|
30
|
+
|
|
36
31
|
## Commands
|
|
37
32
|
|
|
38
33
|
```bash
|
|
@@ -85,12 +80,6 @@ This allows:
|
|
|
85
80
|
- Single source of truth for design
|
|
86
81
|
- Foundation updates propagate to all sites
|
|
87
82
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
See [CLAUDE.md](./CLAUDE.md) for detailed instructions that AI assistants can use.
|
|
91
|
-
|
|
92
|
-
## Learn More
|
|
83
|
+
{{> ai-assistance}}
|
|
93
84
|
|
|
94
|
-
-
|
|
95
|
-
- [@uniweb/kit Components](https://www.npmjs.com/package/@uniweb/kit)
|
|
96
|
-
- [Tailwind CSS v4](https://tailwindcss.com)
|
|
85
|
+
{{> learn-more}}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Auto-generated foundation entry point
|
|
2
|
+
// DO NOT EDIT - This file is regenerated during build
|
|
3
|
+
|
|
4
|
+
import './styles.css'
|
|
5
|
+
import Section from './components/Section/index.jsx'
|
|
6
|
+
|
|
7
|
+
export const components = { Section }
|
|
8
|
+
|
|
9
|
+
export { Section }
|
|
10
|
+
|
|
11
|
+
export const capabilities = null
|
|
12
|
+
|
|
13
|
+
export const meta = {}
|
|
@@ -1,15 +1,8 @@
|
|
|
1
1
|
# {{projectName}}
|
|
2
2
|
|
|
3
|
-
A website built with [Uniweb](https://github.com/uniweb/
|
|
3
|
+
A website built with [Uniweb](https://github.com/uniweb/cli) — a component web platform that separates content from code.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
pnpm install # Install dependencies
|
|
9
|
-
pnpm dev # Start development server
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
Visit `http://localhost:5173` to see your site.
|
|
5
|
+
{{> quick-start}}
|
|
13
6
|
|
|
14
7
|
## Project Structure
|
|
15
8
|
|
|
@@ -49,10 +42,7 @@ Your content here.
|
|
|
49
42
|
[Call to Action](#)
|
|
50
43
|
```
|
|
51
44
|
|
|
52
|
-
|
|
53
|
-
- Create folder: `site/pages/about/`
|
|
54
|
-
- Add `page.yml` with title and metadata
|
|
55
|
-
- Add sections: `1-intro.md`, `2-team.md`, etc.
|
|
45
|
+
{{> adding-pages}}
|
|
56
46
|
|
|
57
47
|
## Component Development
|
|
58
48
|
|
|
@@ -78,6 +68,8 @@ export default Hero
|
|
|
78
68
|
|
|
79
69
|
Exposed components (selectable via `type:` in frontmatter) need a `meta.js` file.
|
|
80
70
|
|
|
71
|
+
{{> components-docs}}
|
|
72
|
+
|
|
81
73
|
## Building
|
|
82
74
|
|
|
83
75
|
```bash
|
|
@@ -90,12 +82,6 @@ cd site && pnpm build
|
|
|
90
82
|
|
|
91
83
|
Deploy `site/dist/` to any static host (Vercel, Netlify, Cloudflare Pages, etc.)
|
|
92
84
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
See [CLAUDE.md](./CLAUDE.md) for detailed instructions that AI assistants can use.
|
|
96
|
-
|
|
97
|
-
## Learn More
|
|
85
|
+
{{> ai-assistance}}
|
|
98
86
|
|
|
99
|
-
-
|
|
100
|
-
- [@uniweb/kit Components](https://www.npmjs.com/package/@uniweb/kit)
|
|
101
|
-
- [Tailwind CSS v4](https://tailwindcss.com)
|
|
87
|
+
{{> learn-more}}
|
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
},
|
|
12
12
|
"files": ["dist", "src"],
|
|
13
13
|
"scripts": {
|
|
14
|
-
"postinstall": "node scripts/generate-entry.js",
|
|
15
14
|
"dev": "vite",
|
|
16
15
|
"build": "uniweb build",
|
|
17
16
|
"build:vite": "vite build",
|
|
18
|
-
"preview": "vite preview"
|
|
17
|
+
"preview": "vite preview",
|
|
18
|
+
"docs": "uniweb docs"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
|
21
21
|
"react": "^18.0.0 || ^19.0.0",
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Auto-generated foundation entry point
|
|
2
|
+
// DO NOT EDIT - This file is regenerated during build
|
|
3
|
+
|
|
4
|
+
import './styles.css'
|
|
5
|
+
import Section from './components/Section/index.jsx'
|
|
6
|
+
|
|
7
|
+
export const components = { Section }
|
|
8
|
+
|
|
9
|
+
export { Section }
|
|
10
|
+
|
|
11
|
+
export const capabilities = null
|
|
12
|
+
|
|
13
|
+
export const meta = {}
|
|
@@ -66,5 +66,5 @@ uniweb create myproject --template github:user/repo
|
|
|
66
66
|
|
|
67
67
|
## Resources
|
|
68
68
|
|
|
69
|
-
- [Uniweb Documentation](https://github.com/uniweb/
|
|
69
|
+
- [Uniweb Documentation](https://github.com/uniweb/cli)
|
|
70
70
|
- [@uniweb/kit Documentation](https://www.npmjs.com/package/@uniweb/kit)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Auto-generated foundation entry point
|
|
2
|
+
// DO NOT EDIT - This file is regenerated during build
|
|
3
|
+
|
|
4
|
+
import './styles.css'
|
|
5
|
+
import Features from './components/Features/index.jsx'
|
|
6
|
+
import Hero from './components/Hero/index.jsx'
|
|
7
|
+
|
|
8
|
+
export const components = { Features, Hero }
|
|
9
|
+
|
|
10
|
+
export { Features, Hero }
|
|
11
|
+
|
|
12
|
+
export const runtime = null
|
|
13
|
+
|
|
14
|
+
export const meta = {}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Default Foundation Entry Point
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import Section from './components/Section/index.jsx'
|
|
6
|
-
|
|
7
|
-
const components = {
|
|
8
|
-
Section,
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function getComponent(name) {
|
|
12
|
-
return components[name]
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function listComponents() {
|
|
16
|
-
return Object.keys(components)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function getSchema(name) {
|
|
20
|
-
return components[name]?.schema
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function getAllSchemas() {
|
|
24
|
-
const schemas = {}
|
|
25
|
-
for (const [name, component] of Object.entries(components)) {
|
|
26
|
-
if (component.schema) schemas[name] = component.schema
|
|
27
|
-
}
|
|
28
|
-
return schemas
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export { Section }
|
|
32
|
-
export default { getComponent, listComponents, getSchema, getAllSchemas, components }
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generate Foundation Entry Point
|
|
3
|
-
*
|
|
4
|
-
* This script is called during postinstall to ensure the foundation
|
|
5
|
-
* entry point exists before the site dev server starts.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { generateEntryPoint } from '@uniweb/build'
|
|
9
|
-
|
|
10
|
-
try {
|
|
11
|
-
await generateEntryPoint('./src', './src/_entry.generated.js')
|
|
12
|
-
} catch (err) {
|
|
13
|
-
// Silently fail during initial install if dependencies aren't ready
|
|
14
|
-
console.warn('Note: Entry generation skipped (run foundation dev/build to generate)')
|
|
15
|
-
}
|
|
File without changes
|