@janga/norna 0.7.16 → 0.7.17

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 (200) hide show
  1. package/README.md +6 -6
  2. package/astro.config.mjs +35 -3
  3. package/docs/README.md +10 -10
  4. package/docs/commands.md +2 -2
  5. package/docs/content.md +82 -102
  6. package/docs/design/navigation-and-theme-plan.md +115 -0
  7. package/docs/design/norna-diagram-design.md +9 -9
  8. package/docs/design/site-examples-structure.md +9 -9
  9. package/docs/engine-development.md +9 -9
  10. package/docs/getting-started.md +20 -15
  11. package/docs/images-and-metadata.md +10 -9
  12. package/docs/pages.md +134 -0
  13. package/docs/public-files.md +49 -36
  14. package/docs/publishing.md +19 -3
  15. package/docs/site-files.md +29 -28
  16. package/docs/sitewide-content.md +20 -36
  17. package/docs/theme.md +20 -20
  18. package/docs/typography.md +10 -10
  19. package/examples/README.md +2 -2
  20. package/examples/complete-sites/dog-shelter-multi-page/.astro/collections/site.schema.json +17 -41
  21. package/examples/complete-sites/dog-shelter-multi-page/.astro/collections/sitewide.schema.json +26 -67
  22. package/examples/complete-sites/dog-shelter-multi-page/.astro/collections/theme.schema.json +185 -88
  23. package/examples/complete-sites/dog-shelter-multi-page/.astro/data-store.json +1 -1
  24. package/examples/complete-sites/dog-shelter-multi-page/.astro/dev-local.json +4 -4
  25. package/examples/complete-sites/dog-shelter-multi-page/.astro/dev.json +5 -5
  26. package/examples/complete-sites/dog-shelter-multi-page/.astro/dev.log +33 -23
  27. package/examples/complete-sites/dog-shelter-multi-page/README.md +1 -1
  28. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/_metadata.json +8 -8
  29. package/examples/complete-sites/dog-shelter-multi-page/site/.norna/generated-images.json +20 -20
  30. package/examples/complete-sites/dog-shelter-multi-page/site/content.md +3 -4
  31. package/examples/complete-sites/dog-shelter-multi-page/site/{routes → pages}/010-dogs/content.md +3 -4
  32. package/examples/complete-sites/dog-shelter-multi-page/site/{routes → pages}/020-adopt/content.md +3 -4
  33. package/examples/complete-sites/dog-shelter-multi-page/site/sitewide-content.yaml +2 -4
  34. package/examples/complete-sites/dog-shelter-single-page/.astro/collections/site.schema.json +17 -41
  35. package/examples/complete-sites/dog-shelter-single-page/.astro/collections/sitewide.schema.json +26 -67
  36. package/examples/complete-sites/dog-shelter-single-page/.astro/collections/theme.schema.json +185 -88
  37. package/examples/complete-sites/dog-shelter-single-page/.astro/data-store.json +1 -1
  38. package/examples/complete-sites/dog-shelter-single-page/.astro/dev-local.json +8 -0
  39. package/examples/complete-sites/dog-shelter-single-page/.astro/dev.json +5 -5
  40. package/examples/complete-sites/dog-shelter-single-page/.astro/dev.log +16 -12
  41. package/examples/complete-sites/dog-shelter-single-page/README.md +1 -1
  42. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/_metadata.json +8 -8
  43. package/examples/complete-sites/dog-shelter-single-page/site/.norna/generated-images.json +12 -12
  44. package/examples/complete-sites/dog-shelter-single-page/site/content.md +5 -2
  45. package/examples/complete-sites/dog-shelter-single-page/site/sitewide-content.yaml +2 -4
  46. package/examples/feature-demos/media-and-surfaces/.astro/collections/site.schema.json +17 -41
  47. package/examples/feature-demos/media-and-surfaces/.astro/collections/sitewide.schema.json +26 -67
  48. package/examples/feature-demos/media-and-surfaces/.astro/collections/theme.schema.json +185 -88
  49. package/examples/feature-demos/media-and-surfaces/.astro/data-store.json +1 -1
  50. package/examples/feature-demos/media-and-surfaces/.astro/dev.log +4 -14
  51. package/examples/feature-demos/media-and-surfaces/README.md +2 -2
  52. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/_metadata.json +9 -9
  53. package/examples/feature-demos/media-and-surfaces/site/.norna/generated-images.json +16 -16
  54. package/examples/feature-demos/media-and-surfaces/site/content.md +4 -7
  55. package/examples/feature-demos/media-and-surfaces/site/{routes → pages}/010-media/content.md +6 -5
  56. package/examples/feature-demos/media-and-surfaces/site/{routes → pages}/020-surfaces/content.md +7 -6
  57. package/examples/feature-demos/media-and-surfaces/site/sitewide-content.yaml +0 -2
  58. package/examples/feature-demos/sitewide-content/README.md +3 -3
  59. package/examples/feature-demos/sitewide-content/site/content.md +8 -7
  60. package/examples/feature-demos/sitewide-content/site/pages/010-logo-and-navigation/content.md +17 -0
  61. package/examples/feature-demos/sitewide-content/site/{routes → pages}/020-notices/content.md +7 -6
  62. package/examples/feature-demos/sitewide-content/site/{routes → pages}/030-footer/content.md +6 -5
  63. package/examples/feature-demos/sitewide-content/site/sitewide-content.yaml +4 -13
  64. package/examples/feature-demos/theme-presets/README.md +1 -1
  65. package/examples/feature-demos/theme-presets/site/.norna/generated-images.json +60 -60
  66. package/examples/feature-demos/theme-presets/site/content.md +4 -7
  67. package/examples/feature-demos/theme-presets/site/{routes → pages}/010-portfolio/content.md +4 -7
  68. package/examples/feature-demos/theme-presets/site/{routes → pages}/020-documentation/content.md +4 -7
  69. package/examples/feature-demos/theme-presets/site/{routes → pages}/030-project/content.md +4 -7
  70. package/examples/feature-demos/theme-presets/site/{routes → pages}/040-statement/content.md +4 -7
  71. package/examples/feature-demos/theme-presets/site/sitewide-content.yaml +1 -10
  72. package/fixtures/basic/site/content.md +5 -6
  73. package/fixtures/basic/site/sitewide-content.yaml +1 -8
  74. package/fixtures/content-model-v2/site/content.md +11 -13
  75. package/fixtures/content-model-v2/site/pages/010-guide/content.md +18 -0
  76. package/fixtures/nested-pages/site/.norna/generated-images.json +10 -0
  77. package/fixtures/nested-pages/site/config.yaml +1 -0
  78. package/fixtures/nested-pages/site/content.md +15 -0
  79. package/fixtures/nested-pages/site/pages/010-guides/content.md +15 -0
  80. package/fixtures/nested-pages/site/pages/010-guides/pages/010-installation/content.md +21 -0
  81. package/fixtures/nested-pages/site/pages/010-guides/pages/010-installation/images/diagram.svg +21 -0
  82. package/fixtures/nested-pages/site/pages/010-guides/pages/010-installation/pages/010-macos/content.md +14 -0
  83. package/fixtures/nested-pages/site/pages/010-guides/pages/020-workflows/content.md +11 -0
  84. package/fixtures/nested-pages/site/pages/010-guides/theme.yaml +3 -0
  85. package/fixtures/nested-pages/site/pages/020-reference/content.md +10 -0
  86. package/fixtures/nested-pages/site/pages/020-reference/pages/010-installation/content.md +11 -0
  87. package/fixtures/nested-pages/site/theme.yaml +3 -0
  88. package/package.json +7 -4
  89. package/schemas/config.schema.json +5 -5
  90. package/schemas/content-frontmatter.schema.json +28 -63
  91. package/schemas/manifest.json +1 -0
  92. package/schemas/sitewide-content.schema.json +58 -132
  93. package/schemas/theme.schema.json +396 -86
  94. package/scripts/check-config.mjs +6 -5
  95. package/scripts/deploy-site.mjs +6 -8
  96. package/scripts/doctor.mjs +2 -2
  97. package/scripts/generate-images.mjs +11 -18
  98. package/scripts/generate-schemas.mjs +3 -217
  99. package/scripts/lib/base-path-redirect.mjs +9 -0
  100. package/scripts/lib/editor-language-service.mjs +126 -66
  101. package/scripts/lib/heading-ids.mjs +161 -0
  102. package/scripts/lib/navigation-model.mjs +51 -0
  103. package/scripts/lib/norna-markdown-blocks.mjs +3 -4
  104. package/scripts/lib/page-model.mjs +83 -0
  105. package/scripts/lib/project-config.mjs +28 -0
  106. package/scripts/lib/schema-definitions.mjs +41 -46
  107. package/scripts/lib/schema-editor-metadata.mjs +475 -0
  108. package/scripts/lib/schema-value-definitions.mjs +6 -6
  109. package/scripts/lib/site-content.mjs +124 -87
  110. package/scripts/lib/site-paths.mjs +2 -2
  111. package/scripts/lib/theme-config.mjs +9 -16
  112. package/scripts/lib/theme-presets.mjs +9 -1
  113. package/scripts/release.mjs +1 -1
  114. package/scripts/show-typography.mjs +26 -20
  115. package/scripts/sync-content-sections.mjs +106 -65
  116. package/scripts/{test-temporary-visibility.mjs → test-banner-visibility.mjs} +7 -24
  117. package/scripts/test-client-javascript.mjs +39 -42
  118. package/scripts/test-content-check.mjs +138 -54
  119. package/scripts/test-content-model-v2.mjs +445 -228
  120. package/scripts/test-documentation.mjs +6 -1
  121. package/scripts/test-editor-language-service.mjs +168 -24
  122. package/scripts/test-engine-commands.mjs +2 -1
  123. package/scripts/test-heading-ids.mjs +68 -0
  124. package/scripts/test-navigation-model.mjs +63 -0
  125. package/scripts/test-nested-pages.mjs +110 -0
  126. package/scripts/test-package-check.mjs +31 -40
  127. package/scripts/test-page-model.mjs +80 -0
  128. package/scripts/test-project-config.mjs +25 -1
  129. package/scripts/test-schemas.mjs +66 -14
  130. package/scripts/test-theme-presets.mjs +33 -24
  131. package/src/components/NavigationPageTree.astro +68 -0
  132. package/src/components/SectionNavigationScript.astro +110 -5
  133. package/src/components/SiteBreadcrumbs.astro +29 -0
  134. package/src/components/SiteNavigation.astro +65 -69
  135. package/src/components/SitePage.astro +70 -46
  136. package/src/components/SiteSection.astro +27 -20
  137. package/src/content.config.ts +9 -5
  138. package/src/layouts/BaseLayout.astro +11 -20
  139. package/src/lib/pageThemes.ts +42 -0
  140. package/src/lib/sectionContent.ts +109 -106
  141. package/src/lib/siteNavigation.ts +48 -0
  142. package/src/lib/sitePages.ts +85 -38
  143. package/src/pages/{[slug].astro → [...slug].astro} +2 -2
  144. package/src/styles/global.css +373 -55
  145. package/starters/basic/README.md +5 -7
  146. package/starters/basic/site/content.md +7 -4
  147. package/starters/basic/site/sitewide-content.yaml +1 -10
  148. package/starters/project/README.md +8 -8
  149. package/starters/project/site/content.md +5 -4
  150. package/starters/project/site/{routes → pages}/010-guide/content.md +5 -4
  151. package/starters/project/site/sitewide-content.yaml +1 -10
  152. package/docs/routes.md +0 -121
  153. package/examples/feature-demos/sitewide-content/site/routes/010-identity/content.md +0 -20
  154. package/fixtures/content-model-v2/site/routes/010-guide/content.md +0 -17
  155. package/scripts/lib/route-model.mjs +0 -17
  156. package/scripts/test-route-model.mjs +0 -32
  157. package/src/lib/routeThemes.ts +0 -41
  158. /package/examples/complete-sites/dog-shelter-multi-page/site/images/{intro/shelter-dog.jpg → shelter-dog.jpg} +0 -0
  159. /package/examples/complete-sites/dog-shelter-multi-page/site/{routes/010-dogs/images/dogs → pages/010-dogs/images}/rex.jpg +0 -0
  160. /package/examples/complete-sites/dog-shelter-multi-page/site/{routes/010-dogs/images/dogs → pages/010-dogs/images}/rover.jpg +0 -0
  161. /package/examples/complete-sites/dog-shelter-multi-page/site/{routes/020-adopt/images/adopt → pages/020-adopt/images}/adoption-dog.jpg +0 -0
  162. /package/examples/complete-sites/dog-shelter-single-page/site/images/{you-can-help/foster-dog.jpg → foster-dog.jpg} +0 -0
  163. /package/examples/complete-sites/dog-shelter-single-page/site/images/{what-we-do/rescue-dog.jpg → rescue-dog.jpg} +0 -0
  164. /package/examples/feature-demos/media-and-surfaces/site/{routes/010-media/images/cards → pages/010-media/images}/card-carousel.svg +0 -0
  165. /package/examples/feature-demos/media-and-surfaces/site/{routes/010-media/images/cards → pages/010-media/images}/card-stack.svg +0 -0
  166. /package/examples/feature-demos/media-and-surfaces/site/{routes/010-media/images/cards → pages/010-media/images}/card-surfaces.svg +0 -0
  167. /package/examples/feature-demos/media-and-surfaces/site/{routes/010-media/images/carousel → pages/010-media/images}/carousel-one.svg +0 -0
  168. /package/examples/feature-demos/media-and-surfaces/site/{routes/010-media/images/carousel → pages/010-media/images}/carousel-three.svg +0 -0
  169. /package/examples/feature-demos/media-and-surfaces/site/{routes/010-media/images/carousel → pages/010-media/images}/carousel-two.svg +0 -0
  170. /package/examples/feature-demos/media-and-surfaces/site/{routes/010-media/images/stack → pages/010-media/images}/stack-one.svg +0 -0
  171. /package/examples/feature-demos/media-and-surfaces/site/{routes/010-media/images/stack → pages/010-media/images}/stack-two.svg +0 -0
  172. /package/examples/feature-demos/media-and-surfaces/site/{routes → pages}/020-surfaces/theme.yaml +0 -0
  173. /package/examples/feature-demos/theme-presets/site/{routes/010-portfolio/images/portfolio → pages/010-portfolio/images}/puppy-portrait.jpg +0 -0
  174. /package/examples/feature-demos/theme-presets/site/{routes/010-portfolio/images/portfolio → pages/010-portfolio/images}/shepherd-portrait.jpg +0 -0
  175. /package/examples/feature-demos/theme-presets/site/{routes/010-portfolio/images/portfolio → pages/010-portfolio/images}/white-puppy.jpg +0 -0
  176. /package/examples/feature-demos/theme-presets/site/{routes → pages}/010-portfolio/theme.yaml +0 -0
  177. /package/examples/feature-demos/theme-presets/site/{routes/020-documentation/images/documentation → pages/020-documentation/images}/black-schnauzer.jpg +0 -0
  178. /package/examples/feature-demos/theme-presets/site/{routes/020-documentation/images/documentation → pages/020-documentation/images}/retriever-portrait.jpg +0 -0
  179. /package/examples/feature-demos/theme-presets/site/{routes/020-documentation/images/documentation → pages/020-documentation/images}/schnauzer-portrait.jpg +0 -0
  180. /package/examples/feature-demos/theme-presets/site/{routes → pages}/020-documentation/theme.yaml +0 -0
  181. /package/examples/feature-demos/theme-presets/site/{routes/030-project/images/project → pages/030-project/images}/boxer-portrait.jpg +0 -0
  182. /package/examples/feature-demos/theme-presets/site/{routes/030-project/images/project → pages/030-project/images}/grass-puppy.jpg +0 -0
  183. /package/examples/feature-demos/theme-presets/site/{routes/030-project/images/project → pages/030-project/images}/grey-street-dog.jpg +0 -0
  184. /package/examples/feature-demos/theme-presets/site/{routes → pages}/030-project/theme.yaml +0 -0
  185. /package/examples/feature-demos/theme-presets/site/{routes/040-statement/images/statement → pages/040-statement/images}/black-pedigree.jpg +0 -0
  186. /package/examples/feature-demos/theme-presets/site/{routes/040-statement/images/statement → pages/040-statement/images}/sheepdog-grass.jpg +0 -0
  187. /package/examples/feature-demos/theme-presets/site/{routes/040-statement/images/statement → pages/040-statement/images}/sheepdog-wide.jpg +0 -0
  188. /package/examples/feature-demos/theme-presets/site/{routes → pages}/040-statement/theme.yaml +0 -0
  189. /package/fixtures/basic/site/images/{work/.gitkeep → .gitkeep} +0 -0
  190. /package/fixtures/content-model-v2/site/images/{card-section/adopt.svg → adopt.svg} +0 -0
  191. /package/fixtures/content-model-v2/site/images/{intro/detail.jpg → detail.jpg} +0 -0
  192. /package/fixtures/content-model-v2/site/images/{intro/duplicate.jpg → duplicate.jpg} +0 -0
  193. /package/fixtures/content-model-v2/site/images/{card-section/foster.svg → foster.svg} +0 -0
  194. /package/fixtures/content-model-v2/site/images/{intro/hero.jpg → hero.jpg} +0 -0
  195. /package/fixtures/content-model-v2/site/images/{plain/image.jpg → image.jpg} +0 -0
  196. /package/fixtures/content-model-v2/site/images/{timed/slide-one.jpg → slide-one.jpg} +0 -0
  197. /package/fixtures/content-model-v2/site/images/{timed/slide-three.jpg → slide-three.jpg} +0 -0
  198. /package/fixtures/content-model-v2/site/images/{timed/slide-two.jpg → slide-two.jpg} +0 -0
  199. /package/fixtures/content-model-v2/site/{routes/010-guide/images/intro → pages/010-guide/images}/duplicate.jpg +0 -0
  200. /package/starters/basic/site/images/{work/.gitkeep → .gitkeep} +0 -0
@@ -1,45 +1,37 @@
1
1
  # `sitewide-content.yaml`
2
2
 
3
3
  `site/sitewide-content.yaml` is optional. It contains editorial content and
4
- identity shared by every page: the navigation label, banners, and footer.
4
+ optional logo display settings shared by every page: banners, footer, and an
5
+ optional navigation-logo height override.
5
6
 
6
7
  The file contains plain YAML without Markdown frontmatter delimiters. Page
7
8
  sections do not belong here; they remain in each page's `content.md`.
8
9
 
9
- ## Navigation Identity
10
+ ## Navigation Logo
10
11
 
11
- Use the optional `navigation` object for identity shared by the homepage and
12
- all routes:
12
+ A logo file is discovered from `site/public/`; no path or site name is
13
+ configured here. The logo links to the homepage, and its alternative text
14
+ comes from the homepage Markdown H1 in `site/content.md`.
13
15
 
14
- ```yaml
15
- navigation:
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:
16
+ Add `logo` only to override the discovered file's displayed height:
25
17
 
26
18
  ```yaml
27
- navigation:
28
- label: Example Site
29
- logo:
30
- height: 2.6rem
19
+ logo:
20
+ height: 2.6rem
31
21
  ```
32
22
 
33
23
  The logo width follows the file's intrinsic aspect ratio. See
34
24
  [Public Files: Navigation Logo](public-files.md#navigation-logo) for exact
35
25
  filenames, placement, portability, and validation rules.
36
26
 
37
- Routes inherit this identity and cannot replace it in route content or a route
38
- theme.
27
+ The logo is a separate home link and does not have a section menu. In a
28
+ multi-page site, the homepage remains the first ordinary navigation item, uses
29
+ its Markdown H1 as its label, and exposes its sections in the same way as
30
+ pages. Page content and page themes cannot replace the shared logo setting.
39
31
 
40
32
  ## Banners
41
33
 
42
- Use `banners` for short notices shown above page content on every route. List
34
+ Use `banners` for short notices shown above page content on every page. List
43
35
  order controls presentation order. Each banner needs a unique lowercase `id`,
44
36
  a title, and text:
45
37
 
@@ -54,9 +46,8 @@ banners:
54
46
  text: Not for production use.
55
47
  ```
56
48
 
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.
49
+ `tone` currently supports `warning`. `visible` is optional. `from` is inclusive
50
+ and `until` is exclusive; both use `YYYY-MM-DD`, and either may be omitted.
60
51
 
61
52
  Visitors can dismiss each active banner. Dismissal state is stored locally in
62
53
  the browser and tied to the banner content, so an edited banner can appear
@@ -71,19 +62,12 @@ information:
71
62
  ```yaml
72
63
  footer:
73
64
  copyrightMessage: (c) Example Owner.
74
- buildInfo:
75
- enabled: true
76
- text: Built
77
- dateTimeFormat:
78
- locale: en-GB
79
- timeZone: UTC
80
- dateStyle: short
81
- timeStyle: short
65
+ buildInfo: true
82
66
  ```
83
67
 
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.
68
+ Set `buildInfo` to `true` to show the generated build date and time. Norna uses
69
+ the site's configured language, a compact format, and UTC. If both copyright
70
+ text and build information are absent, no footer is rendered.
87
71
 
88
72
  See [Site Files](site-files.md) for where this optional file belongs in the
89
73
  complete site model.
package/docs/theme.md CHANGED
@@ -4,9 +4,9 @@
4
4
  required plain YAML file. The normal setup selects one complete theme preset
5
5
  and adds only focused overrides when needed.
6
6
 
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`.
7
+ An optional `theme.yaml` inside a page directory replaces the root visual
8
+ theme for that page. Navigation-logo display settings remain site-wide and
9
+ belong in `sitewide-content.yaml`.
10
10
 
11
11
  ## Theme Presets
12
12
 
@@ -80,8 +80,8 @@ typography override.
80
80
  Norna never loads `orig-*-theme.yaml`; only `theme.yaml` is active. The export
81
81
  command refuses to overwrite an existing reference file.
82
82
 
83
- Site identity is not part of the visual theme. Define the optional navigation
84
- label and logo display settings in `site/sitewide-content.yaml`; see
83
+ Page titles and site navigation are not part of the visual theme. Define
84
+ optional logo display settings in `site/sitewide-content.yaml`; see
85
85
  [Sitewide Content](sitewide-content.md).
86
86
 
87
87
  ## Layout
@@ -226,26 +226,26 @@ palette: paper # Alternatives: dark, light
226
226
  sectionSurfaces: [base, soft, emphasis]
227
227
  ```
228
228
 
229
- ## Route Themes
229
+ ## Page Themes
230
230
 
231
- Add `theme.yaml` to a route directory when that route should have a different
231
+ Add `theme.yaml` to a page directory when that page should have a different
232
232
  visual expression:
233
233
 
234
234
  ```text
235
- site/routes/010-guide/theme.yaml
235
+ site/pages/010-guide/theme.yaml
236
236
  ```
237
237
 
238
- The route theme uses the same visual schema and complete presets as the root
239
- theme. A route can therefore select a different expression without repeating a
238
+ The page theme uses the same visual schema and complete presets as the root
239
+ theme. A page can therefore select a different expression without repeating a
240
240
  large configuration:
241
241
 
242
242
  ```yaml
243
243
  preset: statement
244
244
  ```
245
245
 
246
- It completely replaces the root visual theme for that route. If the route
246
+ It completely replaces the root visual theme for that page. If the page
247
247
  theme selects no top-level preset, omitted values use engine defaults rather
248
- than values from the root theme. It cannot define navigation identity or
248
+ than values from the root theme. It cannot define navigation-logo settings or
249
249
  technical configuration.
250
250
 
251
251
  Section surfaces render as full-width horizontal bands while the section
@@ -254,18 +254,18 @@ accent color.
254
254
 
255
255
  ## Common Questions
256
256
 
257
- ### Should every route select its own preset?
257
+ ### Should every page select its own preset?
258
258
 
259
- No. A route without its own `theme.yaml` inherits the root theme, which is the
259
+ No. A page without its own `theme.yaml` inherits the root theme, which is the
260
260
  normal choice when the site should keep one visual expression.
261
261
 
262
- Add a route theme only when the route should intentionally look different. If
263
- the route should keep the same preset but demonstrate a focused change, repeat
264
- the root preset in the route theme and override only that setting. This is
265
- necessary because a route theme replaces the root visual theme rather than
262
+ Add a page theme only when the page should intentionally look different. If
263
+ the page should keep the same preset but demonstrate a focused change, repeat
264
+ the root preset in the page theme and override only that setting. This is
265
+ necessary because a page theme replaces the root visual theme rather than
266
266
  merging with it.
267
267
 
268
- For example, a route demonstrating section surfaces may keep `preset: project`
269
- and change only `sectionSurfaces`. A route demonstrating image or content
268
+ For example, a page demonstrating section surfaces may keep `preset: project`
269
+ and change only `sectionSurfaces`. A page demonstrating image or content
270
270
  blocks should normally inherit the root preset so that the blocks remain the
271
271
  only variable being compared.
@@ -12,7 +12,7 @@ preset: documentation
12
12
 
13
13
  Use the nested `typography` block only when those typographic choices need to
14
14
  differ from the selected theme preset. Typography is configured at root-theme
15
- or route-theme level, not in page or section content.
15
+ or page-theme level, not in page or section content.
16
16
 
17
17
  ## Typography Profiles
18
18
 
@@ -25,7 +25,7 @@ Available profiles:
25
25
  - `reading`: more generous body text for pages where longer text carries
26
26
  more of the experience.
27
27
  - `statement`: tighter, more declarative line-height for short programmatic
28
- statements. Use it sparingly, usually as a route-level exception.
28
+ statements. Use it sparingly, usually as a page-level exception.
29
29
 
30
30
  If a complete top-level theme preset is selected, that preset supplies the
31
31
  typography choice. If both the top-level preset and nested typography are
@@ -65,7 +65,7 @@ profiles, rhythms, and overrides have been applied:
65
65
  norna typography show
66
66
  ```
67
67
 
68
- The output includes the site theme, every page route, and every section. Each
68
+ The output includes the site theme, every page, and every section. Each
69
69
  resolved value shows its `source`; values inherited by a page or section are
70
70
  also marked with `inherited: true`.
71
71
 
@@ -148,31 +148,31 @@ Supported override fields:
148
148
  - `caption.align`, `caption.size`, `caption.lineHeight`,
149
149
  `caption.spacingBefore`
150
150
 
151
- ## Route Themes
151
+ ## Page Themes
152
152
 
153
- The simplest route-specific typography change is to select a complete theme
153
+ The simplest page-specific typography change is to select a complete theme
154
154
  preset:
155
155
 
156
156
  ```yaml
157
- # site/routes/010-introduction/theme.yaml
157
+ # site/pages/010-introduction/theme.yaml
158
158
  preset: statement
159
159
  ```
160
160
 
161
- A route-local `theme.yaml` replaces the root visual theme rather than inheriting
162
- from it. The complete preset supplies a coherent route theme without repeating
161
+ A page-local `theme.yaml` replaces the root visual theme rather than inheriting
162
+ from it. The complete preset supplies a coherent page theme without repeating
163
163
  the root values.
164
164
 
165
165
  Use a nested typography choice when only the typographic character needs to be
166
166
  specified explicitly:
167
167
 
168
168
  ```yaml
169
- # site/routes/010-introduction/theme.yaml
169
+ # site/pages/010-introduction/theme.yaml
170
170
  typography:
171
171
  profile: statement
172
172
  rhythm: normal
173
173
  ```
174
174
 
175
- Without a top-level theme preset, other omitted route-theme values use engine
175
+ Without a top-level theme preset, other omitted page-theme values use engine
176
176
  defaults rather than values from the root theme.
177
177
 
178
178
  The `body.width` value controls the prose column independently of the page and
@@ -7,10 +7,10 @@ documentation workflow.
7
7
  | Example | Purpose | Live demo | Source |
8
8
  | --- | --- | --- | --- |
9
9
  | Dog shelter, single page | A coherent homepage made from sections | [Open site](https://janga.github.io/norna/examples/complete-sites/dog-shelter-single-page/) | [View files](complete-sites/dog-shelter-single-page/) |
10
- | Dog shelter, multi-page | A coherent site with ordered routes and route-local images | [Open site](https://janga.github.io/norna/examples/complete-sites/dog-shelter-multi-page/) | [View files](complete-sites/dog-shelter-multi-page/) |
10
+ | Dog shelter, multi-page | A coherent site with ordered pages and page-local images | [Open site](https://janga.github.io/norna/examples/complete-sites/dog-shelter-multi-page/) | [View files](complete-sites/dog-shelter-multi-page/) |
11
11
  | Theme presets | All complete presets without overrides | [Open site](https://janga.github.io/norna/examples/feature-demos/theme-presets/) | [View files](feature-demos/theme-presets/) |
12
12
  | Media and surfaces | Image blocks, cards, notes, palettes, and section surfaces | [Open site](https://janga.github.io/norna/examples/feature-demos/media-and-surfaces/) | [View files](feature-demos/media-and-surfaces/) |
13
- | Sitewide content | Shared identity, navigation, banners, and footer content | [Open site](https://janga.github.io/norna/examples/feature-demos/sitewide-content/) | [View files](feature-demos/sitewide-content/) |
13
+ | Sitewide content | Shared logo settings, banners, and footer content | [Open site](https://janga.github.io/norna/examples/feature-demos/sitewide-content/) | [View files](feature-demos/sitewide-content/) |
14
14
 
15
15
  ## Directory Structure
16
16
 
@@ -2,58 +2,34 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "type": "object",
4
4
  "properties": {
5
- "title": {
6
- "type": "string"
7
- },
8
- "description": {
9
- "type": "string"
5
+ "page": {
6
+ "type": "object",
7
+ "properties": {
8
+ "description": {
9
+ "description": "Optional page-specific meta description.",
10
+ "type": "string",
11
+ "minLength": 1
12
+ }
13
+ },
14
+ "additionalProperties": false,
15
+ "description": "Optional metadata for this homepage or additional page. The Markdown H1 supplies the page title."
10
16
  },
11
17
  "navigation": {
18
+ "description": "Optional navigation metadata for this page.",
12
19
  "type": "object",
13
20
  "properties": {
14
- "include": {
21
+ "listed": {
22
+ "default": true,
23
+ "description": "List this page in site navigation. The page remains public when false.",
15
24
  "type": "boolean"
16
- },
17
- "label": {
18
- "type": "string"
19
25
  }
20
26
  },
21
27
  "additionalProperties": false
22
28
  },
23
- "sections": {
24
- "default": {},
25
- "type": "object",
26
- "propertyNames": {
27
- "type": "string",
28
- "pattern": "^[a-z0-9-]+$"
29
- },
30
- "additionalProperties": {
31
- "type": "object",
32
- "properties": {
33
- "visible": {
34
- "type": "object",
35
- "properties": {
36
- "from": {
37
- "type": "string",
38
- "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
39
- },
40
- "until": {
41
- "type": "string",
42
- "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
43
- }
44
- },
45
- "additionalProperties": false
46
- }
47
- },
48
- "additionalProperties": false
49
- }
50
- },
51
29
  "$schema": {
52
30
  "type": "string"
53
31
  }
54
32
  },
55
- "required": [
56
- "title",
57
- "description"
58
- ]
33
+ "additionalProperties": false,
34
+ "description": "Frontmatter for a homepage or additional page content.md file."
59
35
  }
@@ -2,55 +2,49 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "type": "object",
4
4
  "properties": {
5
- "navigation": {
5
+ "logo": {
6
6
  "type": "object",
7
7
  "properties": {
8
- "brand": {
8
+ "height": {
9
+ "description": "Displayed logo height. Width follows the intrinsic aspect ratio.",
9
10
  "type": "string",
10
- "minLength": 1
11
- },
12
- "logo": {
13
- "type": "object",
14
- "properties": {
15
- "alt": {
16
- "type": "string",
17
- "minLength": 1
18
- },
19
- "height": {
20
- "type": "string",
21
- "pattern": "^(?:0|(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:px|rem|em|vw|vh|vmin|vmax|ch|%)|clamp\\(\\s*(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:px|rem|em|vw|vh|vmin|vmax|ch|%)\\s*,\\s*(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:px|rem|em|vw|vh|vmin|vmax|ch|%)\\s*,\\s*(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:px|rem|em|vw|vh|vmin|vmax|ch|%)\\s*\\))$"
22
- }
23
- },
24
- "additionalProperties": false
11
+ "pattern": "^(?:0|(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:px|rem|em|vw|vh|vmin|vmax|ch|%)|clamp\\(\\s*(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:px|rem|em|vw|vh|vmin|vmax|ch|%)\\s*,\\s*(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:px|rem|em|vw|vh|vmin|vmax|ch|%)\\s*,\\s*(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:px|rem|em|vw|vh|vmin|vmax|ch|%)\\s*\\))$"
25
12
  }
26
13
  },
27
- "additionalProperties": false
14
+ "additionalProperties": false,
15
+ "description": "Optional display settings for a convention-based navigation logo."
28
16
  },
29
17
  "banners": {
30
18
  "default": [],
19
+ "description": "Site-wide dismissible notices.",
31
20
  "type": "array",
32
21
  "items": {
33
22
  "type": "object",
34
23
  "properties": {
35
24
  "id": {
36
25
  "type": "string",
37
- "pattern": "^[a-z0-9-]+$"
26
+ "pattern": "^[a-z0-9-]+$",
27
+ "description": "Stable banner identifier used for dismissal state."
38
28
  },
39
29
  "tone": {
40
30
  "default": "warning",
31
+ "description": "Semantic banner tone.",
41
32
  "type": "string",
42
33
  "enum": [
43
34
  "warning"
44
35
  ]
45
36
  },
46
37
  "visible": {
38
+ "description": "Optional date window for the banner.",
47
39
  "type": "object",
48
40
  "properties": {
49
41
  "from": {
42
+ "description": "First date on which the content is visible.",
50
43
  "type": "string",
51
44
  "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
52
45
  },
53
46
  "until": {
47
+ "description": "First date on which the content is no longer visible.",
54
48
  "type": "string",
55
49
  "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
56
50
  }
@@ -59,11 +53,13 @@
59
53
  },
60
54
  "title": {
61
55
  "type": "string",
62
- "minLength": 1
56
+ "minLength": 1,
57
+ "description": "Short banner heading."
63
58
  },
64
59
  "text": {
65
60
  "type": "string",
66
- "minLength": 1
61
+ "minLength": 1,
62
+ "description": "Concise banner message."
67
63
  }
68
64
  },
69
65
  "required": [
@@ -71,61 +67,23 @@
71
67
  "title",
72
68
  "text"
73
69
  ],
74
- "additionalProperties": false
70
+ "additionalProperties": false,
71
+ "description": "Dismissible site-wide warning shown above page content for important temporary information."
75
72
  }
76
73
  },
77
74
  "footer": {
75
+ "description": "Site-wide footer content.",
78
76
  "type": "object",
79
77
  "properties": {
80
78
  "copyrightMessage": {
79
+ "description": "Copyright or ownership text shown in the site footer.",
81
80
  "type": "string",
82
81
  "minLength": 1
83
82
  },
84
83
  "buildInfo": {
85
- "type": "object",
86
- "properties": {
87
- "enabled": {
88
- "default": true,
89
- "type": "boolean"
90
- },
91
- "text": {
92
- "type": "string",
93
- "minLength": 1
94
- },
95
- "dateTimeFormat": {
96
- "type": "object",
97
- "properties": {
98
- "locale": {
99
- "type": "string",
100
- "minLength": 1
101
- },
102
- "timeZone": {
103
- "type": "string",
104
- "minLength": 1
105
- },
106
- "dateStyle": {
107
- "type": "string",
108
- "minLength": 1
109
- },
110
- "timeStyle": {
111
- "type": "string",
112
- "minLength": 1
113
- }
114
- },
115
- "required": [
116
- "locale",
117
- "timeZone",
118
- "dateStyle",
119
- "timeStyle"
120
- ],
121
- "additionalProperties": false
122
- }
123
- },
124
- "required": [
125
- "text",
126
- "dateTimeFormat"
127
- ],
128
- "additionalProperties": false
84
+ "default": false,
85
+ "description": "Show a localized generated build timestamp in the footer.",
86
+ "type": "boolean"
129
87
  }
130
88
  },
131
89
  "additionalProperties": false
@@ -134,5 +92,6 @@
134
92
  "type": "string"
135
93
  }
136
94
  },
137
- "additionalProperties": false
95
+ "additionalProperties": false,
96
+ "description": "Editorial content and optional navigation logo display settings shared by every page."
138
97
  }