uniweb 1.0.0 → 1.0.2

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.
Files changed (129) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +532 -3
  3. package/package.json +60 -11
  4. package/partials/adding-pages.hbs +77 -0
  5. package/partials/agents.md +3000 -0
  6. package/partials/ai-assistance.hbs +28 -0
  7. package/partials/components-docs.hbs +13 -0
  8. package/partials/config-reference.hbs +66 -0
  9. package/partials/deployment.hbs +13 -0
  10. package/partials/learn-more.hbs +6 -0
  11. package/partials/quick-start.hbs +8 -0
  12. package/partials/search-docs.hbs +110 -0
  13. package/src/backend/asset-download.js +222 -0
  14. package/src/backend/client.js +986 -0
  15. package/src/backend/foundation-bring-along.js +692 -0
  16. package/src/backend/payment-handoff.js +362 -0
  17. package/src/backend/service-request.js +210 -0
  18. package/src/backend/site-media.js +255 -0
  19. package/src/backend/site-preview.js +77 -0
  20. package/src/backend/site-sync.js +2515 -0
  21. package/src/backend/workspace.js +234 -0
  22. package/src/commands/add.js +1900 -0
  23. package/src/commands/build.js +1214 -0
  24. package/src/commands/clone.js +466 -0
  25. package/src/commands/content.js +202 -0
  26. package/src/commands/deploy.js +537 -0
  27. package/src/commands/dev.js +202 -0
  28. package/src/commands/docs.js +530 -0
  29. package/src/commands/doctor.js +1982 -0
  30. package/src/commands/export.js +116 -0
  31. package/src/commands/families.js +82 -0
  32. package/src/commands/forget.js +197 -0
  33. package/src/commands/handoff.js +21 -0
  34. package/src/commands/i18n.js +1707 -0
  35. package/src/commands/inspect.js +375 -0
  36. package/src/commands/invite.js +24 -0
  37. package/src/commands/org.js +96 -0
  38. package/src/commands/publish.js +1087 -0
  39. package/src/commands/pull.js +1257 -0
  40. package/src/commands/push.js +663 -0
  41. package/src/commands/refresh.js +212 -0
  42. package/src/commands/register.js +1092 -0
  43. package/src/commands/rename.js +647 -0
  44. package/src/commands/site.js +358 -0
  45. package/src/commands/snapshot.js +461 -0
  46. package/src/commands/starter.js +206 -0
  47. package/src/commands/status.js +302 -0
  48. package/src/commands/sync.js +93 -0
  49. package/src/commands/template.js +107 -0
  50. package/src/commands/update.js +887 -0
  51. package/src/commands/validate.js +376 -0
  52. package/src/framework-index.json +248 -0
  53. package/src/index.js +2241 -0
  54. package/src/templates/fetchers/github.js +113 -0
  55. package/src/templates/fetchers/npm.js +85 -0
  56. package/src/templates/fetchers/release.js +92 -0
  57. package/src/templates/index.js +190 -0
  58. package/src/templates/processor.js +333 -0
  59. package/src/templates/resolver.js +232 -0
  60. package/src/templates/validator.js +155 -0
  61. package/src/utils/agents-stamp.js +110 -0
  62. package/src/utils/args.js +126 -0
  63. package/src/utils/asset-upload.js +270 -0
  64. package/src/utils/bytes.js +30 -0
  65. package/src/utils/code-upload.js +394 -0
  66. package/src/utils/config.js +417 -0
  67. package/src/utils/conformance.js +274 -0
  68. package/src/utils/dep-survey.js +176 -0
  69. package/src/utils/destination-prompt.js +146 -0
  70. package/src/utils/discover.js +75 -0
  71. package/src/utils/env.js +22 -0
  72. package/src/utils/exit.js +30 -0
  73. package/src/utils/fetch-retry.js +109 -0
  74. package/src/utils/flag-guard.js +246 -0
  75. package/src/utils/foundation-name.js +179 -0
  76. package/src/utils/git.js +342 -0
  77. package/src/utils/host-prompt.js +51 -0
  78. package/src/utils/install-integrity.js +210 -0
  79. package/src/utils/interactive.js +118 -0
  80. package/src/utils/json-file.js +72 -0
  81. package/src/utils/names.js +91 -0
  82. package/src/utils/placement.js +151 -0
  83. package/src/utils/pm.js +165 -0
  84. package/src/utils/preview.js +20 -0
  85. package/src/utils/pull-written.js +132 -0
  86. package/src/utils/records-guard.js +88 -0
  87. package/src/utils/registry-auth.js +994 -0
  88. package/src/utils/registry-orgs.js +290 -0
  89. package/src/utils/scaffold.js +483 -0
  90. package/src/utils/schemaless-report.js +30 -0
  91. package/src/utils/semver-precedence.js +80 -0
  92. package/src/utils/session-file.js +95 -0
  93. package/src/utils/site-content-refs.js +23 -0
  94. package/src/utils/site-copies.js +123 -0
  95. package/src/utils/site-data-upload.js +302 -0
  96. package/src/utils/site-identity.js +137 -0
  97. package/src/utils/snapshot-settings.js +112 -0
  98. package/src/utils/update-check.js +302 -0
  99. package/src/utils/uwx-read.js +157 -0
  100. package/src/utils/workspace.js +223 -0
  101. package/src/versions.js +467 -0
  102. package/starter/foundation/main.js +50 -0
  103. package/starter/foundation/sections/Section/index.jsx +95 -0
  104. package/starter/foundation/sections/Section/meta.js +44 -0
  105. package/starter/site/pages/about/1-about.md.hbs +13 -0
  106. package/starter/site/pages/about/page.yml +3 -0
  107. package/starter/site/pages/home/1-welcome.md.hbs +14 -0
  108. package/starter/site/pages/home/page.yml +3 -0
  109. package/templates/foundation/_gitignore +5 -0
  110. package/templates/foundation/components/.gitkeep +0 -0
  111. package/templates/foundation/main.js.hbs +33 -0
  112. package/templates/foundation/package.json.hbs +51 -0
  113. package/templates/foundation/sections/.gitkeep +0 -0
  114. package/templates/foundation/styles.css +6 -0
  115. package/templates/foundation/vite.config.js +3 -0
  116. package/templates/site/_gitignore +12 -0
  117. package/templates/site/entry.js +7 -0
  118. package/templates/site/index.html.hbs +13 -0
  119. package/templates/site/package.json.hbs +27 -0
  120. package/templates/site/public/favicon.svg +7 -0
  121. package/templates/site/site.yml.hbs +91 -0
  122. package/templates/site/theme.yml +99 -0
  123. package/templates/site/vite.config.js +7 -0
  124. package/templates/workspace/AGENTS.md.hbs +2 -0
  125. package/templates/workspace/README.md.hbs +87 -0
  126. package/templates/workspace/_gitignore +29 -0
  127. package/templates/workspace/_vscode/settings.json +6 -0
  128. package/templates/workspace/package.json.hbs +20 -0
  129. package/templates/workspace/pnpm-workspace.yaml.hbs +26 -0
package/README.md CHANGED
@@ -1,5 +1,534 @@
1
- # Deprecated Package
1
+ # uniweb
2
2
 
3
- This package is no longer supported and has been deprecated. To avoid malicious use, npm is hanging on to the package name.
3
+ A component content architecture for React. Build sites where content authors and component developers can't break each other's work—and scale from local files to visual editing without rewrites.
4
4
 
5
- Please contact support@npmjs.com if you have questions about this package.
5
+ Create well-structured Vite + React projects with file-based routing, localization, and clean content/code separation out of the box.
6
+
7
+ ## Quick Start
8
+
9
+ ```bash
10
+ npm create uniweb
11
+ ```
12
+
13
+ The interactive prompt asks for a project name and template. Pick one, then:
14
+
15
+ ```bash
16
+ cd my-project
17
+ pnpm install # or npm install
18
+ pnpm dev # or npm run dev
19
+ ```
20
+
21
+ Edit files in `site/pages/` and `src/sections/` to see changes instantly.
22
+
23
+ > **pnpm ready** — `pnpm create uniweb` works out of the box. Projects include both `pnpm-workspace.yaml` and npm workspaces.
24
+
25
+ ### Templates
26
+
27
+ | Template | Description |
28
+ | --- | --- |
29
+ | **Starter** | Foundation + site + sample content (default) |
30
+ | **None** | Foundation + site with no content |
31
+ | **Marketing** | Landing page, features, pricing, testimonials |
32
+ | **Docs** | Documentation with sidebar and search |
33
+ | **Academic** | Research site with publications and team |
34
+ | **International** | Multilingual site with i18n and blog |
35
+ | **Dynamic** | Live API data fetching with loading states |
36
+ | **Store** | E-commerce with product grid |
37
+ | **Extensions** | Multi-foundation with visual effects extension |
38
+
39
+ **See them live:** [View all template demos](https://uniweb.github.io/templates/)
40
+
41
+ Use `--blank` for an empty workspace (no packages) — grow with `uniweb add`.
42
+
43
+ **Two starting points.** Either let the CLI create a new directory:
44
+
45
+ ```bash
46
+ pnpm create uniweb my-site --template docs
47
+ ```
48
+
49
+ …or scaffold inside an existing directory (e.g., a freshly-cloned GitHub repo):
50
+
51
+ ```bash
52
+ pnpm create uniweb . --template docs
53
+ ```
54
+
55
+ ### Local Scripts
56
+
57
+ Run these from the **project root**:
58
+
59
+ ```bash
60
+ pnpm dev # Start development server
61
+ pnpm build # Build foundation + site for production
62
+ pnpm preview # Preview the production build
63
+ ```
64
+
65
+ The `build` command outputs to `site/dist/`. With pre-rendering enabled (the default for official templates), you get static HTML files ready to deploy anywhere. For the actual deploy step (and the `uniweb deploy` / `uniweb register` commands), see [Deployment](#deployment) below.
66
+
67
+ ## What You Get
68
+
69
+ Every project starts as a workspace with two packages:
70
+
71
+ - **`site/`** — Content, pages, entry point (package name: `site`)
72
+ - **`src/`** — React components, the site's source code (package name: `src`)
73
+
74
+ A site is pure content. A foundation is the site's source code — that's why it lives in `src/`. Content authors work in markdown. Component authors work in React. Neither can break the other's work. As your project grows, use `uniweb add` to add more foundations, sites, and extensions.
75
+
76
+ ```
77
+ my-project/
78
+ ├── site/ # Content + configuration
79
+ │ ├── pages/ # File-based routing
80
+ │ │ └── home/
81
+ │ │ ├── page.yml # Page metadata
82
+ │ │ └── hero.md # Section content
83
+ │ ├── locales/ # i18n (hash-based translations)
84
+ │ ├── entry.js # Entry point (~6 lines)
85
+ │ ├── vite.config.js # 3-line config
86
+ │ └── public/ # Static assets
87
+ │
88
+ └── src/ # Foundation package (the site's source)
89
+ ├── sections/ # Section types (addressable from markdown)
90
+ │ ├── Hero.jsx # Bare file → section type (no meta.js needed)
91
+ │ └── Features/
92
+ │ ├── meta.js # Content interface (params, presets)
93
+ │ └── Features.jsx
94
+ ├── components/ # Regular React components
95
+ │ └── Button.jsx
96
+ ├── main.js # Package exports (vars, defaultLayout, props)
97
+ ├── styles.css # Tailwind v4 + CSS tokens
98
+ ├── package.json # name: "src"
99
+ ├── vite.config.js # 3-line config
100
+ └── dist/ # Built output
101
+ ```
102
+
103
+ **Pages are folders.** Create `pages/about/` with markdown files inside → visit `/about`. That's the whole routing model.
104
+
105
+ **Batteries included:** File-based routing, pre-rendering, localization, dynamic routes, media processing, search indexing, and more. See [Building with Uniweb](https://github.com/uniweb/docs/blob/main/development/building-with-uniweb.md) for the full list.
106
+
107
+ ### Content as Markdown
108
+
109
+ ```markdown
110
+ ---
111
+ type: Hero
112
+ theme: dark
113
+ ---
114
+
115
+ # Welcome
116
+
117
+ Build something great.
118
+
119
+ [Get Started](#)
120
+ ```
121
+
122
+ Frontmatter specifies the component type and configuration. The body contains the actual content—headings, paragraphs, links, images—which gets semantically parsed into structured data your component receives.
123
+
124
+ ### Beyond Markdown
125
+
126
+ For content that doesn't fit markdown patterns—products, team members, events—use tagged data blocks:
127
+
128
+ ````markdown
129
+ ```yaml:team-member
130
+ name: Sarah Chen
131
+ role: Lead Architect
132
+ ```
133
+ ````
134
+
135
+ Access the parsed data via `content.data`:
136
+
137
+ ```jsx
138
+ function TeamCard({ content }) {
139
+ const member = content.data['team-member']
140
+ return (
141
+ <div>
142
+ {member.name} — {member.role}
143
+ </div>
144
+ )
145
+ }
146
+ ```
147
+
148
+ Natural content stays in markdown; structured data goes in tagged blocks (YAML or JSON).
149
+
150
+ ### Components as React
151
+
152
+ ```jsx
153
+ export default function Hero({ content, params }) {
154
+ const { title, paragraphs, links } = content
155
+
156
+ return (
157
+ <section className="py-20 text-center">
158
+ <h1 className="text-4xl font-bold">{title}</h1>
159
+ <p className="text-xl text-gray-600">{paragraphs[0]}</p>
160
+ {links[0] && (
161
+ <a
162
+ href={links[0].href}
163
+ className="mt-8 px-6 py-3 bg-blue-600 text-white rounded inline-block"
164
+ >
165
+ {links[0].label}
166
+ </a>
167
+ )}
168
+ </section>
169
+ )
170
+ }
171
+ ```
172
+
173
+ Standard React. Standard Tailwind. The `{ content, params }` interface is only for _section types_ — components that content creators select in markdown frontmatter. Everything else uses regular React props.
174
+
175
+ ### Composition
176
+
177
+ Sections aren't limited to flat content. Content authors can embed interactive React components using markdown image syntax:
178
+
179
+ ```markdown
180
+ ---
181
+ type: SplitContent
182
+ ---
183
+
184
+ # See it in action
185
+
186
+ The architecture handles the hard parts so you can focus on what matters.
187
+
188
+ ![Live metrics](@PerformanceChart){period=30d}
189
+ ```
190
+
191
+ `@PerformanceChart` is a full React component — a ThreeJS animation, an interactive diagram, a live data visualization — placed by the content author, rendered in the component's visual slot via `<Visual>`. It looks like an image reference, but it can be anything.
192
+
193
+ Authors can also compose layouts from reusable section types using child sections:
194
+
195
+ ```
196
+ pages/home/
197
+ ├── highlights.md # type: Grid, columns: 3
198
+ ├── @stats.md # type: StatCard
199
+ ├── @testimonial.md # type: Testimonial
200
+ └── @demo.md # type: SplitContent (with an embedded @LiveDemo inset)
201
+ ```
202
+
203
+ Three different section types, arranged in a grid, one with an interactive component inside it — all authored in markdown. The developer builds reusable pieces; the content author composes them. See the [Component Patterns guide](https://github.com/uniweb/docs/blob/main/development/component-patterns.md) for the full composition model.
204
+
205
+ ## Next Steps
206
+
207
+ After creating your project:
208
+
209
+ 1. **Explore the structure** — Browse `site/pages/` to see how content is organized. Each page folder contains `page.yml` (metadata) and `.md` files (sections).
210
+
211
+ 2. **Generate component docs** — Run `uniweb docs` to create `COMPONENTS.md` with all available components, their parameters, and presets.
212
+
213
+ 3. **Learn the configuration** — Run `uniweb docs site` or `uniweb docs page` for quick reference on configuration options.
214
+
215
+ 4. **Create a section type** — Add a file to `src/sections/` (e.g., `Banner.jsx`) and rebuild. Bare files at the root are discovered automatically — no `meta.js` needed. Add `meta.js` when you want to declare params or presets. See the [Component Metadata Reference](https://github.com/uniweb/docs/blob/main/reference/component-metadata.md) for the full schema.
216
+
217
+ The `meta.js` file defines what content and parameters a component accepts. The runtime uses this metadata to apply defaults and guarantee content structure—no defensive null checks needed in your component code.
218
+
219
+ ### Your First Content Change
220
+
221
+ Open `site/pages/home/hero.md` and edit the headline:
222
+
223
+ ```markdown
224
+ ---
225
+ type: Hero
226
+ ---
227
+
228
+ # Your New Headline Here
229
+
230
+ Updated description text.
231
+
232
+ [Get Started](/about)
233
+ ```
234
+
235
+ Save and see the change instantly in your browser.
236
+
237
+ ### Your First Component Change
238
+
239
+ Open `src/sections/Hero.jsx`. The component receives parsed content:
240
+
241
+ ```jsx
242
+ export default function Hero({ content }) {
243
+ const { title, paragraphs, links, images, items } = content
244
+ // Edit the JSX below...
245
+ }
246
+ ```
247
+
248
+ The parser extracts semantic elements from markdown—`title` from the first heading, `paragraphs` from body text, `links` from `[text](url)`, and so on. The `items` array contains child groups created when headings appear after content (useful for features, pricing tiers, team members, etc.).
249
+
250
+ ## Foundations Are Portable
251
+
252
+ The `src/` folder (your project's foundation) ships with your project as a convenience, but a foundation is dynamically loaded — sites reference it by configuration, not by folder proximity.
253
+
254
+ **Two ways to use a foundation:**
255
+
256
+ | Mode | How it works | Best for |
257
+ | ---------------- | ---------------------------------- | -------------------------------------------------- |
258
+ | **Local folder** | Foundation lives in your workspace | Developing site and components together |
259
+ | **Runtime link** | Foundation loads from a URL | Independent release cycles, platform-managed sites |
260
+
261
+ You can delete the `src/` folder entirely and point your site at a registered foundation. Or develop a foundation locally, then register it for other sites to consume. The site doesn't care where its components come from.
262
+
263
+ **This enables two development patterns:**
264
+
265
+ _Site-first_ — You're building a website. The foundation is your component library, co-developed with the site. This is the common case.
266
+
267
+ _Foundation-first_ — You're building a component system. The site is a test harness with sample content. The real sites live elsewhere—other repositories, other teams, or managed on [uniweb.app](https://uniweb.app). Use `uniweb add site` to add multiple test sites exercising a shared foundation.
268
+
269
+ ## Growing Your Project
270
+
271
+ > **Install the CLI globally** with `npm i -g uniweb` for the best experience — inside a project it runs the project's own copy. Keep it current: `create` and `clone` start a project on the CLI that runs them, so a global install stops them when a newer release is out. Without a global install, use `npx uniweb@latest create` to start a project and `pnpm uniweb` inside one.
272
+
273
+ Start simple. Add what you need, when you need it:
274
+
275
+ ```bash
276
+ # Create a blank workspace
277
+ uniweb create my-workspace --blank
278
+
279
+ cd my-workspace
280
+
281
+ # Add a co-located foundation + site pair
282
+ uniweb add project blog
283
+
284
+ # Add a second foundation at root
285
+ uniweb add foundation DocKit
286
+
287
+ # Add a site wired to a specific foundation
288
+ uniweb add site docs --foundation DocKit
289
+
290
+ # Add an extension (auto-wired to the only site)
291
+ uniweb add extension effects
292
+
293
+ # Scaffold + apply content from an official template
294
+ uniweb add project marketing --from marketing
295
+
296
+ # Install dependencies and run in dev mode
297
+ pnpm install # or npm install
298
+ pnpm dev # or npm run dev
299
+ ```
300
+
301
+ The workspace grows organically. `add` handles placement, wires dependencies, updates workspace globs, and generates root scripts. The name you provide becomes both the directory name and the package name. Use `--path` to override default placement, or `--project` for explicit co-located layouts.
302
+
303
+ ## Deployment
304
+
305
+ A Uniweb project produces two artifacts — a **site** (content) and a **foundation** (code). **Who manages the content** decides what you ship:
306
+
307
+ - If you (or your dev team) manage the content, you ship them together — the site and its foundation, bundled or linked.
308
+ - If someone else manages the content, you ship only the foundation. Content authors compose sites in the Uniweb apps; there's no site to deploy from your repo.
309
+
310
+ ### Path 1 — You manage the content
311
+
312
+ You (or your dev team) write the markdown. Deploy site + foundation together.
313
+
314
+ The shortest path to a live site is free, on GitHub Pages, with a custom domain:
315
+
316
+ ```bash
317
+ uniweb create . # from within a freshly-cloned GitHub repo
318
+ uniweb add ci --host=github-pages
319
+ # Commit, push to GitHub, enable Pages in repo settings → live site
320
+ ```
321
+
322
+ `uniweb add ci` scaffolds a GitHub Actions workflow that runs `uniweb build` on each push. Pre-rendering is on by default — static HTML, fast first paint, SEO out of the box. Use `--domain=<domain>` for a custom domain.
323
+
324
+ **Other free static hosts.** Cloudflare Pages, Netlify, and Vercel work three ways: `uniweb add ci --host=<adapter>` scaffolds a workflow (and a per-PR preview that comments the URL), connecting the repo through their dashboard lets the host build it with no config at all, or `uniweb deploy --host=<adapter>` uploads from your machine.
325
+
326
+ **When to choose Uniweb hosting instead** (paid): when you need dynamic-page prerender at the edge (for collections fetched at runtime, not just at build time), foundation/runtime version propagation without redeploying every site, or edge SSR. If your site's content lives in markdown and updates ship via git, free CI is the right call.
327
+
328
+ ### Path 2 — Someone else manages the content
329
+
330
+ You're building a foundation for clients, content authors, or any team that won't write markdown. The foundation is your product; the repo's `site/` is a test harness for the code (run `pnpm dev` to preview your components against sample content). You don't deploy a site — you register a foundation:
331
+
332
+ ```bash
333
+ cd src
334
+ uniweb register --scope @your-org
335
+ ```
336
+
337
+ Real sites built on your foundation are managed in the **Uniweb apps** (web + desktop) — visual editors designed for non-technical authors. They never see git, markdown, yaml, or React. They see *your* components, with live previews and visual controls for the params you defined. The foundation becomes the editor's native vocabulary for that site: you keep creative control of the design system, they get an editor that feels custom-built for them.
338
+
339
+ This is the best path when site content has a life independent of the foundation's release cycle — agencies, design studios, multi-client teams, or any project where content authors aren't the same people as the developers.
340
+
341
+ ### Hybrid
342
+
343
+ Markdown in a git repo and content in the Uniweb apps can share the same site. Directional sync is available today: `uniweb push` sends local content to the backend, `uniweb pull` brings the backend's content back to local files, and `uniweb clone` bootstraps a local project from a site that already lives in the backend. Authors edit visually, devs edit in their IDE, both surfaces work on the same content. The advanced two-way-merge experience — conflict resolution, branch isolation, and review flows when both surfaces change the same content concurrently — is still evolving.
344
+
345
+ ### Commands at a glance
346
+
347
+ | Command | What it does |
348
+ | --- | --- |
349
+ | `uniweb deploy` | Ask where the site should go, then do it. Remembers the answer in `deploy.yml`. |
350
+ | `uniweb add ci --host=<adapter>` | Scaffold a CI workflow (+ PR previews) so every push deploys. `github-pages`, `cloudflare-pages`, `netlify`, `vercel`. |
351
+ | `uniweb add ci --target foundation` | Publish foundations at permanent versioned GitHub Pages URLs — the free alternative to the catalog. |
352
+ | `uniweb publish` | Go live on Uniweb hosting (paid) — syncs content, brings the site's foundation along, and serves dynamically. The canonical verb for Uniweb hosting. |
353
+ | `uniweb deploy --host=<adapter>` | Ship to a third-party static host in one step — builds `dist/`, uploads, invalidates. Drives that host's own CLI. |
354
+ | `uniweb export` | Produce a self-contained `dist/` for any static host. You upload it yourself. `--host=<adapter>` adds host-specific helper files. |
355
+ | `uniweb register --scope @org` | Register a foundation to the registry (path 2). |
356
+ | `uniweb build` | Inspect a build locally. For shipping, use `publish` (Uniweb hosting) or `deploy`/`export` (static hosts). |
357
+ | `uniweb update` | Align this project with the CLI you're running: bump `@uniweb/*` deps in every `package.json` to the CLI's matrix (then install), and refresh `AGENTS.md`. Pins to *this* CLI's matrix — run `npx uniweb@latest update` to align to the latest release. Updating the CLI itself is your package manager's job (`npm i -g uniweb@latest`). |
358
+
359
+ `--host=<adapter>` is the same option across `deploy`, `export`, and `add ci`. Built-in adapters: `github-pages`, `cloudflare-pages`, `netlify`, `vercel`, `s3-cloudfront`, and `generic-static` (an artifact shape for `export`, not a deploy target). Each adapter implements only the operations it supports, and the CLI never offers one it can't perform: `add ci` lists only hosts that can scaffold a workflow, and `deploy`'s picker lists only destinations with a working deploy hook.
360
+
361
+ ---
362
+
363
+ Both paths use the same framework. The difference is who edits content, where it lives, and what gets deployed. For the deeper menu — standalone vs cataloged foundations, S3+CloudFront, manual exports, per-host recipes, foundation propagation — see → **[Deploying](https://github.com/uniweb/docs/blob/main/development/deploying.md)**.
364
+
365
+ ---
366
+
367
+ ## Keeping a Project in Sync
368
+
369
+ Uniweb projects pin to specific `@uniweb/*` versions in their `package.json` files and ship an `AGENTS.md` stamped with the CLI version that wrote it. As the framework releases, both can drift from what the CLI you're running expects.
370
+
371
+ Two paired verbs cover the drift:
372
+
373
+ - **`uniweb doctor`** — diagnoses only. Flags `@uniweb/*` / `uniweb` declarations that lag the running CLI, plus `AGENTS.md` staleness, plus a small set of safely auto-fixable structural issues.
374
+ - **`uniweb update`** — the mutator. Rewrites `@uniweb/*` + `uniweb` version keys in every workspace `package.json` to the CLI's bundled matrix (deps that are *ahead* are left alone — never downgraded), runs your workspace's package manager, and refreshes `AGENTS.md`. Each file's existing indentation is preserved.
375
+
376
+ ```bash
377
+ npx uniweb@latest update # canonical: pin to the latest release (no install)
378
+ npx uniweb@latest update --yes # same, non-interactive (CI, agents, automation)
379
+ uniweb update --dry-run # preview the plan without touching files
380
+ ```
381
+
382
+ `update` aligns your project to *the CLI that's running it*. `npx uniweb@latest update` is the "pin to the newest release" path. A project-local copy (`node_modules/.bin/uniweb`) deliberately pins to your committed `uniweb` version — bump it in `package.json` and re-install, or use the npx form, to go further.
383
+
384
+ **Updating the CLI itself is separate**, and it's your package manager's job:
385
+
386
+ ```bash
387
+ npm i -g uniweb@latest # npm
388
+ pnpm add -g uniweb@latest # pnpm
389
+ yarn global add uniweb@latest # yarn
390
+ ```
391
+
392
+ `uniweb update` prints the right command for your install when a newer release exists. It will *not* update the CLI itself — running it twice was never the intent.
393
+
394
+ ---
395
+
396
+ ## Documentation
397
+
398
+ Full documentation is available at **[github.com/uniweb/docs](https://github.com/uniweb/docs)**:
399
+
400
+ | Section | Topics |
401
+ | ------- | ------ |
402
+ | [Getting Started](https://github.com/uniweb/docs/tree/main/getting-started) | Introduction, quickstart, templates |
403
+ | [Authoring](https://github.com/uniweb/docs/tree/main/authoring) | Writing content, site setup, theming, collections, translations |
404
+ | [Development](https://github.com/uniweb/docs/tree/main/development) | Building foundations, component patterns, data fetching, layouts |
405
+ | [Reference](https://github.com/uniweb/docs/tree/main/reference) | Configuration files, kit API, CLI commands, deployment |
406
+
407
+ ### Quick Reference
408
+
409
+ | Topic | Guide |
410
+ | ------------------ | ------------------------------------------------------------------- |
411
+ | Content Structure | [How markdown becomes component props](https://github.com/uniweb/docs/blob/main/reference/content-structure.md) |
412
+ | Component Metadata | [The meta.js schema](https://github.com/uniweb/docs/blob/main/reference/component-metadata.md) |
413
+ | Site Configuration | [site.yml reference](https://github.com/uniweb/docs/blob/main/reference/site-configuration.md) |
414
+ | CLI Commands | [All CLI commands and flags](https://github.com/uniweb/docs/blob/main/reference/cli-commands.md) |
415
+ | Templates | [Built-in, official, and external templates](https://github.com/uniweb/docs/blob/main/getting-started/templates.md) |
416
+ | Deployment | [Two artifacts, two verbs — bundled, linked, and per-host recipes](https://github.com/uniweb/docs/blob/main/development/deploying.md) |
417
+
418
+ ---
419
+
420
+ ## Configuration
421
+
422
+ ### Site Configuration
423
+
424
+ The `defineSiteConfig()` function handles all Vite configuration for sites:
425
+
426
+ ```javascript
427
+ import { defineSiteConfig } from '@uniweb/build/site'
428
+
429
+ export default defineSiteConfig({
430
+ // All options are optional
431
+ tailwind: true, // Enable Tailwind CSS v4 (default: true)
432
+ plugins: [], // Additional Vite plugins
433
+ // ...any other Vite config options
434
+ })
435
+ ```
436
+
437
+ ### Foundation Configuration
438
+
439
+ The `defineFoundationConfig()` function handles all Vite configuration for foundations:
440
+
441
+ ```javascript
442
+ import { defineFoundationConfig } from '@uniweb/build'
443
+
444
+ export default defineFoundationConfig({
445
+ // All options are optional - entry is auto-generated
446
+ fileName: 'foundation', // Output file name
447
+ externals: [], // Additional packages to externalize
448
+ includeDefaultExternals: true, // Include react, @uniweb/core, etc.
449
+ tailwind: true, // Enable Tailwind CSS v4 Vite plugin
450
+ sourcemap: true, // Generate sourcemaps
451
+ plugins: [], // Additional Vite plugins
452
+ build: {}, // Additional Vite build options
453
+ // ...any other Vite config options
454
+ })
455
+ ```
456
+
457
+ For Tailwind CSS v3 projects, set `tailwind: false` and use PostCSS:
458
+
459
+ ```javascript
460
+ export default defineFoundationConfig({
461
+ tailwind: false, // Uses PostCSS instead of Vite plugin
462
+ })
463
+ ```
464
+
465
+ ### Workspace Configuration
466
+
467
+ A default project has two packages, listed in both `pnpm-workspace.yaml` and `package.json`:
468
+
469
+ ```yaml
470
+ # pnpm-workspace.yaml
471
+ packages:
472
+ - src
473
+ - site
474
+ ```
475
+
476
+ In `package.json` (for npm compatibility):
477
+
478
+ ```json
479
+ {
480
+ "workspaces": ["src", "site"]
481
+ }
482
+ ```
483
+
484
+ When you `add` more packages, the CLI adds the appropriate workspaces automatically:
485
+
486
+ ```yaml
487
+ # After: uniweb add site marketing/blog
488
+ # After: uniweb add foundation marketing/blogger
489
+ packages:
490
+ - src
491
+ - site
492
+ - marketing/blog
493
+ - marketing/blogger
494
+ ```
495
+
496
+ ## FAQ
497
+
498
+ **How is this different from MDX?**
499
+
500
+ MDX blends markdown and JSX—content authors write code. Uniweb keeps them separate: content stays in markdown, components stay in React. Authors can still embed interactive components (via `![](@Component)` syntax), but they never see JSX. Component updates don't require content changes, and content changes can't break components.
501
+
502
+ **How is this different from Astro?**
503
+
504
+ Astro is a static site generator. Uniweb is a component content architecture that works with any deployment (static, SSR, or platform-managed). The foundation model means components are portable across sites and ready for integration with visual editors.
505
+
506
+ **Do I need uniweb.app?**
507
+
508
+ No. Local markdown files work great for developer-managed sites. The platform adds dynamic content, visual editing, and team collaboration when you need it.
509
+
510
+ **Can I use an existing component library?**
511
+
512
+ Yes. Foundations are standard React. Import any library into your foundation components. The `{ content, params }` interface only applies to section types (components with `meta.js`) — everything else uses regular React props.
513
+
514
+ **Is this SEO-friendly?**
515
+
516
+ Yes. Content is pre-embedded in the initial HTML—no fetch waterfalls, no layout shifts. Meta tags are generated per page. SSG is supported by default.
517
+
518
+ **What about dynamic routes?**
519
+
520
+ Pages can define data sources that auto-generate subroutes. A `/blog` page can have an index and a `[slug]` template that renders each post.
521
+
522
+ **Is Uniweb good for documentation sites?**
523
+
524
+ Yes — documentation is a natural fit. Content stays in markdown (easy to version, review, and contribute to), while the foundation handles navigation, search, and rendering. [Uniweb's own docs](https://github.com/uniweb/docs) use this pattern: pure markdown in a public repo, rendered by a separate foundation.
525
+
526
+ ## Related Packages
527
+
528
+ - [`@uniweb/build`](https://github.com/uniweb/build) — Foundation build tooling
529
+ - [`@uniweb/runtime`](https://github.com/uniweb/runtime) — Foundation loader and orchestrator for sites
530
+ - [`@uniweb/templates`](https://github.com/uniweb/templates) — Official project templates (content only, CLI provides structure)
531
+
532
+ ## License
533
+
534
+ Apache 2.0
package/package.json CHANGED
@@ -1,19 +1,68 @@
1
1
  {
2
2
  "name": "uniweb",
3
- "version": "1.0.0",
4
- "description": "",
5
- "main": "index.js",
6
- "scripts": {
7
- "test": "echo \"Error: no test specified\" && exit 1"
3
+ "version": "1.0.2",
4
+ "description": "Create structured Vite + React sites with content/code separation",
5
+ "type": "module",
6
+ "bin": {
7
+ "uniweb": "src/index.js"
8
+ },
9
+ "exports": {
10
+ "./processor": "./src/templates/processor.js"
8
11
  },
12
+ "files": [
13
+ "src",
14
+ "templates",
15
+ "partials",
16
+ "starter"
17
+ ],
18
+ "keywords": [
19
+ "uniweb",
20
+ "cli",
21
+ "scaffold",
22
+ "foundation",
23
+ "components",
24
+ "vite"
25
+ ],
26
+ "author": "Proximify",
27
+ "license": "Apache-2.0",
9
28
  "repository": {
10
29
  "type": "git",
11
- "url": "git+https://github.com/npm/deprecate-holder.git"
30
+ "url": "git+https://github.com/uniweb/cli.git"
12
31
  },
13
- "author": "",
14
- "license": "ISC",
32
+ "homepage": "https://github.com/uniweb/cli#readme",
15
33
  "bugs": {
16
- "url": "https://github.com/npm/deprecate-holder/issues"
34
+ "url": "https://github.com/uniweb/cli/issues"
35
+ },
36
+ "engines": {
37
+ "node": ">=20.19"
38
+ },
39
+ "dependencies": {
40
+ "handlebars": "^4.7.8",
41
+ "js-yaml": "^4.1.0",
42
+ "prompts": "^2.4.2",
43
+ "tar": "^7.0.0",
44
+ "@uniweb/content-writer": "~1.0.1",
45
+ "@uniweb/core": "~1.0.1",
46
+ "@uniweb/semantic-parser": "~1.5.1",
47
+ "@uniweb/schemas": "~1.0.1"
17
48
  },
18
- "homepage": "https://github.com/npm/deprecate-holder#readme"
19
- }
49
+ "peerDependencies": {
50
+ "@uniweb/build": "~1.0.1",
51
+ "@uniweb/semantic-parser": "~1.5.1",
52
+ "@uniweb/content-reader": "~1.2.8"
53
+ },
54
+ "peerDependenciesMeta": {
55
+ "@uniweb/build": {
56
+ "optional": true
57
+ },
58
+ "@uniweb/content-reader": {
59
+ "optional": true
60
+ },
61
+ "@uniweb/semantic-parser": {
62
+ "optional": true
63
+ }
64
+ },
65
+ "scripts": {
66
+ "test": "node --test 'test/**/*.test.js'"
67
+ }
68
+ }