Seed: eyes design on showcase, whale/wave art, richer long read

- The showcase category picks the eyes banner design (inherited by its
  pages; night-sky overrides with stars); the seeder now leaves
  content=None for entries with empty markdown so it stays a category
  label.
- Public-domain demo images in pagerite/seed-assets/ (Hokusai's Great
  Wave, Shute's 1892 Moby-Dick engravings), shipped via build artifacts.
- Welcome figure uses {width=420}; Gallery gets the Great Wave as its
  {.wide} piece; Loomings gains h2/h3 sections and the engravings.
This commit is contained in:
2026-08-19 02:00:54 +00:00
parent dfd3ef1dad
commit 178d22c05c
7 changed files with 108 additions and 30 deletions
+5 -1
View File
@@ -130,7 +130,11 @@ def _seed(data: Data) -> None:
markdown, banner = _store_seed_file(markdown, banner, orig, body)
node = _ensure(data.menu, path)
node.title = title
node.content = markdown
# Empty markdown means a pure category label (e.g. "showcase",
# seeded only to carry a banner design): leave content as None so
# the node renders the placeholder and nav points at its children.
if markdown:
node.content = markdown
node.banner = banner
node.banner_design = design
node.order = order
+2 -2
View File
@@ -91,8 +91,8 @@ class Data(msgspec.Struct):
#: banner artwork, next to the nav. Empty = the plain brand link.
brand_html: str = ""
#: Active theme name (empty = none/base only). Themes live in
#: frontend/src/assets/themes/{theme}/theme.css, with their banner
#: artwork at pagerite/themes/{theme}/banner.svg (inlined server-side).
#: pagerite/themes/{theme}/ (theme.css and/or banner.css/banner.svg/
#: banner.html), served by the backend from disk.
theme: str = "purple"
#: Raw site-wide custom CSS, injected inline in every page <head>.
#: Trusted author content; not sanitized.
Binary file not shown.

After

Width:  |  Height:  |  Size: 410 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

+98 -25
View File
@@ -6,8 +6,21 @@ menu levels deep) covering editing and the full Markdown feature set —
each feature shown as its Markdown source in a code block followed by
the rendered result — and a showcase section with image positioning,
long-form layout and a simple custom banner.
Binary seed images live in ``seed-assets/`` (public domain, from
Wikimedia Commons: the two whale engravings are Augustus Burnham
Shute's illustrations for an 1892 edition of Moby-Dick; the wave is
Hokusai's "The Great Wave off Kanagawa").
"""
from pathlib import Path
ASSETS = Path(__file__).with_name("seed-assets")
def _asset(name: str) -> bytes:
return (ASSETS / name).read_bytes()
WELCOME = """\
Welcome to your new **Pagerite** site. Everything you see is a page written in Markdown, served from a pretty URL, and editable right here in the browser.
@@ -17,7 +30,7 @@ Where to go next:
- The [showcase](/showcase/gallery) section shows what finished pages can look like: image positioning, banners, a long read.
- Click the 🖊️ pen on any page to open the editor, and the ⚙️ pen for site settings and the structure tree.
![Abstract waves](waves.svg "Generated SVG artwork, attached to this page")
![Abstract waves](waves.svg "Generated SVG artwork, attached to this page"){width=420}
*Delete or rewrite any of these pages — they are only here to get you started.*
"""
@@ -248,32 +261,81 @@ If your Markdown contains its own `# heading`, the page title is not repeated as
"""
GALLERY = """\
Pages can attach images and position them freely. All artwork here is generated SVG, stored content-addressed and served from `/_f/`.
Pages can attach images and position them freely. The vector artwork here is generated SVG; the woodblock print is Hokusai's *The Great Wave off Kanagawa* (public domain, via Wikimedia Commons).
![The Great Wave off Kanagawa](great-wave.jpg "Hokusai, c. 1831 — full-bleed with {.wide}"){.wide}
A wide image escapes the text column for emphasis between sections. No HTML needed — just Markdown and an attribute.
![Shapes](shapes.svg "Floated left with {.left}"){.left width=240}
This text wraps around a left-floated figure. The caption comes from the image title, the float from `{.left width=240}` — brace attributes on the image itself.
![Waves](waves.svg "Floated right with {.right}"){.right width=240}
![Abstract waves](waves.svg "Floated right with {.right}"){.right width=240}
Mixing floats in one article is fine. Both images were uploaded to this page and referenced by relative path, so the whole page (images included) can be moved in the structure tree without breaking anything.
![Dunes](dunes.svg "Full-bleed with {.wide}"){.wide}
A wide image escapes the text column for emphasis between sections. No HTML needed — just Markdown and an attribute.
"""
NIGHT_SKY = """\
This page's banner is not an image — it's a few lines of HTML stored with the page:
This page's banner is not an image or a code snippet — it's the **stars** banner design, picked from a dropdown in the banner editor (🖊️ in the banner corner). Nothing is stored in the page beyond that choice.
```html
<div style="background: linear-gradient(100deg, #14243d, #3d2b6b 45%,
#7c5cff 75%, #ff5c8a); height: 100%"></div>
```
Banner designs are folders in `pagerite/themes/{name}/` — a `banner.css` plus a `banner.html` or `banner.svg` — so a design can be anything from a static gradient to an animated canvas like the starfield above. This site ships `stars` and `eyes` (a critter in the grass), and themes can bring their own.
Banners are arbitrary trusted markup: a styled div, an `<img>`, even a canvas with a script. Subpages inherit the nearest banner up their path, so a whole section can share one look — this one is set on a leaf page, so nothing else inherits it.
Subpages inherit the nearest banner and design up their path, so a whole section can share one look. This page is a leaf: set a design here and nothing else is affected.
For animated banners, pick a **banner design** in the banner editor instead of writing code: this site ships `stars` (a drifting starfield) and `eyes` (a critter in the grass), and themes can bring their own. Designs are folders in `pagerite/themes/{name}/` — a `banner.css` plus a `banner.html` or `banner.svg` — and are selectable on any page via the UI.
A page can also carry its own banner HTML — an `<img>`, a styled div, a canvas with a script — which renders *on top of* the design's artwork, so author code always wins. But most of the time, picking a design is all you need.
"""
# Moby-Dick; or, The Whale (1851), Herman Melville — public domain.
# Chapter 1, abridged and headed. A real long-read: flowing sections,
# figures, a list — not a feature showcase. (Engravings: Augustus
# Burnham Shute's illustrations for the 1892 edition, public domain.)
LOOMINGS = """\
*The opening of Herman Melville's Moby-Dick (1851), abridged — here to show what a longer article feels like: the multi-column layout on wide screens, images breaking up the text, and the gentle reveal as sections scroll into view.*
{dates}
![Dunes at dusk](dunes.svg "Full-width artwork between sections"){.wide}
## The watery part of the world
Call me Ishmael. Some years ago — never mind how long precisely — having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen and regulating the circulation. Whenever I find myself growing grim about the mouth; whenever it is a damp, drizzly November in my soul; whenever I find myself involuntarily pausing before coffin warehouses, and bringing up the rear of every funeral I meet; and especially whenever my hypos get such an upper hand of me, that it requires a strong moral principle to prevent me from deliberately stepping into the street, and methodically knocking people's hats off — then, I account it high time to get to sea as soon as I can. This is my substitute for pistol and ball. With a philosophical flourish Cato throws himself upon his sword; I quietly take to the ship. There is nothing surprising in this. If they but knew it, almost all men in their degree, some time or other, cherish very nearly the same feelings towards the ocean with me.
![Moby Dick breeches a whaleboat](md-whale.jpg "Augustus Burnham Shute, 1892 — public domain"){.right width=320}
There now is your insular city of the Manhattoes, belted round by wharves as Indian isles by coral reefs — commerce surrounds it with her surf. Right and left, the streets take you waterward. Its extreme downtown is the battery, where that noble mole is washed by waves, and cooled by breezes, which a few hours previous were out of sight of land. Look at the crowds of water-gazers there.
Circumambulate the city of a dreamy Sabbath afternoon. Go from Corlears Hook to Coenties Slip, and from thence, by Whitehall, northward. What do you see? — Posted like silent sentinels all around the town, stand thousands upon thousands of mortal men fixed in ocean reveries. Some leaning against the spiles; some seated upon the pier-heads; some looking over the bulwarks of ships from China; some high aloft in the rigging, as if striving to get a still better seaward peep. But these are all landsmen; of week days pent up in lath and plaster — tied to counters, nailed to benches, clinched to desks. How then is this? Are the green fields gone? What do they here?
But look! here come more crowds, pacing straight for the water, and seemingly bound for a dive. Strange! Nothing will content them but the extremest limit of the land; loitering under the shady lee of yonder warehouses will not suffice. No. They must get just as nigh the water as they possibly can without falling in. And there they stand — miles of them — leagues. Inlanders all, they come from lanes and alleys, streets and avenues — north, east, south, and west. Yet here they all unite. Tell me, does the magnetic virtue of the needles of the compasses of all those ships attract them thither?
## Meditation and water
Once more. Say you are in the country; in some high land of lakes. Take almost any path you please, and ten to one it carries you down in a dale, and leaves you there by a pool in the stream. There is magic in it. Let the most absent-minded of men be plunged in his deepest reveries — stand that man on his legs, set his feet a-going, and he will infallibly lead you to water, if water there be in all that region. Should you ever be athirst in the great American desert, try this experiment, if your caravan happen to be supplied with a metaphysical professor. Yes, as every one knows, meditation and water are wedded for ever.
### The artist's problem
But here is an artist. He desires to paint you the dreamiest, shadiest, quietest, most enchanting bit of romantic landscape in all the valley of the Saco. What is the chief element he employs? There stand his trees, each with a hollow trunk, as if a hermit and a crucifix were within; and here sleeps his meadow, and there sleep his cattle; and up from yonder cottage goes a sleepy smoke. Deep into distant woodlands winds a mazy way, reaching to overlapping spurs of mountains bathed in their hill-side blue. But though the picture lies thus tranced, and though this pine-tree shakes down its sighs like leaves upon this shepherd's head, yet all were vain, unless the shepherd's eye were fixed upon the magic stream before him.
Why did the poor poet of Tennessee, upon suddenly receiving two handfuls of silver, deliberate whether to buy him a coat, which he sadly needed, or invest his money in a pedestrian trip to Rockaway Beach? Why is almost every robust healthy boy with a robust healthy soul in him, at some time or other crazy to go to sea? Why upon your first voyage as a passenger, did you yourself feel such a mystical vibration, when you were first told that you and your ship were now out of sight of land? Why did the old Persians hold the sea holy? Why did the Greeks give it a separate deity, and own brother of Jove? Surely all this is not without meaning. And still deeper the meaning of that story of Narcissus, who because he could not grasp the tormenting, mild image he saw in the fountain, plunged into it and was drowned. But that same image, we ourselves see in all rivers and oceans. It is the image of the ungraspable phantom of life; and this is the key to it all.
## A simple sailor, right before the mast
Now, when I say that I am in the habit of going to sea whenever I begin to grow hazy about the eyes, and begin to be over conscious of my lungs, I do not mean to have it inferred that I ever go to sea as a passenger. For to go as a passenger you must needs have a purse, and a purse is but a rag unless you have something in it. Besides, passengers get sea-sick — grow quarrelsome — don't sleep of nights — do not enjoy themselves much, as a general thing; — no, I never go as a passenger; nor, though I am something of a salt, do I ever go to sea as a Commodore, or a Captain, or a Cook. I abandon the glory and distinction of such offices to those who like them. For my part, I abominate all honorable respectable toils, trials, and tribulations of every kind whatsoever. It is quite as much as I can do to take care of myself, without taking care of ships, barques, brigs, schooners, and what not.
No, when I go to sea, I go as a simple sailor, right before the mast, plumb down into the forecastle, aloft there to the royal mast-head. True, they rather order me about some, and make me jump from spar to spar, like a grasshopper in a May meadow. And at first, this sort of thing is unpleasant enough. It touches one's sense of honor, particularly if you come of an old established family in the land, the Van Rensselaers, or Randolphs, or Hardicanutes. And more than all, if just previous to putting your hand into the tar-pot, you have been lording it as a country schoolmaster, making the tallest boys stand in awe of you. The transition is a keen one, I assure you, from a schoolmaster to a sailor, and requires a strong decoction of Seneca and the Stoics to enable you to grin and bear it. But even this wears off in time.
![The final chase](md-chase.jpg "A. Burnham Shute's illustration of the final chase, 1892 — public domain")
What of it, if some old hunks of a sea-captain orders me to get a broom and sweep down the decks? What does that indignity amount to, weighed, I mean, in the scales of the New Testament? Do you think the archangel Gabriel thinks anything the less of me, because I promptly and respectfully obey that old hunks in that particular instance? Who ain't a slave? Tell me that. Well, then, however the old sea-captains may order me about — however they may thump and punch me about, I have the satisfaction of knowing that it is all right; that everybody else is one way or other served in much the same way — either in a physical or metaphysical point of view, that is; and so the universal thump is passed round, and all hands should rub each other's shoulder-blades, and be content.
And finally, what shall I say of the reasons for going a-whaling? Chief among them:
- The overwhelming idea of the great whale himself — such a portentous and mysterious monster roused all my curiosity.
- The undeliverable, nameless perils of the whale, and the attendants of the wondrous world of waters.
- The tormenting, mild image of the ungraspable phantom of life, seen in all rivers and oceans.
These were the things that finally drew me to the sea — and if they but knew it, almost all men cherish very nearly the same feelings towards the ocean with me.
"""
SMALL_RELEASES = """\
@@ -296,11 +358,6 @@ This site runs on **Pagerite**: FastAPI + html5tagger + kanta, with content writ
*Replace this page with whatever your site is about.*
"""
BANNER_DIV = (
'<div style="background: linear-gradient(100deg, #14243d, #3d2b6b 45%,'
' #7c5cff 75%, #ff5c8a); height: 100%"></div>'
)
WAVES_SVG = """\
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 400">
<defs>
@@ -344,12 +401,15 @@ DUNES_SVG = """\
"""
#: path -> (title, markdown, {filename: bytes}, banner HTML, menu order,
#: banner design). Banners are deliberately set only on one leaf page
#: (showcase/night-sky), so nothing else inherits a custom banner.
#: banner design). Designs demonstrate inheritance: the "showcase" label
#: picks "eyes" (all its pages show the critter), and the leaf
#: "showcase/night-sky" overrides that with "stars". Elsewhere the active
#: theme's own design shows.
#: Note there are deliberately no "docs" or "showcase" landing pages:
#: those labels are created without content, so they render a placeholder
#: page and their nav links point at the first child (see
#: views.first_leaf).
#: views.first_leaf). "showcase" is seeded explicitly (empty markdown,
#: which the seeder leaves as content=None) just to carry the design.
PAGES: dict[str, tuple[str, str, dict[str, bytes], str, float, str | None]] = {
"": ("Welcome", WELCOME, {"waves.svg": WAVES_SVG.encode()}, "", 1, None),
"about": ("About", ABOUT, {}, "", 3, None),
@@ -371,18 +431,31 @@ PAGES: dict[str, tuple[str, str, dict[str, bytes], str, float, str | None]] = {
3,
None,
),
"showcase": ("Showcase", "", {}, "", 4, "eyes"),
"showcase/gallery": (
"Gallery",
GALLERY,
{
"great-wave.jpg": _asset("great-wave.jpg"),
"shapes.svg": SHAPES_SVG.encode(),
"waves.svg": WAVES_SVG.encode(),
"dunes.svg": DUNES_SVG.encode(),
},
"",
1,
None,
),
"showcase/night-sky": ("Night Sky", NIGHT_SKY, {}, BANNER_DIV, 2, None),
"showcase/small-releases": ("Small Releases", SMALL_RELEASES, {}, "", 3, None),
"showcase/loomings": (
"Loomings — a Long Read",
LOOMINGS,
{
"dunes.svg": DUNES_SVG.encode(),
"md-whale.jpg": _asset("md-whale.jpg"),
"md-chase.jpg": _asset("md-chase.jpg"),
},
"",
2,
None,
),
"showcase/night-sky": ("Night Sky", NIGHT_SKY, {}, "", 3, "stars"),
"showcase/small-releases": ("Small Releases", SMALL_RELEASES, {}, "", 4, None),
}
+3 -2
View File
@@ -45,8 +45,9 @@ packages = ["pagerite"]
[tool.hatch.build]
# `only-packages` drops directories without an __init__.py, so the theme
# files must be force-included as artifacts (like the frontend build).
artifacts = ["pagerite/frontend-build", "pagerite/themes"]
# files and seed image assets must be force-included as artifacts (like
# the frontend build).
artifacts = ["pagerite/frontend-build", "pagerite/themes", "pagerite/seed-assets"]
only-packages = true
[tool.hatch.build.targets.sdist.hooks.custom]