@janga/norna 0.7.6 → 0.7.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -7
- package/astro.config.mjs +76 -0
- package/bin/norna-cli.mjs +2 -2
- package/docs/README.md +3 -3
- package/docs/commands.md +7 -6
- package/docs/configuration.md +3 -2
- package/docs/content.md +202 -91
- package/docs/design/site-examples-structure.md +1 -1
- package/docs/engine-development.md +3 -3
- package/docs/getting-started.md +50 -8
- package/docs/images-and-metadata.md +117 -20
- package/docs/routes.md +20 -12
- package/docs/site-structure.md +9 -5
- package/docs/theme.md +12 -8
- package/docs/typography.md +9 -10
- package/examples/dog-gallery/site/content.md +38 -77
- package/examples/dog-gallery/site/routes/010-dog-care/route-content.md +0 -10
- package/fixtures/basic/site/content.md +2 -4
- package/fixtures/content-model-v2/.astro/collections/site.schema.json +776 -0
- package/fixtures/content-model-v2/.astro/collections/theme.schema.json +668 -0
- package/fixtures/content-model-v2/.astro/content-assets.mjs +4 -0
- package/fixtures/content-model-v2/.astro/content-modules.mjs +1 -0
- package/fixtures/content-model-v2/.astro/content.d.ts +175 -0
- package/fixtures/content-model-v2/.astro/data-store.json +1 -0
- package/fixtures/content-model-v2/.astro/dev-local.json +8 -0
- package/fixtures/content-model-v2/.astro/dev.json +13 -0
- package/fixtures/content-model-v2/.astro/dev.log +231 -0
- package/fixtures/content-model-v2/.astro/settings.json +5 -0
- package/fixtures/content-model-v2/.astro/types.d.ts +2 -0
- package/fixtures/content-model-v2/dist/_astro/GalleryGrid.astro_astro_type_script_index_0_lang.B0kxDyGz.js +1 -0
- package/fixtures/content-model-v2/dist/_astro/SitePage.BbfZub4g.css +1 -0
- package/fixtures/content-model-v2/dist/guide/index.html +3 -0
- package/fixtures/content-model-v2/dist/images/generated/intro/detail-27930b14-480.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/intro/detail-27930b14-768.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/intro/detail-27930b14-971.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/intro/duplicate-49c98f6c-480.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/intro/duplicate-49c98f6c-768.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/intro/duplicate-49c98f6c-971.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/intro/hero-6d588a83-480.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/intro/hero-6d588a83-768.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/intro/hero-6d588a83-971.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/plain/image-3770d763-1080.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/plain/image-3770d763-1440.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/plain/image-3770d763-1600.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/plain/image-3770d763-480.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/plain/image-3770d763-768.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/routes/010-guide/images/intro/duplicate-5cf614d2-480.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/routes/010-guide/images/intro/duplicate-5cf614d2-768.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/routes/010-guide/images/intro/duplicate-5cf614d2-960.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-one-3770d763-1080.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-one-3770d763-1440.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-one-3770d763-1600.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-one-3770d763-480.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-one-3770d763-768.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-three-5bdec65e-1080.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-three-5bdec65e-1440.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-three-5bdec65e-1600.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-three-5bdec65e-480.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-three-5bdec65e-768.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-two-26c08aee-1080.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-two-26c08aee-1440.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-two-26c08aee-1600.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-two-26c08aee-480.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-two-26c08aee-768.webp +0 -0
- package/fixtures/content-model-v2/dist/index.html +8 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/_metadata.json +80 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/astro-D_GIpJIE.js +434 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/astro-D_GIpJIE.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/astro_n_aria-query.js +6390 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/astro_n_aria-query.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/astro_n_axobject-query.js +2702 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/astro_n_axobject-query.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/astro_n_html-escaper.js +65 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/astro_n_html-escaper.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js +455 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/audit-DM9Hkl5B.js +1534 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/audit-DM9Hkl5B.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/embla-carousel.js +1389 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/embla-carousel.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/highlight-DnZ1ULOL.js +48 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/highlight-DnZ1ULOL.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/icons-RyebKi45.js +42 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/icons-RyebKi45.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/package.json +3 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/rolldown-runtime-BvCyGRYZ.js +4 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/settings-DaU-gNnK.js +190 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/settings-DaU-gNnK.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/toolbar-63PA619H.js +458 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/toolbar-63PA619H.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/ui-library--bkcNSYz.js +1016 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/ui-library--bkcNSYz.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/window-jPkpKVcy.js +32 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/window-jPkpKVcy.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/xray-BXCHpEJP.js +111 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/xray-BXCHpEJP.js.map +1 -0
- package/fixtures/content-model-v2/site/.norna/generated-images.json +210 -0
- package/fixtures/content-model-v2/site/config.mjs +11 -0
- package/fixtures/content-model-v2/site/content.md +84 -0
- package/fixtures/content-model-v2/site/images/card-section/adopt.svg +9 -0
- package/fixtures/content-model-v2/site/images/card-section/foster.svg +12 -0
- package/fixtures/content-model-v2/site/images/intro/detail.jpg +0 -0
- package/fixtures/content-model-v2/site/images/intro/duplicate.jpg +0 -0
- package/fixtures/content-model-v2/site/images/intro/hero.jpg +0 -0
- package/fixtures/content-model-v2/site/images/plain/image.jpg +0 -0
- package/fixtures/content-model-v2/site/images/timed/slide-one.jpg +0 -0
- package/fixtures/content-model-v2/site/images/timed/slide-three.jpg +0 -0
- package/fixtures/content-model-v2/site/images/timed/slide-two.jpg +0 -0
- package/fixtures/content-model-v2/site/routes/010-guide/images/intro/duplicate.jpg +0 -0
- package/fixtures/content-model-v2/site/routes/010-guide/route-content.md +17 -0
- package/fixtures/content-model-v2/site/theme.md +9 -0
- package/package.json +3 -2
- package/scripts/deploy-site.mjs +11 -4
- package/scripts/dev-local.mjs +6 -0
- package/scripts/generate-images.mjs +132 -56
- package/scripts/lib/image-dimensions.mjs +26 -0
- package/scripts/lib/norna-markdown-blocks.mjs +643 -0
- package/scripts/lib/site-content.mjs +31 -29
- package/scripts/show-typography.mjs +17 -9
- package/scripts/sync-content-sections.mjs +414 -412
- package/scripts/test-content-check.mjs +59 -45
- package/scripts/test-content-model-v2.mjs +1230 -0
- package/scripts/test-engine-commands.mjs +1 -1
- package/scripts/test-package-check.mjs +36 -8
- package/scripts/test-temporary-visibility.mjs +3 -6
- package/src/components/CardList.astro +77 -0
- package/src/components/GalleryGrid.astro +22 -12
- package/src/components/SiteNavigation.astro +5 -4
- package/src/components/SitePage.astro +9 -2
- package/src/components/SiteSection.astro +35 -13
- package/src/content.config.ts +4 -17
- package/src/lib/generatedImages.ts +50 -10
- package/src/lib/sectionContent.ts +130 -35
- package/src/styles/global.css +187 -0
- package/starters/basic/README.md +4 -2
- package/starters/basic/site/content.md +9 -11
- package/starters/project/README.md +7 -3
- package/starters/project/site/content.md +0 -9
- package/starters/project/site/routes/010-guide/route-content.md +0 -5
package/docs/getting-started.md
CHANGED
|
@@ -16,10 +16,13 @@ Install Playwright Chromium only when you plan to run navigation diagnostics:
|
|
|
16
16
|
npx playwright install chromium
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
## Create A Site
|
|
19
|
+
## Create A Site
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
### Standalone Site
|
|
22
|
+
|
|
23
|
+
Use a standalone setup when the website is its own project. Create the site
|
|
24
|
+
from the starter first, then install dependencies inside the new site
|
|
25
|
+
directory:
|
|
23
26
|
|
|
24
27
|
```sh
|
|
25
28
|
cd path/to/your/projects
|
|
@@ -55,11 +58,33 @@ The starter contains:
|
|
|
55
58
|
- `site/config.mjs`
|
|
56
59
|
- `site/theme.md`
|
|
57
60
|
- `site/content.md`
|
|
58
|
-
- `site/images/work/.gitkeep`
|
|
59
61
|
- `site/public/robots.txt`
|
|
60
62
|
|
|
61
63
|
Commit the generated `package-lock.json` after the first install.
|
|
62
64
|
|
|
65
|
+
### Embedded Site
|
|
66
|
+
|
|
67
|
+
Use an embedded setup when a Norna site should live inside an existing Node or
|
|
68
|
+
GitHub project:
|
|
69
|
+
|
|
70
|
+
```sh
|
|
71
|
+
cd existing-project
|
|
72
|
+
npx @janga/norna@latest init . --type embedded --site-dir presentation
|
|
73
|
+
npm install
|
|
74
|
+
npm run norna:dev
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The command looks different because the target is different. `.` means "add
|
|
78
|
+
Norna to the current project" instead of creating a new directory.
|
|
79
|
+
`--site-dir presentation` tells Norna to manage `presentation/` as the site
|
|
80
|
+
directory instead of the default `site/`.
|
|
81
|
+
|
|
82
|
+
Embedded setup keeps the surrounding project structure. It adds namespaced
|
|
83
|
+
`norna:*` scripts so Norna does not take over the project's normal `build`,
|
|
84
|
+
`test`, or deploy scripts.
|
|
85
|
+
|
|
86
|
+
Relevant documentation: [Commands](commands.md), [Site Structure](site-structure.md).
|
|
87
|
+
|
|
63
88
|
## First Edits
|
|
64
89
|
|
|
65
90
|
1. Edit `site/config.mjs` for the site's URL, language labels, GitHub
|
|
@@ -67,9 +92,11 @@ Commit the generated `package-lock.json` after the first install.
|
|
|
67
92
|
2. Edit `site/theme.md` for site-wide layout, layout density, typography
|
|
68
93
|
rhythm, image sizing, font, typography preset, colors, inline styles, and
|
|
69
94
|
frame colors, or omit it to use engine defaults.
|
|
70
|
-
3. Edit `site/content.md` for homepage title, description, sections,
|
|
71
|
-
|
|
72
|
-
|
|
95
|
+
3. Edit `site/content.md` for homepage title, description, Markdown sections,
|
|
96
|
+
text, Norna managed media blocks, page/section presentation overrides, alt
|
|
97
|
+
text, and captions.
|
|
98
|
+
4. Put source images under `site/images/<section-id>/`, where `<section-id>`
|
|
99
|
+
matches a `## Section {#section-id}` heading in `site/content.md`.
|
|
73
100
|
5. Add optional route pages under
|
|
74
101
|
`site/routes/<NNN-route-id>/route-content.md`, for example
|
|
75
102
|
`site/routes/010-about/route-content.md`.
|
|
@@ -78,10 +105,23 @@ Commit the generated `package-lock.json` after the first install.
|
|
|
78
105
|
7. Run:
|
|
79
106
|
|
|
80
107
|
```sh
|
|
108
|
+
npm run norna:config:check
|
|
109
|
+
npm run norna:content:check
|
|
110
|
+
npm run norna:sync
|
|
81
111
|
npm run norna:check
|
|
82
112
|
npm run build
|
|
83
113
|
```
|
|
84
114
|
|
|
115
|
+
`norna:sync` moves misplaced referenced image files when the intended move is
|
|
116
|
+
unambiguous. It can move images between sections and routes, but cross-route
|
|
117
|
+
writes require a clean Git working tree so the operation is easy to roll back.
|
|
118
|
+
Publishing is normally done by committing the site files and pushing them with
|
|
119
|
+
Git; the starter GitHub Pages workflow runs the required checks before
|
|
120
|
+
publishing.
|
|
121
|
+
|
|
122
|
+
Relevant documentation: [Content](content.md), [Theme](theme.md),
|
|
123
|
+
[Typography](typography.md), [Routes](routes.md), [Images And Metadata](images-and-metadata.md).
|
|
124
|
+
|
|
85
125
|
## Configure The Public URL
|
|
86
126
|
|
|
87
127
|
For a custom domain or any site published at the web root, use:
|
|
@@ -104,13 +144,15 @@ site: {
|
|
|
104
144
|
```
|
|
105
145
|
|
|
106
146
|
After that, content files may still use root-style internal links such as
|
|
107
|
-
`/getting-started/` and `/
|
|
147
|
+
`/getting-started/` and `/favicon.svg`. Norna applies `site.basePath` during
|
|
108
148
|
rendering so the built links work under the GitHub Pages project path.
|
|
109
149
|
|
|
110
150
|
The starter includes a GitHub Pages workflow in `.github/workflows/deploy.yml`.
|
|
111
151
|
In the GitHub repository settings, configure Pages to build from GitHub
|
|
112
152
|
Actions.
|
|
113
153
|
|
|
154
|
+
Relevant documentation: [Configuration](configuration.md), [Publishing](publishing.md).
|
|
155
|
+
|
|
114
156
|
Read [Site Structure](site-structure.md), [Content](content.md),
|
|
115
157
|
[Theme](theme.md), [Typography](typography.md), [Routes](routes.md), and
|
|
116
158
|
[Configuration](configuration.md) before publishing a real site.
|
|
@@ -1,26 +1,80 @@
|
|
|
1
1
|
# Images And Metadata
|
|
2
2
|
|
|
3
|
-
This document describes
|
|
3
|
+
This document describes Norna's image pipeline. Site repositories own their
|
|
4
4
|
source images and any copyright or licensing policy for those images.
|
|
5
5
|
|
|
6
|
-
## Source Images
|
|
6
|
+
## Managed Source Images
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
`
|
|
8
|
+
Norna-managed local images are referenced from Markdown with
|
|
9
|
+
`norna-image-stack`, `norna-image-carousel`, or `norna-card-list` blocks. See
|
|
10
|
+
[Content](content.md#managed-media-blocks) for the block syntax.
|
|
11
|
+
|
|
12
|
+
Homepage source images live under:
|
|
13
|
+
|
|
14
|
+
```text
|
|
15
|
+
site/images/<section-id>/
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Route source images live under:
|
|
19
|
+
|
|
20
|
+
```text
|
|
21
|
+
site/routes/<NNN-route-id>/images/<section-id>/
|
|
22
|
+
```
|
|
10
23
|
|
|
11
24
|
Supported source extensions:
|
|
12
25
|
|
|
13
26
|
- `.jpg`
|
|
14
27
|
- `.jpeg`
|
|
15
28
|
- `.png`
|
|
29
|
+
- `.svg`
|
|
30
|
+
|
|
31
|
+
Managed media block references use only the filename:
|
|
32
|
+
|
|
33
|
+
````md
|
|
34
|
+
```norna-image-stack
|
|
35
|
+
- image: portrait.jpg
|
|
36
|
+
alt: Optional alt text.
|
|
37
|
+
caption: Optional caption.
|
|
38
|
+
```
|
|
39
|
+
````
|
|
40
|
+
|
|
41
|
+
`alt` and `caption` are optional. If `alt` is omitted, Norna renders an empty
|
|
42
|
+
alt attribute.
|
|
43
|
+
|
|
44
|
+
For generated or edited images, keep provenance near the image in a source-only
|
|
45
|
+
comment. Norna removes these comments from rendered HTML:
|
|
46
|
+
|
|
47
|
+
```md
|
|
48
|
+
<!-- norna-image-provenance:
|
|
49
|
+
image: portrait.jpg
|
|
50
|
+
source: generated
|
|
51
|
+
prompt: Short prompt or editing note.
|
|
52
|
+
-->
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Filenames do not have to be globally unique for the site to be valid.
|
|
56
|
+
Automatic sync only moves misplaced files when the filename identifies exactly
|
|
57
|
+
one source candidate across the site's page and route image roots, and when the
|
|
58
|
+
move will not break another reference. If the move crosses page or route image
|
|
59
|
+
roots, `content:sync` requires a clean Git working tree before writing.
|
|
16
60
|
|
|
17
|
-
|
|
18
|
-
image scripts reject duplicate filenames because image rows identify images by
|
|
19
|
-
filename only.
|
|
61
|
+
## Markdown Images
|
|
20
62
|
|
|
21
|
-
|
|
63
|
+
Use ordinary Markdown images for external images or static public assets:
|
|
64
|
+
|
|
65
|
+
```md
|
|
66
|
+

|
|
67
|
+

|
|
68
|
+
```
|
|
22
69
|
|
|
23
|
-
|
|
70
|
+
Relative local Markdown images such as `` are not
|
|
71
|
+
managed by Norna. `content:check` warns about them because Norna cannot
|
|
72
|
+
validate, process, or sync those files through the image pipeline.
|
|
73
|
+
|
|
74
|
+
## Generated Variants And Static SVG
|
|
75
|
+
|
|
76
|
+
For raster images, `npm run norna:images` and `npm run norna:build` generate
|
|
77
|
+
WebP files in:
|
|
24
78
|
|
|
25
79
|
```text
|
|
26
80
|
site/.norna/public/images/generated/
|
|
@@ -46,6 +100,19 @@ example-work-1a2b3c4d-1440.webp
|
|
|
46
100
|
When a source image changes, the generated URL changes too. This avoids stale
|
|
47
101
|
browser, CDN, and GitHub Actions cache entries at the old URL.
|
|
48
102
|
|
|
103
|
+
SVG files are managed by the same Markdown media blocks, validation and sync
|
|
104
|
+
model, but they are not rasterized and do not get WebP variants. Norna copies
|
|
105
|
+
the SVG source to:
|
|
106
|
+
|
|
107
|
+
```text
|
|
108
|
+
site/.norna/public/images/original/
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The copied SVG filename includes the source hash. If the SVG has a `viewBox` or
|
|
112
|
+
numeric `width` and `height`, Norna stores that ratio in the image manifest so
|
|
113
|
+
the existing image layout can size it like other images. If no intrinsic aspect
|
|
114
|
+
ratio can be read, the SVG is still rendered directly.
|
|
115
|
+
|
|
49
116
|
## Manifest
|
|
50
117
|
|
|
51
118
|
The generated image manifest is:
|
|
@@ -54,13 +121,15 @@ The generated image manifest is:
|
|
|
54
121
|
site/.norna/generated-images.json
|
|
55
122
|
```
|
|
56
123
|
|
|
57
|
-
It is versioned site state.
|
|
58
|
-
output version, and generated variant paths.
|
|
59
|
-
|
|
60
|
-
|
|
124
|
+
It is versioned site state. For raster images, it stores source hashes,
|
|
125
|
+
original dimensions, output version, and generated variant paths. For static
|
|
126
|
+
SVG images, it stores the source hash, copied public path, output version, and
|
|
127
|
+
intrinsic dimensions when they can be read. The image pipeline reuses generated
|
|
128
|
+
or copied files only when the manifest entry matches the current source hash
|
|
129
|
+
and output version, and all expected output files exist.
|
|
61
130
|
|
|
62
|
-
Generated files under `site/.norna/public/` are build-preparation output
|
|
63
|
-
|
|
131
|
+
Generated files under `site/.norna/public/` are build-preparation output and
|
|
132
|
+
should not be versioned.
|
|
64
133
|
|
|
65
134
|
## Metadata Behavior
|
|
66
135
|
|
|
@@ -70,10 +139,38 @@ copyright metadata.
|
|
|
70
139
|
Generated WebP files are created with ImageMagick using `-strip`, so embedded
|
|
71
140
|
metadata is not a publication mechanism for generated variants. Keep licensing,
|
|
72
141
|
credits, copyright notices, alt text, and captions in site-owned files such as
|
|
73
|
-
`site/content.md`, `COPYRIGHT.md`, or other site
|
|
142
|
+
`site/content.md`, route content files, `COPYRIGHT.md`, or other site
|
|
143
|
+
documentation.
|
|
74
144
|
|
|
75
145
|
If a site wants embedded metadata in original source files, that process is
|
|
76
|
-
outside the current
|
|
146
|
+
outside the current Norna command surface.
|
|
147
|
+
|
|
148
|
+
## AI-Generated Images
|
|
149
|
+
|
|
150
|
+
For AI-generated images, keep provenance and the generation prompt in a
|
|
151
|
+
Markdown comment near the image block. This makes the image maintainable as
|
|
152
|
+
content: future editors can understand where it came from and regenerate or
|
|
153
|
+
revise it without reverse-engineering the asset.
|
|
154
|
+
|
|
155
|
+
````md
|
|
156
|
+
<!--
|
|
157
|
+
AI image prompt for workflow.png:
|
|
158
|
+
A clean editorial illustration of ordinary project files becoming a small
|
|
159
|
+
static website, restrained colors, readable composition, no text in the image.
|
|
160
|
+
-->
|
|
161
|
+
|
|
162
|
+
```norna-image-stack
|
|
163
|
+
- image: workflow.png
|
|
164
|
+
alt: Abstract illustration of project files becoming a website.
|
|
165
|
+
caption: Generated illustration.
|
|
166
|
+
```
|
|
167
|
+
````
|
|
168
|
+
|
|
169
|
+
The same provenance comment style can be used next to a `norna-image-carousel`
|
|
170
|
+
or `norna-card-list` block when generated images are referenced there.
|
|
171
|
+
|
|
172
|
+
This is a maintenance rule for real editorial images. It is not necessary for
|
|
173
|
+
throwaway test fixtures or examples where the prompt has no practical value.
|
|
77
174
|
|
|
78
175
|
## GitHub Actions Cache
|
|
79
176
|
|
|
@@ -83,6 +180,6 @@ The starter workflow caches:
|
|
|
83
180
|
site/.norna/public/images/generated
|
|
84
181
|
```
|
|
85
182
|
|
|
86
|
-
The cache key should include `site/.norna/generated-images.json` so
|
|
87
|
-
|
|
88
|
-
|
|
183
|
+
The cache key should include `site/.norna/generated-images.json` so unchanged
|
|
184
|
+
generated variants can be restored during deploy. With a cache miss or a
|
|
185
|
+
changed source hash, variants are rebuilt from source images.
|
package/docs/routes.md
CHANGED
|
@@ -4,9 +4,14 @@
|
|
|
4
4
|
under `site/routes/<NNN-route-id>/route-content.md` and build to first-level
|
|
5
5
|
URLs.
|
|
6
6
|
|
|
7
|
-
Routes use the same page frontmatter, section
|
|
8
|
-
Markdown section model as the homepage. See
|
|
9
|
-
and section model.
|
|
7
|
+
Routes use the same page frontmatter, optional section metadata, Norna managed
|
|
8
|
+
media blocks, and Markdown section model as the homepage. See
|
|
9
|
+
[Content](content.md) for the page and section model.
|
|
10
|
+
|
|
11
|
+
Route directories can contain route content, route-local images, and
|
|
12
|
+
route-local presentation overrides in `route-content.md`. They cannot contain
|
|
13
|
+
technical site configuration; technical configuration stays at the selected
|
|
14
|
+
site directory's top-level `config.mjs`.
|
|
10
15
|
|
|
11
16
|
## Route Directory Format
|
|
12
17
|
|
|
@@ -61,8 +66,6 @@ title: About
|
|
|
61
66
|
description: About this site.
|
|
62
67
|
navigation:
|
|
63
68
|
label: About
|
|
64
|
-
sections:
|
|
65
|
-
- id: intro
|
|
66
69
|
---
|
|
67
70
|
|
|
68
71
|
## Intro {#intro}
|
|
@@ -99,14 +102,19 @@ Route images live under the physical route directory:
|
|
|
99
102
|
site/routes/010-about/images/intro/image.jpg
|
|
100
103
|
```
|
|
101
104
|
|
|
102
|
-
Image references in route
|
|
105
|
+
Image references in route content still use only the filename:
|
|
103
106
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
- image: image.jpg
|
|
109
|
-
alt: "Intro image."
|
|
107
|
+
````md
|
|
108
|
+
```norna-image-stack
|
|
109
|
+
- image: image.jpg
|
|
110
|
+
alt: Intro image.
|
|
110
111
|
```
|
|
112
|
+
````
|
|
111
113
|
|
|
112
114
|
The image directory segment after `images/` should match the section id.
|
|
115
|
+
If the section id or route folder changes, run `norna content:check` to find
|
|
116
|
+
misplaced images and `norna content:sync` to move unambiguous files into the
|
|
117
|
+
expected section folder. `content:sync` can move images between route image
|
|
118
|
+
roots when the filename is unambiguous across the site and the move will not
|
|
119
|
+
break another reference; these cross-route writes require a clean Git working
|
|
120
|
+
tree.
|
package/docs/site-structure.md
CHANGED
|
@@ -41,8 +41,10 @@ Version these files in a site repository:
|
|
|
41
41
|
image sizing, font, typography defaults, colors, inline styles, and frame
|
|
42
42
|
colors.
|
|
43
43
|
See [Theme](theme.md).
|
|
44
|
-
- `site/content.md`: homepage page file with editable content,
|
|
45
|
-
|
|
44
|
+
- `site/content.md`: homepage page file with editable content, Markdown
|
|
45
|
+
sections, optional section metadata, managed media blocks, alt text, and
|
|
46
|
+
captions.
|
|
47
|
+
See [Content](content.md).
|
|
46
48
|
- `site/images/<section-id>/`: original source images.
|
|
47
49
|
- `site/routes/<NNN-route-id>/route-content.md`: optional route page files.
|
|
48
50
|
See [Routes](routes.md).
|
|
@@ -50,7 +52,7 @@ Version these files in a site repository:
|
|
|
50
52
|
for that route page.
|
|
51
53
|
- `site/public/`: site-specific static public files.
|
|
52
54
|
- `site/.norna/generated-images.json`: generated image manifest used to
|
|
53
|
-
decide whether WebP variants can be reused.
|
|
55
|
+
decide whether WebP variants and copied managed SVG files can be reused.
|
|
54
56
|
- `.github/workflows/deploy.yml`: site-owned GitHub Pages workflow.
|
|
55
57
|
- `package.json` and `package-lock.json`: scripts and pinned engine dependency.
|
|
56
58
|
|
|
@@ -81,8 +83,10 @@ In this repository:
|
|
|
81
83
|
- `bin/norna-cli.mjs` dispatches public CLI commands.
|
|
82
84
|
- `scripts/` contains validation, image, local preview, deploy, and test tools.
|
|
83
85
|
- `src/` contains the Astro renderer, components, styles, and content schema.
|
|
84
|
-
- `starters/basic/` is
|
|
85
|
-
|
|
86
|
+
- `starters/basic/` is the default compact starter copied by
|
|
87
|
+
`norna init <target-dir>`.
|
|
88
|
+
- `starters/project/` is a project-site starter used as a maintained example
|
|
89
|
+
for small project and developer-tool sites.
|
|
86
90
|
- `fixtures/basic/site/` is used by engine regression tests.
|
|
87
91
|
- `examples/dog-gallery/site/` is the local visual dog example used by demo
|
|
88
92
|
builds and navigation diagnostics.
|
package/docs/theme.md
CHANGED
|
@@ -6,7 +6,8 @@ missing, built-in engine defaults are used.
|
|
|
6
6
|
|
|
7
7
|
Page-level presentation in `site/content.md` and route page files is always an
|
|
8
8
|
override on top of `site/theme.md`. Section-level presentation is an override
|
|
9
|
-
on top of the resolved page presentation.
|
|
9
|
+
on top of the resolved page presentation. Use those overrides for focused
|
|
10
|
+
exceptions; the normal place for shared visual choices is `site/theme.md`.
|
|
10
11
|
|
|
11
12
|
## Minimal Theme
|
|
12
13
|
|
|
@@ -73,9 +74,9 @@ navigation:
|
|
|
73
74
|
`desktop` / `mobile` values.
|
|
74
75
|
- `density`: default structural spacing profile. Allowed values are `compact`,
|
|
75
76
|
`normal`, and `airy`.
|
|
76
|
-
- `spacing`: optional structural spacing overrides for sections and
|
|
77
|
-
|
|
78
|
-
`desktop` / `mobile` values.
|
|
77
|
+
- `spacing`: optional structural spacing overrides for sections and Norna
|
|
78
|
+
managed media blocks. Every spacing value accepts either one CSS length for all
|
|
79
|
+
viewports or `desktop` / `mobile` values.
|
|
79
80
|
|
|
80
81
|
Example:
|
|
81
82
|
|
|
@@ -104,8 +105,8 @@ Spacing keys:
|
|
|
104
105
|
- `firstSectionTop`: space above the first section heading.
|
|
105
106
|
- `sectionGap`: space above each following section.
|
|
106
107
|
- `finalSectionBottom`: space below the final section.
|
|
107
|
-
- `bodyToImages`: space from section body text to
|
|
108
|
-
- `imageGap`: space between
|
|
108
|
+
- `bodyToImages`: space from section body text to Norna managed media blocks.
|
|
109
|
+
- `imageGap`: space between stacked images or carousel blocks.
|
|
109
110
|
|
|
110
111
|
Text-near spacing, such as spacing after headings, spacing before Markdown
|
|
111
112
|
subheadings, paragraph spacing, and caption spacing, belongs to
|
|
@@ -206,11 +207,14 @@ presentation:
|
|
|
206
207
|
paragraphSpacing: 1em
|
|
207
208
|
```
|
|
208
209
|
|
|
209
|
-
Section-specific presentation belongs under
|
|
210
|
+
Section-specific presentation belongs under
|
|
211
|
+
`sections.<section-id>.presentation`. Use it when one section genuinely needs
|
|
212
|
+
different presentation; do not use `sections` to define section order or normal
|
|
213
|
+
Markdown structure.
|
|
210
214
|
|
|
211
215
|
```yaml
|
|
212
216
|
sections:
|
|
213
|
-
|
|
217
|
+
intro:
|
|
214
218
|
presentation:
|
|
215
219
|
backgroundColor: "#161616"
|
|
216
220
|
textColor: "#ffffff"
|
package/docs/typography.md
CHANGED
|
@@ -5,8 +5,8 @@ presets, text rhythm, and optional overrides.
|
|
|
5
5
|
|
|
6
6
|
The normal place to choose a site-wide typography preset and rhythm is the
|
|
7
7
|
top-level `typography` block in `site/theme.md`.
|
|
8
|
-
Page and section files may override the theme when a
|
|
9
|
-
|
|
8
|
+
Page and section files may override the theme when a focused exception is
|
|
9
|
+
needed, but the normal workflow is to keep typography in `theme.md`.
|
|
10
10
|
|
|
11
11
|
## Presets
|
|
12
12
|
|
|
@@ -18,9 +18,8 @@ Available presets:
|
|
|
18
18
|
short information blocks.
|
|
19
19
|
- `text-forward`: more generous body text for pages where longer text carries
|
|
20
20
|
more of the experience.
|
|
21
|
-
- `statement`: tighter, more declarative line-height for
|
|
22
|
-
|
|
23
|
-
section override.
|
|
21
|
+
- `statement`: tighter, more declarative line-height for short programmatic
|
|
22
|
+
statements. Use it sparingly, usually as a page or section exception.
|
|
24
23
|
|
|
25
24
|
If theme typography is omitted, `quiet-gallery` is used.
|
|
26
25
|
|
|
@@ -132,10 +131,10 @@ typography:
|
|
|
132
131
|
```
|
|
133
132
|
|
|
134
133
|
A page-level `presentation.typography.preset` changes the typographic character
|
|
135
|
-
for that page. A section-level
|
|
136
|
-
changes the typographic
|
|
137
|
-
|
|
138
|
-
set.
|
|
134
|
+
for that page. A section-level
|
|
135
|
+
`sections.<section-id>.presentation.typography.preset` changes the typographic
|
|
136
|
+
character for that section. `rhythm` is inherited separately, so changing
|
|
137
|
+
preset does not change spacing unless `rhythm` is also set.
|
|
139
138
|
|
|
140
139
|
If a section sets `typography.rhythm`, that section changes text-near spacing.
|
|
141
140
|
If a section only sets `typography.overrides`, it keeps the resolved page
|
|
@@ -145,7 +144,7 @@ Example section override:
|
|
|
145
144
|
|
|
146
145
|
```yaml
|
|
147
146
|
sections:
|
|
148
|
-
|
|
147
|
+
intro:
|
|
149
148
|
presentation:
|
|
150
149
|
typography:
|
|
151
150
|
preset: statement
|
|
@@ -4,84 +4,10 @@ description: A small norna example with free dog images.
|
|
|
4
4
|
navigation:
|
|
5
5
|
label: Dog site!
|
|
6
6
|
sections:
|
|
7
|
-
-
|
|
8
|
-
presentation:
|
|
9
|
-
typography:
|
|
10
|
-
preset: statement
|
|
11
|
-
overrides:
|
|
12
|
-
headings:
|
|
13
|
-
h2:
|
|
14
|
-
size: xlarge
|
|
15
|
-
gallery:
|
|
16
|
-
- image: photo-of-a-black-dog.jpg
|
|
17
|
-
alt: "A black dog sitting outdoors and looking at the camera."
|
|
18
|
-
caption:
|
|
19
|
-
"Photo of a dog. ContaDeletada2906, CC0 1.0, via Wikimedia Commons."
|
|
20
|
-
- image: black-puppy-meadow.png
|
|
21
|
-
alt:
|
|
22
|
-
"A black puppy standing in a grassy meadow and looking at the camera."
|
|
23
|
-
caption: "AI-generated image."
|
|
24
|
-
- id: summer-dogs
|
|
7
|
+
summer-dogs:
|
|
25
8
|
visible:
|
|
26
9
|
from: "2026-08-01"
|
|
27
10
|
until: "2026-09-01"
|
|
28
|
-
presentation:
|
|
29
|
-
backgroundColor: "#181818"
|
|
30
|
-
typography:
|
|
31
|
-
preset: compact-gallery
|
|
32
|
-
gallery: []
|
|
33
|
-
- id: brown-dogs
|
|
34
|
-
presentation:
|
|
35
|
-
typography:
|
|
36
|
-
preset: text-forward
|
|
37
|
-
gallery:
|
|
38
|
-
- image: brown-dog.jpg
|
|
39
|
-
alt: "A brown dog looking directly at the camera."
|
|
40
|
-
caption: "DogBrown. Frank-3, CC0 1.0, via Wikimedia Commons."
|
|
41
|
-
- image: dog-accompanies-master.jpg
|
|
42
|
-
alt: "A man walks outdoors with a dog at his side."
|
|
43
|
-
caption:
|
|
44
|
-
"Dog accompanies his master. Steve Hillebrand, U.S. Fish and Wildlife
|
|
45
|
-
Service, public domain."
|
|
46
|
-
- id: golden-dogs
|
|
47
|
-
presentation:
|
|
48
|
-
typography:
|
|
49
|
-
overrides:
|
|
50
|
-
headings:
|
|
51
|
-
h2:
|
|
52
|
-
size: large
|
|
53
|
-
h3:
|
|
54
|
-
size: medium
|
|
55
|
-
body:
|
|
56
|
-
lineHeight: 1.58
|
|
57
|
-
paragraphSpacing: 1em
|
|
58
|
-
gallery:
|
|
59
|
-
- image: golden-retriever.jpg
|
|
60
|
-
alt: "A golden retriever standing outdoors."
|
|
61
|
-
caption: "Golden Retriever. Ribo, public domain, via Wikimedia Commons."
|
|
62
|
-
- image: toller-puppy.jpg
|
|
63
|
-
alt:
|
|
64
|
-
"A young Nova Scotia Duck Tolling Retriever puppy sitting on grass."
|
|
65
|
-
caption:
|
|
66
|
-
"Nova Scotia Duck Tolling Retriever puppy. RM, public domain, via
|
|
67
|
-
Wikimedia Commons."
|
|
68
|
-
- id: white-dogs
|
|
69
|
-
presentation:
|
|
70
|
-
typography:
|
|
71
|
-
overrides:
|
|
72
|
-
caption:
|
|
73
|
-
spacingBefore: 0.35em
|
|
74
|
-
gallery:
|
|
75
|
-
- carousel:
|
|
76
|
-
- image: white-cute-dog.jpg
|
|
77
|
-
alt: "A white dog looking toward the camera."
|
|
78
|
-
caption:
|
|
79
|
-
"White cute dog. Neal Ziring, public domain, via Wikimedia
|
|
80
|
-
Commons."
|
|
81
|
-
- image: white-puppy-garden.png
|
|
82
|
-
alt: "A fluffy white puppy standing on grass in a garden."
|
|
83
|
-
caption: "AI-generated image."
|
|
84
|
-
- id: sources
|
|
85
11
|
---
|
|
86
12
|
|
|
87
13
|
## Black Dogs {#black-dogs}
|
|
@@ -104,6 +30,15 @@ This `####` heading should follow `typography.headings.h4`.
|
|
|
104
30
|
Curabitur blandit tempus porttitor. Donec id elit non mi porta gravida at eget
|
|
105
31
|
metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.
|
|
106
32
|
|
|
33
|
+
```norna-image-stack
|
|
34
|
+
- image: photo-of-a-black-dog.jpg
|
|
35
|
+
alt: A black dog sitting outdoors and looking at the camera.
|
|
36
|
+
caption: Photo of a dog. ContaDeletada2906, CC0 1.0, via Wikimedia Commons.
|
|
37
|
+
- image: black-puppy-meadow.png
|
|
38
|
+
alt: A black puppy standing in a grassy meadow and looking at the camera.
|
|
39
|
+
caption: AI-generated image.
|
|
40
|
+
```
|
|
41
|
+
|
|
107
42
|
## Summer Dogs {#summer-dogs}
|
|
108
43
|
|
|
109
44
|
This temporary section is visible during August 2026. It is here to demonstrate
|
|
@@ -126,6 +61,15 @@ Maecenas sed diam eget risus varius blandit sit amet non magna. Morbi leo risus,
|
|
|
126
61
|
porta ac consectetur ac, vestibulum at eros. Sed posuere consectetur est at
|
|
127
62
|
lobortis.
|
|
128
63
|
|
|
64
|
+
```norna-image-stack
|
|
65
|
+
- image: brown-dog.jpg
|
|
66
|
+
alt: A brown dog looking directly at the camera.
|
|
67
|
+
caption: DogBrown. Frank-3, CC0 1.0, via Wikimedia Commons.
|
|
68
|
+
- image: dog-accompanies-master.jpg
|
|
69
|
+
alt: A man walks outdoors with a dog at his side.
|
|
70
|
+
caption: Dog accompanies his master. Steve Hillebrand, U.S. Fish and Wildlife Service, public domain.
|
|
71
|
+
```
|
|
72
|
+
|
|
129
73
|
## Golden Dogs {#golden-dogs}
|
|
130
74
|
|
|
131
75
|
Golden-coated retrievers add a third image section and more scrolling depth.
|
|
@@ -134,13 +78,21 @@ Cras justo odio, dapibus ac facilisis in, egestas eget quam.
|
|
|
134
78
|
|
|
135
79
|
### Training note
|
|
136
80
|
|
|
137
|
-
This
|
|
138
|
-
site-wide `headings.h4` style.
|
|
81
|
+
This `###` heading follows the site-wide `headings.h3` style.
|
|
139
82
|
|
|
140
83
|
Nulla vitae elit libero, a pharetra augue. Integer posuere erat a ante venenatis
|
|
141
84
|
dapibus posuere velit aliquet. Aenean eu leo quam. Pellentesque ornare sem
|
|
142
85
|
lacinia quam venenatis vestibulum.
|
|
143
86
|
|
|
87
|
+
```norna-image-stack
|
|
88
|
+
- image: golden-retriever.jpg
|
|
89
|
+
alt: A golden retriever standing outdoors.
|
|
90
|
+
caption: Golden Retriever. Ribo, public domain, via Wikimedia Commons.
|
|
91
|
+
- image: toller-puppy.jpg
|
|
92
|
+
alt: A young Nova Scotia Duck Tolling Retriever puppy sitting on grass.
|
|
93
|
+
caption: Nova Scotia Duck Tolling Retriever puppy. RM, public domain, via Wikimedia Commons.
|
|
94
|
+
```
|
|
95
|
+
|
|
144
96
|
## White Dogs {#white-dogs}
|
|
145
97
|
|
|
146
98
|
A white dog completes the colour-based image sequence.
|
|
@@ -152,6 +104,15 @@ Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Lorem ipsum
|
|
|
152
104
|
dolor sit amet, consectetur adipiscing elit. Donec sed odio dui. Vestibulum id
|
|
153
105
|
ligula porta felis euismod semper.
|
|
154
106
|
|
|
107
|
+
```norna-image-stack
|
|
108
|
+
- image: white-cute-dog.jpg
|
|
109
|
+
alt: A white dog looking toward the camera.
|
|
110
|
+
caption: White cute dog. Neal Ziring, public domain, via Wikimedia Commons.
|
|
111
|
+
- image: white-puppy-garden.png
|
|
112
|
+
alt: A fluffy white puppy standing on grass in a garden.
|
|
113
|
+
caption: AI-generated image.
|
|
114
|
+
```
|
|
115
|
+
|
|
155
116
|
## Sources {#sources}
|
|
156
117
|
|
|
157
118
|
Most images are sourced from Wikimedia Commons pages that list CC0 or
|
|
@@ -3,16 +3,6 @@ title: Dog care
|
|
|
3
3
|
description: A small route for testing multi-page norna navigation.
|
|
4
4
|
navigation:
|
|
5
5
|
label: Dog care
|
|
6
|
-
sections:
|
|
7
|
-
- id: daily-rhythm
|
|
8
|
-
presentation:
|
|
9
|
-
typography:
|
|
10
|
-
overrides:
|
|
11
|
-
headings:
|
|
12
|
-
h2:
|
|
13
|
-
size: large
|
|
14
|
-
- id: calm-training
|
|
15
|
-
- id: media-notes
|
|
16
6
|
---
|
|
17
7
|
|
|
18
8
|
## Daily rhythm {#daily-rhythm}
|