@janga/norna 0.7.13 → 0.7.15

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 (146) hide show
  1. package/README.md +15 -9
  2. package/bin/norna-cli.mjs +11 -4
  3. package/docs/README.md +71 -43
  4. package/docs/commands.md +34 -20
  5. package/docs/configuration.md +43 -62
  6. package/docs/content.md +34 -7
  7. package/docs/design/command-organization.md +15 -8
  8. package/docs/design/norna-diagram-design.md +6 -6
  9. package/docs/design/site-examples-structure.md +1 -1
  10. package/docs/engine-development.md +22 -9
  11. package/docs/getting-started.md +29 -16
  12. package/docs/how-to/embedded-site.md +1 -1
  13. package/docs/images-and-metadata.md +3 -3
  14. package/docs/local-development.md +11 -3
  15. package/docs/public-files.md +105 -0
  16. package/docs/publishing.md +4 -8
  17. package/docs/routes.md +6 -7
  18. package/docs/site-files.md +144 -0
  19. package/docs/sitewide-content.md +47 -33
  20. package/docs/theme.md +37 -49
  21. package/docs/typography.md +25 -31
  22. package/examples/complete-sites/dog-shelter-multi-page/README.md +8 -0
  23. package/examples/complete-sites/{dog-shelter-single-page/site/config.md → dog-shelter-multi-page/site/config.yaml} +0 -2
  24. package/examples/complete-sites/dog-shelter-multi-page/site/sitewide-content.yaml +6 -0
  25. package/examples/complete-sites/dog-shelter-multi-page/site/{theme.md → theme.yaml} +0 -2
  26. package/examples/complete-sites/dog-shelter-single-page/README.md +8 -0
  27. package/examples/complete-sites/{dog-shelter-multi-page/site/config.md → dog-shelter-single-page/site/config.yaml} +0 -2
  28. package/examples/complete-sites/dog-shelter-single-page/site/sitewide-content.yaml +6 -0
  29. package/examples/complete-sites/dog-shelter-single-page/site/{theme.md → theme.yaml} +0 -2
  30. package/examples/feature-demos/media-and-surfaces/.astro/data-store.json +1 -1
  31. package/examples/feature-demos/media-and-surfaces/README.md +1 -1
  32. package/examples/feature-demos/media-and-surfaces/site/{config.md → config.yaml} +0 -2
  33. package/examples/feature-demos/media-and-surfaces/site/content.md +2 -2
  34. package/examples/feature-demos/media-and-surfaces/site/routes/020-surfaces/{route-content.md → content.md} +3 -7
  35. package/examples/feature-demos/media-and-surfaces/site/routes/020-surfaces/theme.yaml +3 -0
  36. package/examples/feature-demos/media-and-surfaces/site/{sitewide-content.md → sitewide-content.yaml} +1 -3
  37. package/examples/feature-demos/media-and-surfaces/site/{theme.md → theme.yaml} +0 -2
  38. package/examples/feature-demos/sitewide-content/README.md +8 -0
  39. package/examples/feature-demos/sitewide-content/site/{config.md → config.yaml} +0 -2
  40. package/examples/feature-demos/sitewide-content/site/routes/010-identity/{route-content.md → content.md} +3 -3
  41. package/examples/feature-demos/sitewide-content/site/routes/020-notices/{route-content.md → content.md} +1 -1
  42. package/examples/feature-demos/sitewide-content/site/routes/030-footer/{route-content.md → content.md} +1 -1
  43. package/examples/feature-demos/sitewide-content/site/{sitewide-content.md → sitewide-content.yaml} +1 -11
  44. package/examples/feature-demos/sitewide-content/site/{theme.md → theme.yaml} +0 -2
  45. package/examples/feature-demos/theme-presets/site/config.yaml +1 -0
  46. package/examples/feature-demos/theme-presets/site/routes/010-portfolio/{theme.md → theme.yaml} +0 -2
  47. package/examples/feature-demos/theme-presets/site/routes/020-documentation/{theme.md → theme.yaml} +0 -2
  48. package/examples/feature-demos/theme-presets/site/routes/030-project/theme.yaml +1 -0
  49. package/examples/feature-demos/theme-presets/site/routes/040-statement/{route-content.md → content.md} +1 -1
  50. package/examples/feature-demos/theme-presets/site/routes/040-statement/{theme.md → theme.yaml} +0 -2
  51. package/examples/feature-demos/theme-presets/site/{sitewide-content.md → sitewide-content.yaml} +1 -3
  52. package/examples/feature-demos/theme-presets/site/theme.yaml +1 -0
  53. package/fixtures/basic/site/{config.md → config.yaml} +0 -2
  54. package/fixtures/basic/site/content.md +3 -3
  55. package/fixtures/basic/site/{sitewide-content.md → sitewide-content.yaml} +0 -2
  56. package/fixtures/basic/site/{theme.md → theme.yaml} +3 -6
  57. package/fixtures/content-model-v2/site/{config.md → config.yaml} +0 -2
  58. package/fixtures/content-model-v2/site/theme.yaml +4 -0
  59. package/package.json +10 -3
  60. package/schemas/config.schema.json +77 -0
  61. package/schemas/content-frontmatter.schema.json +81 -0
  62. package/schemas/manifest.json +9 -0
  63. package/schemas/sitewide-content.schema.json +215 -0
  64. package/schemas/theme.schema.json +1208 -0
  65. package/scripts/check-config.mjs +18 -11
  66. package/scripts/export-theme-preset.mjs +1 -1
  67. package/scripts/generate-schemas.mjs +283 -0
  68. package/scripts/init-site.mjs +22 -27
  69. package/scripts/lib/documentation-links.mjs +8 -0
  70. package/scripts/lib/editor-language-service.mjs +609 -0
  71. package/scripts/lib/example-sites.mjs +2 -2
  72. package/scripts/lib/git-status.mjs +7 -0
  73. package/scripts/lib/logo-assets.mjs +15 -10
  74. package/scripts/lib/norna-markdown-blocks.mjs +90 -11
  75. package/scripts/lib/presentation.mjs +23 -12
  76. package/scripts/lib/project-config.mjs +17 -41
  77. package/scripts/lib/public-asset-conventions.mjs +112 -0
  78. package/scripts/lib/schema-definitions.mjs +213 -0
  79. package/scripts/lib/schema-value-definitions.mjs +86 -0
  80. package/scripts/lib/site-content.mjs +24 -18
  81. package/scripts/lib/site-paths.mjs +4 -8
  82. package/scripts/lib/sitewide-content.mjs +24 -0
  83. package/scripts/lib/theme-config.mjs +15 -35
  84. package/scripts/lib/theme-presets.mjs +76 -66
  85. package/scripts/lib/typography.mjs +15 -15
  86. package/scripts/lib/yaml-config.mjs +50 -0
  87. package/scripts/list-theme-presets.mjs +15 -0
  88. package/scripts/release.mjs +84 -8
  89. package/scripts/show-typography.mjs +22 -46
  90. package/scripts/sync-content-sections.mjs +2 -2
  91. package/scripts/test-client-javascript.mjs +28 -28
  92. package/scripts/test-content-check.mjs +21 -26
  93. package/scripts/test-content-model-v2.mjs +72 -40
  94. package/scripts/test-documentation.mjs +70 -4
  95. package/scripts/test-editor-language-service.mjs +158 -0
  96. package/scripts/test-engine-commands.mjs +65 -34
  97. package/scripts/test-package-check.mjs +37 -30
  98. package/scripts/test-project-config.mjs +15 -20
  99. package/scripts/test-schemas.mjs +102 -0
  100. package/scripts/test-temporary-visibility.mjs +5 -13
  101. package/scripts/test-theme-presets.mjs +64 -37
  102. package/src/components/CardList.astro +2 -5
  103. package/src/components/ImageCarousel.astro +21 -21
  104. package/src/components/{GalleryGrid.astro → ImageStack.astro} +12 -12
  105. package/src/components/SectionNavigationScript.astro +28 -0
  106. package/src/components/SiteNavigation.astro +6 -5
  107. package/src/components/SitePage.astro +8 -8
  108. package/src/components/SiteSection.astro +18 -21
  109. package/src/content.config.ts +17 -209
  110. package/src/layouts/BaseLayout.astro +9 -9
  111. package/src/lib/{galleryImages.ts → imagePresentation.ts} +7 -7
  112. package/src/lib/routeThemes.ts +9 -29
  113. package/src/lib/sectionContent.ts +3 -3
  114. package/src/lib/sitePublicAssets.ts +5 -21
  115. package/src/styles/global.css +73 -73
  116. package/starters/basic/.github/workflows/deploy.yml +1 -1
  117. package/starters/basic/README.md +16 -13
  118. package/starters/basic/package.json +3 -2
  119. package/starters/basic/site/{config.md → config.yaml} +0 -2
  120. package/starters/basic/site/content.md +1 -1
  121. package/starters/basic/site/{sitewide-content.md → sitewide-content.yaml} +1 -3
  122. package/starters/basic/site/{theme.md → theme.yaml} +8 -15
  123. package/starters/project/.github/workflows/deploy.yml +1 -1
  124. package/starters/project/README.md +22 -15
  125. package/starters/project/package.json +3 -2
  126. package/starters/project/site/{config.md → config.yaml} +0 -2
  127. package/starters/project/site/{sitewide-content.md → sitewide-content.yaml} +1 -3
  128. package/starters/project/site/{theme.md → theme.yaml} +4 -8
  129. package/docs/site-structure.md +0 -98
  130. package/examples/complete-sites/dog-shelter-multi-page/site/sitewide-content.md +0 -16
  131. package/examples/complete-sites/dog-shelter-single-page/site/sitewide-content.md +0 -16
  132. package/examples/feature-demos/media-and-surfaces/site/routes/020-surfaces/theme.md +0 -8
  133. package/examples/feature-demos/theme-presets/site/config.md +0 -3
  134. package/examples/feature-demos/theme-presets/site/routes/030-project/theme.md +0 -3
  135. package/examples/feature-demos/theme-presets/site/theme.md +0 -3
  136. package/fixtures/content-model-v2/site/theme.md +0 -7
  137. package/scripts/lib/sitewide-config.mjs +0 -34
  138. package/src/components/MobileSectionNavigationScript.astro +0 -14
  139. /package/examples/complete-sites/dog-shelter-multi-page/site/routes/010-dogs/{route-content.md → content.md} +0 -0
  140. /package/examples/complete-sites/dog-shelter-multi-page/site/routes/020-adopt/{route-content.md → content.md} +0 -0
  141. /package/examples/feature-demos/media-and-surfaces/site/routes/010-media/{route-content.md → content.md} +0 -0
  142. /package/examples/feature-demos/theme-presets/site/routes/010-portfolio/{route-content.md → content.md} +0 -0
  143. /package/examples/feature-demos/theme-presets/site/routes/020-documentation/{route-content.md → content.md} +0 -0
  144. /package/examples/feature-demos/theme-presets/site/routes/030-project/{route-content.md → content.md} +0 -0
  145. /package/fixtures/content-model-v2/site/routes/010-guide/{route-content.md → content.md} +0 -0
  146. /package/starters/project/site/routes/010-guide/{route-content.md → content.md} +0 -0
@@ -0,0 +1,144 @@
1
+ # Site Files
2
+
3
+ Norna expects a defined set of files and directories. Their names and locations
4
+ are part of the site model: following the structure lets Norna find content,
5
+ presentation, configuration, routes, and assets without path configuration.
6
+
7
+ The selected site directory is `site/` by default:
8
+
9
+ ```text
10
+ site/
11
+ |-- config.yaml
12
+ |-- theme.yaml
13
+ |-- sitewide-content.yaml
14
+ |-- content.md
15
+ |-- images/
16
+ | `-- <section-id>/
17
+ |-- routes/
18
+ | `-- <NNN-route-id>/
19
+ | |-- content.md
20
+ | |-- theme.yaml
21
+ | `-- images/
22
+ | `-- <section-id>/
23
+ |-- public/
24
+ `-- .norna/
25
+ |-- generated-images.json
26
+ `-- public/
27
+ ```
28
+
29
+ File and directory names shown literally above must use that exact lowercase
30
+ spelling. This keeps sites portable between case-sensitive and
31
+ case-insensitive file systems.
32
+
33
+ ## Root Files
34
+
35
+ | Path | Required | Responsibility |
36
+ | --- | --- | --- |
37
+ | `config.yaml` | Yes | Public URL, language, and browser scroll behavior. |
38
+ | `theme.yaml` | Yes | Complete visual preset and optional focused overrides. |
39
+ | `sitewide-content.yaml` | No | Shared navigation identity, banners, and footer. |
40
+ | `content.md` | Yes | Homepage metadata, sections, prose, and Norna blocks. |
41
+
42
+ These responsibilities are deliberately separate:
43
+
44
+ - [`config.yaml`](configuration.md) contains the few technical settings that
45
+ apply to the whole site.
46
+ - [`theme.yaml`](theme.md) controls presentation. A normal file can contain
47
+ only a preset selection.
48
+ - [`sitewide-content.yaml`](sitewide-content.md) contains editorial material
49
+ shared by every page.
50
+ - [`content.md`](content.md) is the homepage page file and remains ordinary
51
+ Markdown with YAML frontmatter.
52
+
53
+ Routes cannot provide `config.yaml` or `sitewide-content.yaml`. Technical
54
+ configuration and shared identity have one site-wide source.
55
+
56
+ ## Images
57
+
58
+ Managed homepage images belong in:
59
+
60
+ ```text
61
+ site/images/<section-id>/
62
+ ```
63
+
64
+ The directory name must match an explicit level 2 Markdown section id in
65
+ `content.md`. Markdown blocks refer to managed images by filename, not by path.
66
+ See [Images and Metadata](images-and-metadata.md) for supported formats,
67
+ generated variants, and syncing.
68
+
69
+ ## Routes
70
+
71
+ Each first-level route is one directory under `routes/`:
72
+
73
+ ```text
74
+ site/routes/010-guide/
75
+ |-- content.md
76
+ |-- theme.yaml
77
+ `-- images/
78
+ `-- intro/
79
+ ```
80
+
81
+ `content.md` is required for a route. The optional route `theme.yaml` replaces
82
+ the root visual theme for that route. Route images follow the same
83
+ `images/<section-id>/` convention as homepage images.
84
+
85
+ The three-digit route prefix controls navigation order and is not part of the
86
+ URL. See [Routes](routes.md) for exact directory-name and route-id rules.
87
+
88
+ ## Public Files
89
+
90
+ `site/public/` contains static files copied without image processing. Most
91
+ names are site-owned, but Norna recognizes a small set of exact conventional
92
+ filenames for the navigation logo and browser icons.
93
+
94
+ See [Public Files](public-files.md) for logo and favicon filenames, arbitrary
95
+ static files, root-relative links, and publishing paths.
96
+
97
+ ## Selecting The Site Directory
98
+
99
+ Use `NORNA_SITE_DIR` or `norna --site-dir <path>` to select a site directory
100
+ explicitly.
101
+
102
+ Without an explicit selection, Norna first accepts the current directory when
103
+ it contains both `config.yaml` and `content.md`. Otherwise it walks upward until
104
+ it finds a default `site/` directory containing those two files.
105
+
106
+ ## Versioned Files
107
+
108
+ Version the source files above together with:
109
+
110
+ - `site/.norna/generated-images.json`, which records reusable managed-image
111
+ output;
112
+ - `.github/workflows/deploy.yml`, when using the included GitHub Pages
113
+ publishing integration;
114
+ - `package.json` and `package-lock.json`, which pin the local Norna engine and
115
+ project scripts.
116
+
117
+ Source images and files under `site/public/` are also versioned site input.
118
+
119
+ ## Generated Files
120
+
121
+ Do not edit these by hand:
122
+
123
+ - `site/.norna/public/`: build-preparation output copied from `site/public/`,
124
+ plus generated or copied managed images;
125
+ - `dist/`: final static website output;
126
+ - `.astro/`: Astro cache, generated types, and local dev-server state.
127
+
128
+ `norna site:public` removes stale copied static files from
129
+ `site/.norna/public/` while preserving managed image output under its `images/`
130
+ directory.
131
+
132
+ ## Engine Repository Layout
133
+
134
+ These directories belong to the Norna engine repository, not to an ordinary
135
+ site:
136
+
137
+ - `bin/`: the launcher and public CLI dispatcher;
138
+ - `scripts/`: validation, image, preview, publishing, and test tools;
139
+ - `src/`: the Astro renderer, components, styles, and content schema;
140
+ - `starters/`: source copied by `norna init`;
141
+ - `examples/`: complete sites and focused feature demonstrations;
142
+ - `fixtures/`: engine regression input;
143
+ - root `site/`: the Norna introduction and documentation site.
144
+
@@ -1,38 +1,49 @@
1
- # Sitewide Content
1
+ # `sitewide-content.yaml`
2
2
 
3
- `site/sitewide-content.md` contains content and settings shared by the whole site. It
4
- is separate from `content.md`, which defines the homepage, and from
5
- `config.md`, which defines the public URL and optional language and scroll
6
- behaviour.
3
+ `site/sitewide-content.yaml` is optional. It contains editorial content and
4
+ identity shared by every page: the navigation label, banners, and footer.
7
5
 
8
- ## Site identity
6
+ The file contains plain YAML without Markdown frontmatter delimiters. Page
7
+ sections do not belong here; they remain in each page's `content.md`.
9
8
 
10
- Use the optional `navigation` object for identity shared by all pages. `brand`
11
- is the text shown in the home link when no logo is present. A logo is discovered
12
- from one convention-based file in `site/public`: `logo.svg`, `logo.png`,
13
- `logo.jpg`, or `logo.jpeg`.
9
+ ## Navigation Identity
10
+
11
+ Use the optional `navigation` object for identity shared by the homepage and
12
+ all routes:
14
13
 
15
14
  ```yaml
16
15
  navigation:
17
- brand: Example Site
16
+ label: Example Site
17
+ ```
18
+
19
+ Without a navigation logo, `label` is shown in the home link. With a logo,
20
+ `label` becomes the image alternative text. If omitted, Norna uses the homepage
21
+ title from `site/content.md`.
22
+
23
+ A logo file is discovered from `site/public/`; no path is configured here. Add
24
+ `logo` only to override its displayed height:
25
+
26
+ ```yaml
27
+ navigation:
28
+ label: Example Site
18
29
  logo:
19
- alt: Example Site
20
30
  height: 2.6rem
21
31
  ```
22
32
 
23
- If `navigation.brand` is omitted, Norna uses the homepage `title` from
24
- `site/content.md`. The logo's width is derived from its intrinsic aspect ratio.
25
- If both a logo and a brand are present, the logo is displayed and the brand is
26
- used as its text fallback and accessible default.
33
+ The logo width follows the file's intrinsic aspect ratio. See
34
+ [Public Files: Navigation Logo](public-files.md#navigation-logo) for exact
35
+ filenames, placement, portability, and validation rules.
36
+
37
+ Routes inherit this identity and cannot replace it in route content or a route
38
+ theme.
27
39
 
28
40
  ## Banners
29
41
 
30
- Use `banners` for short notices shown above the page content on every route.
31
- The list order controls the presentation order. Each banner needs a unique
32
- `id`, a title and text:
42
+ Use `banners` for short notices shown above page content on every route. List
43
+ order controls presentation order. Each banner needs a unique lowercase `id`,
44
+ a title, and text:
33
45
 
34
46
  ```yaml
35
- ---
36
47
  banners:
37
48
  - id: project-status
38
49
  tone: warning
@@ -41,26 +52,25 @@ banners:
41
52
  until: "2026-09-01"
42
53
  title: Experimental code
43
54
  text: Not for production use.
44
- ---
45
55
  ```
46
56
 
47
- `visible` uses the same date-window rules as temporary sections. Visitors can
48
- dismiss individual active banners. The dismissal is stored locally in the
49
- browser and is tied to the banner content, so an edited banner can appear
50
- again.
57
+ `tone` currently supports `warning`. `visible` is optional and uses the same
58
+ date-window rules as temporary sections: `from` is inclusive and `until` is
59
+ exclusive.
51
60
 
52
- The first version supports the `warning` tone. Keep banner text short; banners
53
- are presented as compact single-line notices and may use an ellipsis when the
54
- text does not fit.
61
+ Visitors can dismiss each active banner. Dismissal state is stored locally in
62
+ the browser and tied to the banner content, so an edited banner can appear
63
+ again. Keep banners concise; they are rendered as compact one-line notices and
64
+ may use an ellipsis when space is limited.
55
65
 
56
66
  ## Footer
57
67
 
58
- The footer is also sitewide content. `copyrightMessage` adds a copyright or
59
- license sentence. `buildInfo` optionally adds a generated build timestamp:
68
+ The footer can contain copyright or ownership text and optional generated build
69
+ information:
60
70
 
61
71
  ```yaml
62
72
  footer:
63
- copyrightMessage: (c) Example Artist.
73
+ copyrightMessage: (c) Example Owner.
64
74
  buildInfo:
65
75
  enabled: true
66
76
  text: Built
@@ -71,5 +81,9 @@ footer:
71
81
  timeStyle: short
72
82
  ```
73
83
 
74
- If both the copyright message and enabled build information are absent, the
75
- footer is not rendered.
84
+ `dateTimeFormat` uses `Intl.DateTimeFormat` values. `timeZone` must be a valid
85
+ IANA time-zone name. If both copyright text and enabled build information are
86
+ absent, no footer is rendered.
87
+
88
+ See [Site Files](site-files.md) for where this optional file belongs in the
89
+ complete site model.
package/docs/theme.md CHANGED
@@ -1,13 +1,12 @@
1
1
  # Theme
2
2
 
3
- `site/theme.md` defines the site-wide visual theme for a `norna` site. It uses
4
- YAML frontmatter and does not need a Markdown body. The root theme file is
5
- required. The normal setup selects one complete theme preset and adds only
6
- focused overrides when needed.
3
+ `site/theme.yaml` defines the site-wide visual theme for a Norna site. It is a
4
+ required plain YAML file. The normal setup selects one complete theme preset
5
+ and adds only focused overrides when needed.
7
6
 
8
- An optional `theme.md` inside a route directory replaces the root visual theme
9
- for that route. Shared identity such as brand and logo remains site-wide and
10
- belongs in `sitewide-content.md`.
7
+ An optional `theme.yaml` inside a route directory replaces the root visual
8
+ theme for that route. Shared identity such as the navigation label and logo
9
+ remains site-wide and belongs in `sitewide-content.yaml`.
11
10
 
12
11
  ## Theme Presets
13
12
 
@@ -22,22 +21,20 @@ Available complete theme presets are:
22
21
  - `statement`: airy spacing and stronger typography for short editorial
23
22
  content.
24
23
 
25
- A normal `theme.md` can be only:
24
+ A normal `theme.yaml` can be only:
26
25
 
27
26
  ```yaml
28
- ---
29
27
  preset: documentation
30
- ---
31
28
  ```
32
29
 
33
30
  Each preset supplies coordinated values for:
34
31
 
35
32
  - layout density, page width, and gutters
36
33
  - managed image sizing
37
- - font family, typography preset, and typography rhythm
34
+ - font family, typography profile, and typography rhythm
38
35
  - palette and section-surface behaviour
39
36
 
40
- The nested `typography.preset` setting documented below is a lower-level
37
+ The nested `typography.profile` setting documented below is a lower-level
41
38
  typography choice. A top-level theme `preset` selects the complete visual
42
39
  system, including that typography choice.
43
40
 
@@ -47,18 +44,14 @@ Values written beside the top-level preset override only that part of the
47
44
  preset. Other preset values remain active:
48
45
 
49
46
  ```yaml
50
- ---
51
47
  preset: documentation
52
48
  layout:
53
49
  pageWidth: 1320px
54
- presentation:
55
- palette: dark
56
- ---
50
+ palette: dark
57
51
  ```
58
52
 
59
- Nested objects are merged by key. Arrays such as
60
- `presentation.sectionSurfaces.sequence` replace the preset array when they are
61
- specified.
53
+ Nested objects are merged by key. `sectionSurfaces` replaces the preset array
54
+ when it is specified.
62
55
 
63
56
  It is still valid to omit the top-level preset and define the visual settings
64
57
  explicitly. Omitted explicit settings then use engine defaults. This is useful
@@ -79,16 +72,17 @@ In a generated site, the equivalent npm command is:
79
72
  npm run norna:theme:export -- documentation
80
73
  ```
81
74
 
82
- The command creates `site/orig-documentation-theme.md`, or the corresponding
75
+ The command creates `site/orig-documentation-theme.yaml`, or the corresponding
83
76
  path under the selected site directory. The file contains the preset values,
84
77
  comments describing accepted alternatives, and an example of a fine-grained
85
78
  typography override.
86
79
 
87
- Norna never loads `orig-*-theme.md`; only `theme.md` is active. The export
80
+ Norna never loads `orig-*-theme.yaml`; only `theme.yaml` is active. The export
88
81
  command refuses to overwrite an existing reference file.
89
82
 
90
83
  Site identity is not part of the visual theme. Define the optional navigation
91
- brand and logo settings in `site/sitewide-content.md`; see [Sitewide Content](sitewide-content.md).
84
+ label and logo display settings in `site/sitewide-content.yaml`; see
85
+ [Sitewide Content](sitewide-content.md).
92
86
 
93
87
  ## Layout
94
88
 
@@ -155,7 +149,7 @@ before Markdown subheadings, paragraph spacing, and caption spacing, belongs to
155
149
 
156
150
  ## Image Sizing
157
151
 
158
- `gallery` is optional. It controls image sizing:
152
+ `images` is optional. It controls managed image sizing:
159
153
 
160
154
  - `width`: hard maximum rendered image area width for images, captions, and
161
155
  aligned text.
@@ -166,7 +160,7 @@ before Markdown subheadings, paragraph spacing, and caption spacing, belongs to
166
160
  Example:
167
161
 
168
162
  ```yaml
169
- gallery:
163
+ images:
170
164
  width: 900px
171
165
  maxAvailableWidthPercent:
172
166
  desktop: 100
@@ -184,7 +178,7 @@ desktop `74` / mobile `68`.
184
178
  Top-level `typography` is the site-wide typographic base. It supports:
185
179
 
186
180
  - `fontFamily`: global CSS font-family stack.
187
- - `preset`: built-in typography preset.
181
+ - `profile`: built-in typography profile.
188
182
  - `rhythm`: text-near spacing profile. Allowed values are `compact`,
189
183
  `normal`, and `airy`.
190
184
  - `overrides`: focused changes to preset values.
@@ -194,7 +188,7 @@ Example:
194
188
  ```yaml
195
189
  typography:
196
190
  fontFamily: "Arial, 'Helvetica Neue', Helvetica, sans-serif"
197
- preset: text-forward
191
+ profile: reading
198
192
  rhythm: normal
199
193
  overrides:
200
194
  headings:
@@ -211,38 +205,34 @@ typography:
211
205
  lineHeight: 1.55
212
206
  ```
213
207
 
214
- Use `norna typography presets` to inspect built-in preset and rhythm values,
208
+ Use `norna typography profiles` to inspect built-in profile and rhythm values,
215
209
  and `norna typography show` to inspect the resolved typography for the
216
210
  selected site. See [Typography](typography.md).
217
211
 
218
- ## Presentation
212
+ ## Palette And Section Surfaces
219
213
 
220
- `presentation` is optional. It selects a small built-in visual palette for the
221
- page frame and defines how section surfaces are assigned:
214
+ `palette` and `sectionSurfaces` are optional top-level theme settings:
222
215
 
223
- - `palette`: `dark`, `light`, or `paper`. The palette controls the page,
224
- navigation, footer, and section colors.
225
- - `sectionSurfaces.mode`: `none` or `cycle`.
226
- - `sectionSurfaces.sequence`: optional sequence of `base`, `soft`, and
227
- `emphasis`. Each surface may occur at most once.
216
+ - `palette`: `dark`, `light`, or `paper`. It coordinates page, navigation,
217
+ footer, and section colors.
218
+ - `sectionSurfaces`: one to three unique values chosen from `base`, `soft`, and
219
+ `emphasis`. One value gives every section the same surface. Multiple values
220
+ cycle in the listed order.
228
221
 
229
222
  Example:
230
223
 
231
224
  ```yaml
232
- presentation:
233
- palette: paper # Alternatives: dark, light
234
- sectionSurfaces:
235
- mode: cycle
236
- sequence: [base, soft, emphasis]
225
+ palette: paper # Alternatives: dark, light
226
+ sectionSurfaces: [base, soft, emphasis]
237
227
  ```
238
228
 
239
229
  ## Route Themes
240
230
 
241
- Add `theme.md` to a route directory when that route should have a different
231
+ Add `theme.yaml` to a route directory when that route should have a different
242
232
  visual expression:
243
233
 
244
234
  ```text
245
- site/routes/010-guide/theme.md
235
+ site/routes/010-guide/theme.yaml
246
236
  ```
247
237
 
248
238
  The route theme uses the same visual schema and complete presets as the root
@@ -250,14 +240,12 @@ theme. A route can therefore select a different expression without repeating a
250
240
  large configuration:
251
241
 
252
242
  ```yaml
253
- ---
254
243
  preset: statement
255
- ---
256
244
  ```
257
245
 
258
246
  It completely replaces the root visual theme for that route. If the route
259
247
  theme selects no top-level preset, omitted values use engine defaults rather
260
- than values from the root theme. It cannot define navigation, brand, logo, or
248
+ than values from the root theme. It cannot define navigation identity or
261
249
  technical configuration.
262
250
 
263
251
  Section surfaces render as full-width horizontal bands while the section
@@ -268,7 +256,7 @@ accent color.
268
256
 
269
257
  ### Should every route select its own preset?
270
258
 
271
- No. A route without its own `theme.md` inherits the root theme, which is the
259
+ No. A route without its own `theme.yaml` inherits the root theme, which is the
272
260
  normal choice when the site should keep one visual expression.
273
261
 
274
262
  Add a route theme only when the route should intentionally look different. If
@@ -278,6 +266,6 @@ necessary because a route theme replaces the root visual theme rather than
278
266
  merging with it.
279
267
 
280
268
  For example, a route demonstrating section surfaces may keep `preset: project`
281
- and change only `presentation.sectionSurfaces`. A route demonstrating media or
282
- content blocks should normally inherit the root preset so that the media or
283
- content remains the only variable being compared.
269
+ and change only `sectionSurfaces`. A route demonstrating image or content
270
+ blocks should normally inherit the root preset so that the blocks remain the
271
+ only variable being compared.
@@ -1,50 +1,48 @@
1
1
  # Typography
2
2
 
3
- `norna` typography is configured in `site/theme.md` through a site-wide font,
4
- presets, text rhythm, and optional overrides.
3
+ Norna typography is configured in `site/theme.yaml` through a site-wide font,
4
+ profile, text rhythm, and optional overrides.
5
5
 
6
6
  The normal workflow is to select a complete top-level theme preset. It already
7
- chooses a coordinated font, typography preset, and rhythm:
7
+ chooses a coordinated font, typography profile, and rhythm:
8
8
 
9
9
  ```yaml
10
- ---
11
10
  preset: documentation
12
- ---
13
11
  ```
14
12
 
15
13
  Use the nested `typography` block only when those typographic choices need to
16
14
  differ from the selected theme preset. Typography is configured at root-theme
17
15
  or route-theme level, not in page or section content.
18
16
 
19
- ## Typography Presets
17
+ ## Typography Profiles
20
18
 
21
- Available presets:
19
+ Available profiles:
22
20
 
23
- - `quiet-gallery`: the default for image-led sites. Text is restrained and
21
+ - `restrained`: the default for image-led sites. Text is restrained and
24
22
  supports the images without dominating the page.
25
- - `compact-gallery`: tighter typography for many sections, many images, or
23
+ - `dense`: tighter typography for many sections, many images, or
26
24
  short information blocks.
27
- - `text-forward`: more generous body text for pages where longer text carries
25
+ - `reading`: more generous body text for pages where longer text carries
28
26
  more of the experience.
29
27
  - `statement`: tighter, more declarative line-height for short programmatic
30
- statements. Use it sparingly, usually as a page or section exception.
28
+ statements. Use it sparingly, usually as a route-level exception.
31
29
 
32
30
  If a complete top-level theme preset is selected, that preset supplies the
33
31
  typography choice. If both the top-level preset and nested typography are
34
- omitted, the engine default is `quiet-gallery`.
32
+ omitted, the engine default is `restrained`.
35
33
 
36
- Presets define alignment, size, weight, and line height for `headings.h1`
34
+ Profiles define alignment, size, weight, and line height for `headings.h1`
37
35
  through `headings.h4`, `body`, and `caption`. They also choose a readable body
38
36
  text width. Built-in presets use `medium` as the default size for every text
39
37
  role. Visual heading hierarchy comes from the Markdown heading level, so `h1`
40
38
  is larger than `h2`, `h2` is larger than `h3`, and so on.
41
39
 
42
- The presets use these controls deliberately:
40
+ The profiles use these controls deliberately:
43
41
 
44
- - `quiet-gallery` uses restrained heading weights and a normal reading width.
45
- - `compact-gallery` uses stronger headings and a wider text column for short,
42
+ - `restrained` uses restrained heading weights and a normal reading width.
43
+ - `dense` uses stronger headings and a wider text column for short,
46
44
  scannable content.
47
- - `text-forward` uses a narrower reading width and more generous body line
45
+ - `reading` uses a narrower reading width and more generous body line
48
46
  height.
49
47
  - `statement` uses the strongest heading weights and a narrow text column for
50
48
  short, declarative content.
@@ -53,15 +51,15 @@ The presets use these controls deliberately:
53
51
  Available rhythms are `compact`, `normal`, and `airy`. Built-in rhythm values
54
52
  use `em` so spacing follows the rendered text size.
55
53
 
56
- Use this command to inspect the exact preset and rhythm values shipped with
54
+ Use this command to inspect the exact profile and rhythm values shipped with
57
55
  the installed engine:
58
56
 
59
57
  ```sh
60
- norna typography presets
58
+ norna typography profiles
61
59
  ```
62
60
 
63
61
  Use this command to inspect the effective values for the selected site after
64
- presets, rhythms, and overrides have been applied:
62
+ profiles, rhythms, and overrides have been applied:
65
63
 
66
64
  ```sh
67
65
  norna typography show
@@ -76,7 +74,7 @@ also marked with `inherited: true`.
76
74
  ```yaml
77
75
  typography:
78
76
  fontFamily: "Arial, 'Helvetica Neue', Helvetica, sans-serif"
79
- preset: quiet-gallery
77
+ profile: restrained
80
78
  rhythm: normal
81
79
  overrides:
82
80
  headings:
@@ -117,7 +115,7 @@ align:
117
115
  Allowed size values are `small`, `medium`, `large`, and `xlarge`. `medium` is
118
116
  the normal reading size. Use `small` for quieter supporting text, and use
119
117
  `large` or `xlarge` only when a page or section needs stronger emphasis.
120
- Each heading level uses its own scale, but follows the same principle:
118
+ Each heading level uses its own scale but follows the same principle:
121
119
  `medium` is the normal size for that level. Norna may render the first section
122
120
  heading as an HTML `h1` for document structure, but its visual typography still
123
121
  follows the Markdown level the user wrote: `##` uses `headings.h2`.
@@ -156,13 +154,11 @@ The simplest route-specific typography change is to select a complete theme
156
154
  preset:
157
155
 
158
156
  ```yaml
159
- # site/routes/010-introduction/theme.md
160
- ---
157
+ # site/routes/010-introduction/theme.yaml
161
158
  preset: statement
162
- ---
163
159
  ```
164
160
 
165
- A route-local `theme.md` replaces the root visual theme rather than inheriting
161
+ A route-local `theme.yaml` replaces the root visual theme rather than inheriting
166
162
  from it. The complete preset supplies a coherent route theme without repeating
167
163
  the root values.
168
164
 
@@ -170,17 +166,15 @@ Use a nested typography choice when only the typographic character needs to be
170
166
  specified explicitly:
171
167
 
172
168
  ```yaml
173
- # site/routes/010-introduction/theme.md
174
- ---
169
+ # site/routes/010-introduction/theme.yaml
175
170
  typography:
176
- preset: statement
171
+ profile: statement
177
172
  rhythm: normal
178
- ---
179
173
  ```
180
174
 
181
175
  Without a top-level theme preset, other omitted route-theme values use engine
182
176
  defaults rather than values from the root theme.
183
177
 
184
178
  The `body.width` value controls the prose column independently of the page and
185
- image widths. Captions are normally centered, but `text-forward` uses
179
+ image widths. Captions are normally centered, but `reading` uses
186
180
  left-aligned captions to support longer explanatory text.
@@ -9,6 +9,14 @@ A small Norna site with a homepage and ordered routes for dogs and adoption.
9
9
  The dog photos are CC0 images by Bicanski, sourced from Pixnio. Attribution is
10
10
  included in the site footer even though the licence does not require it.
11
11
 
12
+ <!-- norna-image-provenance:
13
+ image: site/public/logo.svg
14
+ source: AI-assisted, hand-authored SVG
15
+ prompt: Create a compact horizontal dog shelter logo with a simple dog face in
16
+ a house-shaped mark and the words Dog Shelter. Use flat vector shapes, a warm
17
+ red accent, dark text, transparent background and no external assets.
18
+ -->
19
+
12
20
  Run it from the Norna repository root:
13
21
 
14
22
  ```sh
@@ -0,0 +1,6 @@
1
+ navigation:
2
+ label: Dog Shelter
3
+ logo:
4
+ height: 3rem
5
+ footer:
6
+ copyrightMessage: Dog Shelter example site. Dog photos by Bicanski, CC0, via Pixnio.
@@ -9,6 +9,14 @@ A small Norna site with two homepage sections and no routes.
9
9
  The dog photos are CC0 images by Bicanski, sourced from Pixnio. Attribution is
10
10
  included in the site footer even though the licence does not require it.
11
11
 
12
+ <!-- norna-image-provenance:
13
+ image: site/public/logo.svg
14
+ source: AI-assisted, hand-authored SVG
15
+ prompt: Create a compact horizontal dog shelter logo with a simple dog face in
16
+ a house-shaped mark and the words Dog Shelter. Use flat vector shapes, a warm
17
+ red accent, dark text, transparent background and no external assets.
18
+ -->
19
+
12
20
  Run it from the Norna repository root:
13
21
 
14
22
  ```sh
@@ -0,0 +1,6 @@
1
+ navigation:
2
+ label: Dog Shelter
3
+ logo:
4
+ height: 3rem
5
+ footer:
6
+ copyrightMessage: Dog Shelter example site. Dog photos by Bicanski, CC0, via Pixnio.