uniweb 0.1.4 → 0.1.6

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +336 -11
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uniweb",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "CLI for the Uniweb Component Web Platform",
5
5
  "type": "module",
6
6
  "bin": {
package/src/index.js CHANGED
@@ -261,6 +261,119 @@ async function createWorkspace(projectDir, projectName) {
261
261
  dist
262
262
  .DS_Store
263
263
  *.local
264
+ `)
265
+
266
+ // README.md
267
+ writeFile(join(projectDir, 'README.md'), `# ${projectName}
268
+
269
+ A Uniweb workspace with a site and foundation for co-development.
270
+
271
+ ## Quick Start
272
+
273
+ \`\`\`bash
274
+ pnpm install
275
+ pnpm dev
276
+ \`\`\`
277
+
278
+ Open [http://localhost:3000](http://localhost:3000) to see your site.
279
+
280
+ ## Project Structure
281
+
282
+ \`\`\`
283
+ ${projectName}/
284
+ ├── packages/
285
+ │ ├── site/ # Your website
286
+ │ │ ├── pages/ # Content pages (markdown + YAML)
287
+ │ │ ├── src/ # Site entry point
288
+ │ │ └── vite.config.js
289
+ │ └── foundation/ # Your component library
290
+ │ └── src/
291
+ │ ├── components/ # React components
292
+ │ ├── meta.js # Foundation metadata
293
+ │ └── styles.css # Tailwind styles
294
+ ├── package.json
295
+ └── pnpm-workspace.yaml
296
+ \`\`\`
297
+
298
+ ## Development
299
+
300
+ ### Standard Mode (recommended)
301
+
302
+ \`\`\`bash
303
+ pnpm dev
304
+ \`\`\`
305
+
306
+ Edit components in \`packages/foundation/src/components/\` and see changes instantly via HMR.
307
+ Edit content in \`packages/site/pages/\` to add or modify pages.
308
+
309
+ ### Runtime Loading Mode
310
+
311
+ \`\`\`bash
312
+ pnpm dev:runtime
313
+ \`\`\`
314
+
315
+ Tests production behavior where the foundation is loaded as a separate module.
316
+ Use this to debug issues that only appear in production.
317
+
318
+ ## Building for Production
319
+
320
+ \`\`\`bash
321
+ # Build both foundation and site
322
+ pnpm build
323
+ \`\`\`
324
+
325
+ Output:
326
+ - \`packages/foundation/dist/\` — Bundled foundation (JS + CSS + schema)
327
+ - \`packages/site/dist/\` — Production-ready site
328
+
329
+ ## Adding Components
330
+
331
+ 1. Create a new folder in \`packages/foundation/src/components/YourComponent/\`
332
+ 2. Add \`index.jsx\` with your React component
333
+ 3. Add \`meta.js\` describing the component's content slots and options
334
+ 4. Export from \`packages/foundation/src/index.js\`
335
+
336
+ ## Adding Pages
337
+
338
+ 1. Create a folder in \`packages/site/pages/your-page/\`
339
+ 2. Add \`page.yml\` with page metadata
340
+ 3. Add markdown files (\`1-section.md\`, \`2-section.md\`, etc.) for each section
341
+
342
+ Each markdown file specifies which component to use:
343
+
344
+ \`\`\`markdown
345
+ ---
346
+ component: Hero
347
+ title: Your Title
348
+ subtitle: Your subtitle
349
+ ---
350
+
351
+ Optional body content here.
352
+ \`\`\`
353
+
354
+ ## Configuration
355
+
356
+ Each site has a \`site.yml\` that configures which foundation it uses:
357
+
358
+ \`\`\`yaml
359
+ name: site
360
+ defaultLanguage: en
361
+ foundation: foundation # References packages/foundation
362
+ \`\`\`
363
+
364
+ To add multiple sites or foundations, create new packages and update each site's \`site.yml\`.
365
+
366
+ ## What is Uniweb?
367
+
368
+ Uniweb is a **Component Web Platform** that bridges content and components.
369
+ Foundations define the vocabulary (available components, options, design rules).
370
+ Sites provide content that flows through Foundations.
371
+
372
+ Learn more:
373
+ - [Uniweb on GitHub](https://github.com/uniweb)
374
+ - [CLI Documentation](https://github.com/uniweb/cli)
375
+ - [uniweb.app](https://uniweb.app) — Full publishing platform
376
+
264
377
  `)
265
378
 
266
379
  // Create site package
@@ -301,6 +414,7 @@ async function createSite(projectDir, projectName, isWorkspace = false) {
301
414
  devDependencies: {
302
415
  '@vitejs/plugin-react': '^4.2.1',
303
416
  autoprefixer: '^10.4.18',
417
+ 'js-yaml': '^4.1.0',
304
418
  postcss: '^8.4.35',
305
419
  react: '^18.2.0',
306
420
  'react-dom': '^18.2.0',
@@ -311,13 +425,24 @@ async function createSite(projectDir, projectName, isWorkspace = false) {
311
425
  },
312
426
  })
313
427
 
314
- // Foundation import name
428
+ // Foundation import name (used for initial site.yml)
315
429
  const foundationImport = isWorkspace ? 'foundation' : 'foundation-example'
316
430
 
317
- // tailwind.config.js - scan foundation components
318
- const foundationPath = isWorkspace ? '../foundation' : `./node_modules/${foundationImport}`
319
- writeFile(join(projectDir, 'tailwind.config.js'), `export default {
320
- content: ['${foundationPath}/src/**/*.{js,jsx,ts,tsx}'],
431
+ // tailwind.config.js - reads foundation from site.yml
432
+ writeFile(join(projectDir, 'tailwind.config.js'), `import { readFileSync, existsSync } from 'fs'
433
+ import yaml from 'js-yaml'
434
+
435
+ // Read foundation from site.yml
436
+ const siteConfig = yaml.load(readFileSync('./site.yml', 'utf8'))
437
+ const foundation = siteConfig.foundation || 'foundation'
438
+
439
+ // Resolve foundation path (workspace sibling or node_modules)
440
+ const workspacePath = \`../\${foundation}/src/**/*.{js,jsx,ts,tsx}\`
441
+ const npmPath = \`./node_modules/\${foundation}/src/**/*.{js,jsx,ts,tsx}\`
442
+ const contentPath = existsSync(\`../\${foundation}\`) ? workspacePath : npmPath
443
+
444
+ export default {
445
+ content: [contentPath],
321
446
  theme: {
322
447
  extend: {
323
448
  colors: {
@@ -339,15 +464,31 @@ async function createSite(projectDir, projectName, isWorkspace = false) {
339
464
  }
340
465
  `)
341
466
 
342
- // vite.config.js
467
+ // vite.config.js - reads foundation from site.yml
343
468
  writeFile(join(projectDir, 'vite.config.js'), `import { defineConfig } from 'vite'
469
+ import { readFileSync, existsSync } from 'fs'
470
+ import yaml from 'js-yaml'
344
471
  import react from '@vitejs/plugin-react'
345
472
  import svgr from 'vite-plugin-svgr'
346
473
  import { siteContentPlugin, foundationPlugin } from '@uniweb/runtime/vite'
347
474
 
475
+ // Read foundation from site.yml
476
+ const siteConfig = yaml.load(readFileSync('./site.yml', 'utf8'))
477
+ const foundation = siteConfig.foundation || 'foundation'
478
+
479
+ // Check if foundation is a workspace sibling or npm package
480
+ const isWorkspaceFoundation = existsSync(\`../\${foundation}\`)
481
+ const foundationPath = isWorkspaceFoundation ? \`../\${foundation}\` : \`./node_modules/\${foundation}\`
482
+
348
483
  const useRuntimeLoading = process.env.VITE_FOUNDATION_MODE === 'runtime'
349
484
 
350
485
  export default defineConfig({
486
+ resolve: {
487
+ alias: {
488
+ // Alias #foundation to the actual foundation package
489
+ '#foundation': foundation,
490
+ },
491
+ },
351
492
  plugins: [
352
493
  react(),
353
494
  svgr(),
@@ -356,8 +497,8 @@ export default defineConfig({
356
497
  inject: true,
357
498
  }),
358
499
  useRuntimeLoading && foundationPlugin({
359
- name: '${foundationImport}',
360
- path: ${isWorkspace ? "'../foundation'" : "require.resolve('" + foundationImport + "').replace('/src/index.js', '')"},
500
+ name: foundation,
501
+ path: foundationPath,
361
502
  serve: '/foundation',
362
503
  watch: true,
363
504
  }),
@@ -390,7 +531,7 @@ export default defineConfig({
390
531
  </html>
391
532
  `)
392
533
 
393
- // main.jsx
534
+ // main.jsx - uses #foundation alias (configured in vite.config.js from site.yml)
394
535
  writeFile(join(projectDir, 'src/main.jsx'), `import { initRuntime } from '@uniweb/runtime'
395
536
 
396
537
  const useRuntimeLoading = import.meta.env.VITE_FOUNDATION_MODE === 'runtime'
@@ -402,8 +543,9 @@ async function start() {
402
543
  cssUrl: '/foundation/assets/style.css'
403
544
  })
404
545
  } else {
405
- const foundation = await import('${foundationImport}')
406
- await import('${foundationImport}/styles')
546
+ // #foundation alias is resolved by Vite based on site.yml config
547
+ const foundation = await import('#foundation')
548
+ await import('#foundation/styles')
407
549
  initRuntime(foundation)
408
550
  }
409
551
  }
@@ -414,6 +556,9 @@ start().catch(console.error)
414
556
  // site.yml
415
557
  writeFile(join(projectDir, 'site.yml'), `name: ${projectName}
416
558
  defaultLanguage: en
559
+
560
+ # Foundation to use for this site
561
+ foundation: ${foundationImport}
417
562
  `)
418
563
 
419
564
  // pages/home/page.yml
@@ -433,6 +578,93 @@ ctaUrl: "#"
433
578
  Your content goes here.
434
579
  `)
435
580
 
581
+ // README.md (only for standalone site, not workspace)
582
+ if (!isWorkspace) {
583
+ writeFile(join(projectDir, 'README.md'), `# ${projectName}
584
+
585
+ A Uniweb site — a content-driven website powered by a Foundation component library.
586
+
587
+ ## Quick Start
588
+
589
+ \`\`\`bash
590
+ pnpm install
591
+ pnpm dev
592
+ \`\`\`
593
+
594
+ Open [http://localhost:3000](http://localhost:3000) to see your site.
595
+
596
+ ## Project Structure
597
+
598
+ \`\`\`
599
+ ${projectName}/
600
+ ├── pages/ # Your content
601
+ │ └── home/
602
+ │ ├── page.yml # Page metadata
603
+ │ └── 1-hero.md # Section content
604
+ ├── src/
605
+ │ └── main.jsx # Site entry point
606
+ ├── site.yml # Site configuration
607
+ ├── vite.config.js
608
+ └── package.json
609
+ \`\`\`
610
+
611
+ ## Adding Pages
612
+
613
+ 1. Create a folder in \`pages/your-page/\`
614
+ 2. Add \`page.yml\`:
615
+
616
+ \`\`\`yaml
617
+ title: Your Page Title
618
+ order: 2
619
+ \`\`\`
620
+
621
+ 3. Add section files (\`1-hero.md\`, \`2-features.md\`, etc.):
622
+
623
+ \`\`\`markdown
624
+ ---
625
+ component: Hero
626
+ title: Section Title
627
+ subtitle: Section subtitle
628
+ ---
629
+
630
+ Optional markdown content here.
631
+ \`\`\`
632
+
633
+ ## How It Works
634
+
635
+ - Each folder in \`pages/\` becomes a route (\`/home\`, \`/about\`, etc.)
636
+ - Section files are numbered to control order (\`1-*.md\`, \`2-*.md\`)
637
+ - The \`component\` field specifies which Foundation component renders the section
638
+ - Other frontmatter fields become the component's content
639
+
640
+ ## Configuration
641
+
642
+ The \`site.yml\` file configures your site:
643
+
644
+ \`\`\`yaml
645
+ name: ${projectName}
646
+ defaultLanguage: en
647
+ foundation: ${foundationImport} # Which foundation to use
648
+ \`\`\`
649
+
650
+ To use a different foundation, update the \`foundation\` field and install the package.
651
+
652
+ ## Building for Production
653
+
654
+ \`\`\`bash
655
+ pnpm build
656
+ \`\`\`
657
+
658
+ Output is in \`dist/\` — ready to deploy to any static host.
659
+
660
+ ## Learn More
661
+
662
+ - [Uniweb on GitHub](https://github.com/uniweb)
663
+ - [uniweb.app](https://uniweb.app)
664
+
665
+ `)
666
+ }
667
+
436
668
  success(`Created site: ${projectName}`)
437
669
  }
438
670
 
@@ -677,6 +909,99 @@ export default {
677
909
  }
678
910
  `)
679
911
 
912
+ // README.md (only for standalone foundation, not workspace)
913
+ if (!isWorkspace) {
914
+ writeFile(join(projectDir, 'README.md'), `# ${projectName}
915
+
916
+ A Uniweb Foundation — a React component library for content-driven websites.
917
+
918
+ ## Quick Start
919
+
920
+ \`\`\`bash
921
+ pnpm install
922
+ pnpm dev # Start Vite dev server for component development
923
+ pnpm build # Build for production
924
+ \`\`\`
925
+
926
+ ## Project Structure
927
+
928
+ \`\`\`
929
+ ${projectName}/
930
+ ├── src/
931
+ │ ├── components/ # Your components
932
+ │ │ └── Hero/
933
+ │ │ ├── index.jsx # React component
934
+ │ │ └── meta.js # Component metadata
935
+ │ ├── meta.js # Foundation metadata
936
+ │ ├── index.js # Exports
937
+ │ └── styles.css # Tailwind styles
938
+ ├── package.json
939
+ ├── vite.config.js
940
+ └── tailwind.config.js
941
+ \`\`\`
942
+
943
+ ## Adding Components
944
+
945
+ 1. Create \`src/components/YourComponent/index.jsx\`:
946
+
947
+ \`\`\`jsx
948
+ export function YourComponent({ content }) {
949
+ const { title, description } = content
950
+ return (
951
+ <section className="py-12 px-6">
952
+ <h2>{title}</h2>
953
+ <p>{description}</p>
954
+ </section>
955
+ )
956
+ }
957
+
958
+ export default YourComponent
959
+ \`\`\`
960
+
961
+ 2. Create \`src/components/YourComponent/meta.js\`:
962
+
963
+ \`\`\`js
964
+ export default {
965
+ title: 'Your Component',
966
+ description: 'What this component does',
967
+ category: 'Content',
968
+ elements: {
969
+ title: { label: 'Title', required: true },
970
+ description: { label: 'Description' },
971
+ },
972
+ }
973
+ \`\`\`
974
+
975
+ 3. Export from \`src/index.js\`:
976
+
977
+ \`\`\`js
978
+ export { YourComponent } from './components/YourComponent/index.jsx'
979
+ \`\`\`
980
+
981
+ ## Build Output
982
+
983
+ After \`pnpm build\`:
984
+
985
+ \`\`\`
986
+ dist/
987
+ ├── foundation.js # Bundled components
988
+ ├── assets/style.css # Compiled Tailwind CSS
989
+ └── schema.json # Component metadata for editors
990
+ \`\`\`
991
+
992
+ ## What is a Foundation?
993
+
994
+ A Foundation defines the vocabulary for Uniweb sites:
995
+ - **Components** — The building blocks creators can use
996
+ - **Elements** — Content slots (title, description, images, etc.)
997
+ - **Properties** — Configuration options exposed to creators
998
+ - **Presets** — Pre-configured variations of components
999
+
1000
+ Learn more at [github.com/uniweb](https://github.com/uniweb)
1001
+
1002
+ `)
1003
+ }
1004
+
680
1005
  success(`Created foundation: ${projectName}`)
681
1006
  }
682
1007