create-cogenta 0.5.3 → 0.6.7
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/dist/blueprint-defaults.js +1 -1
- package/dist/blueprint-defaults.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/playground-reset.js +1 -1
- package/dist/playground-reset.js.map +1 -1
- package/dist/recap.js +1 -1
- package/dist/recap.js.map +1 -1
- package/dist/scaffold.d.ts +4 -2
- package/dist/scaffold.d.ts.map +1 -1
- package/dist/scaffold.js +10 -6
- package/dist/scaffold.js.map +1 -1
- package/dist/wizard.js +1 -1
- package/dist/wizard.js.map +1 -1
- package/package.json +14 -13
- package/dist/blueprints/assets/photos/association/community-cleanup.jpg +0 -0
- package/dist/blueprints/assets/photos/association/fundraising-dinner.jpg +0 -0
- package/dist/blueprints/assets/photos/association/garden-planting.jpg +0 -0
- package/dist/blueprints/assets/photos/association/harvest-food-drive.jpg +0 -0
- package/dist/blueprints/assets/photos/association/hero.jpg +0 -0
- package/dist/blueprints/assets/photos/association/volunteer-orientation.jpg +0 -0
- package/dist/blueprints/assets/photos/association/winter-coat-collection.jpg +0 -0
- package/dist/blueprints/assets/photos/blog/blog-runs-itself.jpg +0 -0
- package/dist/blueprints/assets/photos/blog/desk-setup.jpg +0 -0
- package/dist/blueprints/assets/photos/blog/editing.jpg +0 -0
- package/dist/blueprints/assets/photos/blog/hero.jpg +0 -0
- package/dist/blueprints/assets/photos/blog/notebooks.jpg +0 -0
- package/dist/blueprints/assets/photos/blog/plain-text-editor.jpg +0 -0
- package/dist/blueprints/assets/photos/blog/reading-nonfiction.jpg +0 -0
- package/dist/blueprints/assets/photos/blog/small-tool.jpg +0 -0
- package/dist/blueprints/assets/photos/blog/writing-schedule.jpg +0 -0
- package/dist/blueprints/assets/photos/magazine/business-2.jpg +0 -0
- package/dist/blueprints/assets/photos/magazine/business-3.jpg +0 -0
- package/dist/blueprints/assets/photos/magazine/business.jpg +0 -0
- package/dist/blueprints/assets/photos/magazine/culture-2.jpg +0 -0
- package/dist/blueprints/assets/photos/magazine/culture-3.jpg +0 -0
- package/dist/blueprints/assets/photos/magazine/culture.jpg +0 -0
- package/dist/blueprints/assets/photos/magazine/news-2.jpg +0 -0
- package/dist/blueprints/assets/photos/magazine/news-3.jpg +0 -0
- package/dist/blueprints/assets/photos/magazine/news.jpg +0 -0
- package/dist/blueprints/assets/photos/magazine/opinion-2.jpg +0 -0
- package/dist/blueprints/assets/photos/magazine/opinion-3.jpg +0 -0
- package/dist/blueprints/assets/photos/magazine/opinion.jpg +0 -0
- package/dist/blueprints/assets/photos/portfolio/adatum-publishing.jpg +0 -0
- package/dist/blueprints/assets/photos/portfolio/contoso-mobile-app.jpg +0 -0
- package/dist/blueprints/assets/photos/portfolio/fabrikam-annual-report.jpg +0 -0
- package/dist/blueprints/assets/photos/portfolio/hero.jpg +0 -0
- package/dist/blueprints/assets/photos/portfolio/litware-signage.jpg +0 -0
- package/dist/blueprints/assets/photos/portfolio/northwind-rebrand.jpg +0 -0
- package/dist/blueprints/assets/photos/portfolio/proseware-launch.jpg +0 -0
- package/dist/blueprints/assets/photos/portfolio/tailspin-streaming.jpg +0 -0
- package/dist/blueprints/assets/photos/portfolio/wingtip-wayfinding.jpg +0 -0
- package/dist/blueprints/assets/photos/restaurant/charred-octopus.jpg +0 -0
- package/dist/blueprints/assets/photos/restaurant/chocolate-tart.jpg +0 -0
- package/dist/blueprints/assets/photos/restaurant/creme-brulee.jpg +0 -0
- package/dist/blueprints/assets/photos/restaurant/hero.jpg +0 -0
- package/dist/blueprints/assets/photos/restaurant/house-red.jpg +0 -0
- package/dist/blueprints/assets/photos/restaurant/house-white.jpg +0 -0
- package/dist/blueprints/assets/photos/restaurant/pan-seared-trout.jpg +0 -0
- package/dist/blueprints/assets/photos/restaurant/poached-pear.jpg +0 -0
- package/dist/blueprints/assets/photos/restaurant/roasted-beet-salad.jpg +0 -0
- package/dist/blueprints/assets/photos/restaurant/slow-roast-duck-leg.jpg +0 -0
- package/dist/blueprints/assets/photos/restaurant/soup-of-the-day.jpg +0 -0
- package/dist/blueprints/assets/photos/restaurant/sparkling-water.jpg +0 -0
- package/dist/blueprints/assets/photos/restaurant/wild-mushroom-risotto.jpg +0 -0
- package/dist/blueprints/assets/photos/saas/avatar-1.jpg +0 -0
- package/dist/blueprints/assets/photos/saas/hero.jpg +0 -0
- package/dist/blueprints/assets/photos/store/camp-blanket.jpg +0 -0
- package/dist/blueprints/assets/photos/store/canvas-tote.jpg +0 -0
- package/dist/blueprints/assets/photos/store/cast-iron-skillet.jpg +0 -0
- package/dist/blueprints/assets/photos/store/ceramic-pour-over-set.jpg +0 -0
- package/dist/blueprints/assets/photos/store/enamel-mug.jpg +0 -0
- package/dist/blueprints/assets/photos/store/everyday-tee.jpg +0 -0
- package/dist/blueprints/assets/photos/store/field-jacket.jpg +0 -0
- package/dist/blueprints/assets/photos/store/hero.jpg +0 -0
- package/dist/blueprints/assets/photos/store/leather-card-holder.jpg +0 -0
- package/dist/blueprints/assets/photos/store/linen-table-runner.jpg +0 -0
- package/dist/blueprints/assets/photos/store/trail-tote.jpg +0 -0
- package/dist/blueprints/assets/photos/store/wool-beanie.jpg +0 -0
- package/dist/blueprints/assets/photos/store/wool-overshirt.jpg +0 -0
- package/dist/blueprints/assets/photos/vitrine/avatar-1.jpg +0 -0
- package/dist/blueprints/assets/photos/vitrine/avatar-2.jpg +0 -0
- package/dist/blueprints/assets/photos/vitrine/avatar-3.jpg +0 -0
- package/dist/blueprints/assets/photos/vitrine/dashboard.jpg +0 -0
- package/dist/blueprints/assets/photos/vitrine/hero.jpg +0 -0
- package/dist/blueprints/association.d.ts +0 -151
- package/dist/blueprints/association.d.ts.map +0 -1
- package/dist/blueprints/association.js +0 -732
- package/dist/blueprints/association.js.map +0 -1
- package/dist/blueprints/blog.d.ts +0 -198
- package/dist/blueprints/blog.d.ts.map +0 -1
- package/dist/blueprints/blog.js +0 -665
- package/dist/blueprints/blog.js.map +0 -1
- package/dist/blueprints/content-pack.d.ts +0 -143
- package/dist/blueprints/content-pack.d.ts.map +0 -1
- package/dist/blueprints/content-pack.js +0 -111
- package/dist/blueprints/content-pack.js.map +0 -1
- package/dist/blueprints/content-packs.d.ts +0 -11
- package/dist/blueprints/content-packs.d.ts.map +0 -1
- package/dist/blueprints/content-packs.js +0 -29
- package/dist/blueprints/content-packs.js.map +0 -1
- package/dist/blueprints/demo-media.d.ts +0 -39
- package/dist/blueprints/demo-media.d.ts.map +0 -1
- package/dist/blueprints/demo-media.js +0 -30
- package/dist/blueprints/demo-media.js.map +0 -1
- package/dist/blueprints/documentation.d.ts +0 -134
- package/dist/blueprints/documentation.d.ts.map +0 -1
- package/dist/blueprints/documentation.js +0 -678
- package/dist/blueprints/documentation.js.map +0 -1
- package/dist/blueprints/magazine.d.ts +0 -145
- package/dist/blueprints/magazine.d.ts.map +0 -1
- package/dist/blueprints/magazine.js +0 -543
- package/dist/blueprints/magazine.js.map +0 -1
- package/dist/blueprints/menus.d.ts +0 -25
- package/dist/blueprints/menus.d.ts.map +0 -1
- package/dist/blueprints/menus.js +0 -33
- package/dist/blueprints/menus.js.map +0 -1
- package/dist/blueprints/photo-assets.d.ts +0 -3
- package/dist/blueprints/photo-assets.d.ts.map +0 -1
- package/dist/blueprints/photo-assets.js +0 -33
- package/dist/blueprints/photo-assets.js.map +0 -1
- package/dist/blueprints/portfolio.d.ts +0 -141
- package/dist/blueprints/portfolio.d.ts.map +0 -1
- package/dist/blueprints/portfolio.js +0 -700
- package/dist/blueprints/portfolio.js.map +0 -1
- package/dist/blueprints/restaurant.d.ts +0 -124
- package/dist/blueprints/restaurant.d.ts.map +0 -1
- package/dist/blueprints/restaurant.js +0 -457
- package/dist/blueprints/restaurant.js.map +0 -1
- package/dist/blueprints/saas.d.ts +0 -133
- package/dist/blueprints/saas.d.ts.map +0 -1
- package/dist/blueprints/saas.js +0 -551
- package/dist/blueprints/saas.js.map +0 -1
- package/dist/blueprints/site-settings-seed.d.ts +0 -17
- package/dist/blueprints/site-settings-seed.d.ts.map +0 -1
- package/dist/blueprints/site-settings-seed.js +0 -45
- package/dist/blueprints/site-settings-seed.js.map +0 -1
- package/dist/blueprints/starting-skins.d.ts +0 -19
- package/dist/blueprints/starting-skins.d.ts.map +0 -1
- package/dist/blueprints/starting-skins.js +0 -301
- package/dist/blueprints/starting-skins.js.map +0 -1
- package/dist/blueprints/store.d.ts +0 -173
- package/dist/blueprints/store.d.ts.map +0 -1
- package/dist/blueprints/store.js +0 -643
- package/dist/blueprints/store.js.map +0 -1
- package/dist/blueprints/vitrine.d.ts +0 -178
- package/dist/blueprints/vitrine.d.ts.map +0 -1
- package/dist/blueprints/vitrine.js +0 -529
- package/dist/blueprints/vitrine.js.map +0 -1
- package/dist/demo-art/compositions.d.ts +0 -48
- package/dist/demo-art/compositions.d.ts.map +0 -1
- package/dist/demo-art/compositions.js +0 -690
- package/dist/demo-art/compositions.js.map +0 -1
- package/dist/demo-art/index.d.ts +0 -8
- package/dist/demo-art/index.d.ts.map +0 -1
- package/dist/demo-art/index.js +0 -5
- package/dist/demo-art/index.js.map +0 -1
- package/dist/demo-art/oklch.d.ts +0 -39
- package/dist/demo-art/oklch.d.ts.map +0 -1
- package/dist/demo-art/oklch.js +0 -79
- package/dist/demo-art/oklch.js.map +0 -1
- package/dist/demo-art/png.d.ts +0 -24
- package/dist/demo-art/png.d.ts.map +0 -1
- package/dist/demo-art/png.js +0 -110
- package/dist/demo-art/png.js.map +0 -1
- package/dist/demo-art/render.d.ts +0 -228
- package/dist/demo-art/render.d.ts.map +0 -1
- package/dist/demo-art/render.js +0 -478
- package/dist/demo-art/render.js.map +0 -1
|
@@ -1,732 +0,0 @@
|
|
|
1
|
-
import { CogentaError } from '@cogenta/core';
|
|
2
|
-
import { createContentStore, defineCollection, f, validateCollectionSet, } from '@cogenta/schema';
|
|
3
|
-
import { avatarArt, coverArt, heroArt, logoArt } from '../demo-art/compositions.js';
|
|
4
|
-
import { definePageCollection, richTextParagraph, SEO_FIELDS, toBlockZoneEntry, } from './content-pack.js';
|
|
5
|
-
import { STARTING_SKINS } from './starting-skins.js';
|
|
6
|
-
/**
|
|
7
|
-
* The `association` blueprint's content model (L25 pass, batch — warm,
|
|
8
|
-
* human template for a nonprofit or community group): an `event` collection
|
|
9
|
-
* (what a returning visitor comes back to check, dated and located) and a
|
|
10
|
-
* small set of pages built around the mission, the programmes, and a call
|
|
11
|
-
* to act (donate, volunteer, attend).
|
|
12
|
-
*
|
|
13
|
-
* `blocks` on `event` (a page-builder zone, `f.blocks()`) carries the
|
|
14
|
-
* per-event "When / Where" panel — a real `stats` block the theme renders
|
|
15
|
-
* exactly like any other one. This is a deliberate workaround for a real
|
|
16
|
-
* gap, not an oversight: a theme's `renderPage` receives `PageContent`
|
|
17
|
-
* (title, blocks, `PageEntryMeta`), never the entry's raw schema fields, so
|
|
18
|
-
* there is no contract-D-legal way for `@cogenta/theme-association` to read
|
|
19
|
-
* `date`/`location` on a *single* event's own page (unlike the home page's
|
|
20
|
-
* `collectionList`, whose `ContentEntry[]` *does* carry every raw field —
|
|
21
|
-
* see that block's own `date`/`location` reading). Baking a `stats` block
|
|
22
|
-
* with the same date/location the blueprint already computed keeps the
|
|
23
|
-
* panel real, dated correctly, and rendered by ordinary block code — no
|
|
24
|
-
* theme-kit/`cogenta serve` change, which is out of this task's scope.
|
|
25
|
-
* The same `blocks` zone also carries a second, longer `prose` paragraph
|
|
26
|
-
* (`AssociationDemoEvent.whatToExpect`, L26) — without it an event's own
|
|
27
|
-
* page was only its one-line `description`, a photo and the When/Where
|
|
28
|
-
* panel, which read as bare next to the rest of the site.
|
|
29
|
-
*/
|
|
30
|
-
export const event = defineCollection({
|
|
31
|
-
name: 'event',
|
|
32
|
-
labels: { singular: 'Event', plural: 'Events' },
|
|
33
|
-
routing: { pattern: '/events/:slug' },
|
|
34
|
-
fields: {
|
|
35
|
-
title: f.text({ required: true, max: 200 }),
|
|
36
|
-
slug: f.slug({ from: 'title', unique: true }),
|
|
37
|
-
date: f.datetime({ required: true }),
|
|
38
|
-
location: f.text({ max: 200 }),
|
|
39
|
-
description: f.text({ max: 500, multiline: true }),
|
|
40
|
-
coverImage: f.media({ accept: ['image'] }),
|
|
41
|
-
blocks: f.blocks(),
|
|
42
|
-
...SEO_FIELDS,
|
|
43
|
-
},
|
|
44
|
-
indexes: [['slug'], ['date']],
|
|
45
|
-
permissions: {
|
|
46
|
-
read: ['public'],
|
|
47
|
-
create: ['editor', 'admin'],
|
|
48
|
-
update: ['editor', 'admin'],
|
|
49
|
-
delete: ['admin'],
|
|
50
|
-
},
|
|
51
|
-
});
|
|
52
|
-
export const page = definePageCollection('/:slug');
|
|
53
|
-
export const ASSOCIATION_COLLECTIONS = [event, page];
|
|
54
|
-
validateCollectionSet(ASSOCIATION_COLLECTIONS);
|
|
55
|
-
/**
|
|
56
|
-
* Six real-sounding events, deliberately spread from one to six weeks out —
|
|
57
|
-
* `npm create cogenta` always produces a site whose "Upcoming events" list
|
|
58
|
-
* is never empty and never stale, whatever day it is scaffolded on.
|
|
59
|
-
*/
|
|
60
|
-
export const ASSOCIATION_DEMO_EVENTS = [
|
|
61
|
-
{
|
|
62
|
-
title: 'Volunteer orientation evening',
|
|
63
|
-
slug: 'volunteer-orientation-evening',
|
|
64
|
-
daysFromNow: 7,
|
|
65
|
-
hour: 17,
|
|
66
|
-
minute: 0,
|
|
67
|
-
location: 'Community Hall, Room 2',
|
|
68
|
-
description: 'A short, friendly session for anyone new to volunteering with us — what a Thursday shift actually involves, where the van keys live, and who to ask when something breaks. No commitment, just questions, and tea while you ask them.',
|
|
69
|
-
whatToExpect: 'Expect about forty-five minutes: a walk through the four programmes, who runs each one, and which evenings and afternoons have space right now. Bring nothing and commit to nothing — most people leave with one shift pencilled in for the following week, and a couple of names to ask for when they turn up.',
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
title: 'Community clean-up day',
|
|
73
|
-
slug: 'community-clean-up-day',
|
|
74
|
-
daysFromNow: 14,
|
|
75
|
-
hour: 10,
|
|
76
|
-
minute: 0,
|
|
77
|
-
location: 'Riverside Park, main entrance',
|
|
78
|
-
description: 'A morning of raking, planting spring bulbs and clearing last winter’s debris from the riverbank trail, working in pairs along the towpath as far as the old mill. Gloves, bags and tools are all provided — just bring boots you don’t mind getting muddy.',
|
|
79
|
-
whatToExpect: 'We split into pairs at the main entrance and work outward along the towpath, meeting back for sandwiches around midday. Council collects what we bag by the Monday after, so nothing sits by the river over a weekend. Wellingtons help more than the weather forecast usually suggests.',
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
title: 'Harvest food drive',
|
|
83
|
-
slug: 'harvest-food-drive',
|
|
84
|
-
daysFromNow: 21,
|
|
85
|
-
hour: 9,
|
|
86
|
-
minute: 0,
|
|
87
|
-
location: 'Community Hall car park',
|
|
88
|
-
description: 'Drop off tinned and dried goods at the collection point, or come for an hour to sort what arrives into family-sized crates ready for Thursday’s distribution. Last year this single morning restocked the pantry for six weeks — every tin really does make a difference.',
|
|
89
|
-
whatToExpect: 'A folding table goes up in the car park from nine, with a second team sorting inside the hall — tins by type, dried goods by weight, anything close to its date used first. No sign-up needed for either job; if the table looks busy, the sorting team inside can always use another pair of hands.',
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
title: 'Winter coat collection',
|
|
93
|
-
slug: 'winter-coat-collection',
|
|
94
|
-
daysFromNow: 28,
|
|
95
|
-
hour: 11,
|
|
96
|
-
minute: 0,
|
|
97
|
-
location: 'Main Street Fire Station',
|
|
98
|
-
description: 'Clean, wearable coats of any size — children’s especially short this year — go straight to families at the winter shelter before the cold sets in properly. The fire crew lets us use their car park and their kettle, so it doubles as a good chat with the neighbours.',
|
|
99
|
-
whatToExpect: 'Drop coats at the station forecourt any time between eleven and two — someone is always there to take them, no need to stay. Everything is checked for zips and buttons on the spot and sorted by size, so what leaves for the shelter that same afternoon is already ready to wear.',
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
title: 'Annual fundraising dinner',
|
|
103
|
-
slug: 'annual-fundraising-dinner',
|
|
104
|
-
daysFromNow: 35,
|
|
105
|
-
hour: 18,
|
|
106
|
-
minute: 30,
|
|
107
|
-
location: 'Grand Ballroom, Town Hall',
|
|
108
|
-
description: "This year's proceeds go directly to the winter shelter programme, matched pound for pound by two local businesses up to £5,000. Tickets include a three-course dinner, a raffle with prizes donated by shops on Main Street, and a short word from the families the shelter has housed this year.",
|
|
109
|
-
whatToExpect: 'Doors at six thirty for drinks, dinner at seven, and the raffle drawn between courses so nobody has to wait until the end. Smart casual, and the Town Hall car park is free after six for anyone driving in. Tickets are limited to two hundred, so this is the one date worth booking ahead for.',
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
title: 'Neighbourhood garden planting day',
|
|
113
|
-
slug: 'neighbourhood-garden-planting-day',
|
|
114
|
-
daysFromNow: 42,
|
|
115
|
-
hour: 9,
|
|
116
|
-
minute: 30,
|
|
117
|
-
location: 'Elm Street Community Garden',
|
|
118
|
-
description: 'Plant the spring beds with us — seedlings, soil and a flask of coffee all provided, no gardening experience needed. Whatever grows in the shared beds is free for anyone to pick once it comes in, which by June is usually more courgettes than the street knows what to do with.',
|
|
119
|
-
whatToExpect: 'Kneeling pads and tools are laid out by nine thirty, with one of the garden’s regular volunteers showing anyone new what goes where. Children are welcome alongside a parent — there is always a bed of easy, fast-growing things kept aside for smaller hands.',
|
|
120
|
-
},
|
|
121
|
-
];
|
|
122
|
-
/** ISO 8601, computed from "now" at scaffold time — never a fixed calendar date that ages into the past. */
|
|
123
|
-
function futureIso(daysFromNow, hour, minute) {
|
|
124
|
-
const date = new Date();
|
|
125
|
-
date.setUTCDate(date.getUTCDate() + daysFromNow);
|
|
126
|
-
date.setUTCHours(hour, minute, 0, 0);
|
|
127
|
-
return date.toISOString();
|
|
128
|
-
}
|
|
129
|
-
/** `Intl.DateTimeFormat`'s own long form, for the per-event "When" stats item baked into `event.blocks`. */
|
|
130
|
-
function formatWhen(iso) {
|
|
131
|
-
return new Intl.DateTimeFormat('en', {
|
|
132
|
-
weekday: 'short',
|
|
133
|
-
day: 'numeric',
|
|
134
|
-
month: 'short',
|
|
135
|
-
hour: 'numeric',
|
|
136
|
-
minute: '2-digit',
|
|
137
|
-
}).format(new Date(iso));
|
|
138
|
-
}
|
|
139
|
-
const BLOCK_VERSION = '1.0.0';
|
|
140
|
-
function proseParagraph(key, text) {
|
|
141
|
-
return {
|
|
142
|
-
_key: key,
|
|
143
|
-
_type: 'prose',
|
|
144
|
-
_version: BLOCK_VERSION,
|
|
145
|
-
body: richTextParagraph(`${key}-body`, text),
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* The "When / Where" panel every event's own page carries — see this
|
|
150
|
-
* module's own top comment for why a `stats` block, baked at seed time from
|
|
151
|
-
* the same date/location this function's caller already computed, is the
|
|
152
|
-
* honest way to give a single event page a dated, located panel without a
|
|
153
|
-
* theme-kit contract change.
|
|
154
|
-
*/
|
|
155
|
-
function whenWhereBlock(iso, location) {
|
|
156
|
-
return {
|
|
157
|
-
_key: 'when-where',
|
|
158
|
-
_type: 'stats',
|
|
159
|
-
_version: BLOCK_VERSION,
|
|
160
|
-
items: [
|
|
161
|
-
{ _key: 'when', value: formatWhen(iso), label: 'When' },
|
|
162
|
-
{ _key: 'where', value: location, label: 'Where' },
|
|
163
|
-
],
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* `home` (hero + impact numbers + programmes + upcoming events + gallery +
|
|
168
|
-
* a volunteer's own words + partner logos + a donate band + FAQ — the
|
|
169
|
-
* eight-to-twelve-block, real-photo home page a template needs), `about`
|
|
170
|
-
* (the mission, told at length), `programmes` (what "What we do" on the
|
|
171
|
-
* home page actually funds, in full), `events` (every upcoming date, not
|
|
172
|
-
* only the home page's own six), `get-involved` (donate/volunteer/become a
|
|
173
|
-
* member, with a real pricing table) and `privacy` (a short, honest note —
|
|
174
|
-
* every footer needs one).
|
|
175
|
-
*
|
|
176
|
-
* A function of `media` (`SeedContext.media`), not a static const: several
|
|
177
|
-
* blocks need ids `seedDemoMedia` only knows at scaffold time.
|
|
178
|
-
*/
|
|
179
|
-
export function buildAssociationDemoPages(media) {
|
|
180
|
-
const mediaField = (name) => media[name] === undefined ? {} : { media: media[name] };
|
|
181
|
-
// `gallery.items` and `logoStrip.logos` are contract-B `min: 1` lists —
|
|
182
|
-
// emitting either block with an empty array (no media seeded, e.g. this
|
|
183
|
-
// function's own `{}` call in `blueprint-demo-blocks.test.ts`) would be
|
|
184
|
-
// contract-invalid content, not a degraded block. Omit the whole block
|
|
185
|
-
// instead, the same rule `gallery`/`logoStrip`/`mediaFigure` already
|
|
186
|
-
// follow on every other blueprint that seeds media conditionally.
|
|
187
|
-
const galleryItems = [1, 2, 3, 4, 5, 6]
|
|
188
|
-
.map((n) => ({ _key: `gallery-${n}`, media: media[`gallery-${n}`] }))
|
|
189
|
-
.filter((item) => item.media !== undefined);
|
|
190
|
-
const partnerLogos = [1, 2, 3, 4, 5]
|
|
191
|
-
.map((n) => ({ _key: `partner-${n}`, media: media[`partner-${n}`] }))
|
|
192
|
-
.filter((item) => item.media !== undefined);
|
|
193
|
-
return [
|
|
194
|
-
{
|
|
195
|
-
title: 'Home',
|
|
196
|
-
slug: 'home',
|
|
197
|
-
blocks: [
|
|
198
|
-
{
|
|
199
|
-
_key: 'demo-home-hero',
|
|
200
|
-
_type: 'hero',
|
|
201
|
-
_version: BLOCK_VERSION,
|
|
202
|
-
eyebrow: 'Riverside Community Fund',
|
|
203
|
-
title: 'Working together, close to home',
|
|
204
|
-
subtitle: 'Every gift and every hour goes straight back into this neighbourhood.',
|
|
205
|
-
...mediaField('hero'),
|
|
206
|
-
actions: [
|
|
207
|
-
{ label: 'Donate', target: { href: '/get-involved' }, emphasis: 'primary' },
|
|
208
|
-
{ label: 'Volunteer', target: { href: '/get-involved' } },
|
|
209
|
-
],
|
|
210
|
-
},
|
|
211
|
-
{
|
|
212
|
-
_key: 'demo-home-impact',
|
|
213
|
-
_type: 'stats',
|
|
214
|
-
_version: BLOCK_VERSION,
|
|
215
|
-
title: 'Our impact this year',
|
|
216
|
-
items: [
|
|
217
|
-
{ _key: 'i1', value: '12,400', label: 'meals served' },
|
|
218
|
-
{ _key: 'i2', value: '380', label: 'volunteers' },
|
|
219
|
-
{ _key: 'i3', value: '27', label: 'partner schools' },
|
|
220
|
-
{ _key: 'i4', value: '€1.2M', label: 'raised' },
|
|
221
|
-
],
|
|
222
|
-
},
|
|
223
|
-
{
|
|
224
|
-
_key: 'demo-home-work',
|
|
225
|
-
_type: 'featureGrid',
|
|
226
|
-
_version: BLOCK_VERSION,
|
|
227
|
-
title: 'What we do',
|
|
228
|
-
items: [
|
|
229
|
-
{
|
|
230
|
-
_key: 'demo-work-1',
|
|
231
|
-
icon: 'heart',
|
|
232
|
-
title: 'Weekly food distribution',
|
|
233
|
-
text: 'Thursday evenings, from the hall — no paperwork, no means test.',
|
|
234
|
-
link: { href: '/programmes' },
|
|
235
|
-
},
|
|
236
|
-
{
|
|
237
|
-
_key: 'demo-work-2',
|
|
238
|
-
icon: 'book',
|
|
239
|
-
title: 'Homework club',
|
|
240
|
-
text: 'Two afternoons a week for children in years 6 to 9, run entirely by volunteers.',
|
|
241
|
-
link: { href: '/programmes' },
|
|
242
|
-
},
|
|
243
|
-
{
|
|
244
|
-
_key: 'demo-work-3',
|
|
245
|
-
icon: 'leaf',
|
|
246
|
-
title: 'Community garden',
|
|
247
|
-
text: 'Raised beds anyone in the neighbourhood can plant, tend and harvest from.',
|
|
248
|
-
link: { href: '/programmes' },
|
|
249
|
-
},
|
|
250
|
-
],
|
|
251
|
-
},
|
|
252
|
-
{
|
|
253
|
-
_key: 'demo-home-events',
|
|
254
|
-
_type: 'collectionList',
|
|
255
|
-
_version: BLOCK_VERSION,
|
|
256
|
-
title: 'Upcoming events',
|
|
257
|
-
collection: 'event',
|
|
258
|
-
sort: { field: 'createdAt', direction: 'asc' },
|
|
259
|
-
limit: 6,
|
|
260
|
-
layout: 'grid',
|
|
261
|
-
},
|
|
262
|
-
...(galleryItems.length > 0
|
|
263
|
-
? [
|
|
264
|
-
{
|
|
265
|
-
_key: 'demo-home-gallery',
|
|
266
|
-
_type: 'gallery',
|
|
267
|
-
_version: BLOCK_VERSION,
|
|
268
|
-
layout: 'grid',
|
|
269
|
-
items: galleryItems,
|
|
270
|
-
},
|
|
271
|
-
]
|
|
272
|
-
: []),
|
|
273
|
-
{
|
|
274
|
-
_key: 'demo-home-testimonial',
|
|
275
|
-
_type: 'testimonial',
|
|
276
|
-
_version: BLOCK_VERSION,
|
|
277
|
-
quote: richTextParagraph('demo-testimonial-body', 'I came for one Saturday and stayed for three years. Nobody here ever made it feel like a chore.'),
|
|
278
|
-
attribution: {
|
|
279
|
-
name: 'M. Alaoui',
|
|
280
|
-
role: 'Volunteer since 2023',
|
|
281
|
-
...(media.avatar === undefined ? {} : { avatar: media.avatar }),
|
|
282
|
-
},
|
|
283
|
-
},
|
|
284
|
-
...(partnerLogos.length > 0
|
|
285
|
-
? [
|
|
286
|
-
{
|
|
287
|
-
_key: 'demo-home-partners',
|
|
288
|
-
_type: 'logoStrip',
|
|
289
|
-
_version: BLOCK_VERSION,
|
|
290
|
-
caption: 'Our partners',
|
|
291
|
-
logos: partnerLogos,
|
|
292
|
-
},
|
|
293
|
-
]
|
|
294
|
-
: []),
|
|
295
|
-
{
|
|
296
|
-
_key: 'demo-home-cta',
|
|
297
|
-
_type: 'cta',
|
|
298
|
-
_version: BLOCK_VERSION,
|
|
299
|
-
title: 'Every gift counts',
|
|
300
|
-
text: 'A one-off gift or a monthly one — both keep the hall open.',
|
|
301
|
-
actions: [
|
|
302
|
-
{ label: 'Donate now', target: { href: '/get-involved' }, emphasis: 'primary' },
|
|
303
|
-
{ label: 'See how to help', target: { href: '/get-involved' } },
|
|
304
|
-
],
|
|
305
|
-
},
|
|
306
|
-
{
|
|
307
|
-
_key: 'demo-home-faq',
|
|
308
|
-
_type: 'faq',
|
|
309
|
-
_version: BLOCK_VERSION,
|
|
310
|
-
title: 'How to help',
|
|
311
|
-
items: [
|
|
312
|
-
{
|
|
313
|
-
_key: 'faq-1',
|
|
314
|
-
question: 'Do I have to commit to a regular slot to volunteer?',
|
|
315
|
-
answer: richTextParagraph('faq-1-a', 'No. Some people come every week for years, some come twice a year. Both are useful.'),
|
|
316
|
-
},
|
|
317
|
-
{
|
|
318
|
-
_key: 'faq-2',
|
|
319
|
-
question: 'Where does a donation actually go?',
|
|
320
|
-
answer: richTextParagraph('faq-2-a', 'Rent on the hall, the van, and the food we buy to fill the gaps in what is donated — see our accounts on the Get Involved page.'),
|
|
321
|
-
},
|
|
322
|
-
{
|
|
323
|
-
_key: 'faq-3',
|
|
324
|
-
question: 'Can my company help without writing a cheque?',
|
|
325
|
-
answer: richTextParagraph('faq-3-a', 'Often more usefully, yes — storage space, a van on Thursdays, or an hour of an accountant every quarter are all things we have had to buy in the past.'),
|
|
326
|
-
},
|
|
327
|
-
{
|
|
328
|
-
_key: 'faq-4',
|
|
329
|
-
question: 'Is there a minimum age to volunteer?',
|
|
330
|
-
answer: richTextParagraph('faq-4-a', 'Sixteen for most shifts, with a parent or guardian for the garden and food-drive days at any age.'),
|
|
331
|
-
},
|
|
332
|
-
],
|
|
333
|
-
},
|
|
334
|
-
],
|
|
335
|
-
},
|
|
336
|
-
{
|
|
337
|
-
title: 'About',
|
|
338
|
-
slug: 'about',
|
|
339
|
-
blocks: [
|
|
340
|
-
proseParagraph('demo-about-1', 'Riverside Community Fund started in 1994 as three neighbours — a retired teacher, a bus driver and a nurse finishing night shifts — sharing a rented van and a spare room over the hardware shop on Elm Street. That winter they drove hot meals to eleven households who had nowhere else to turn. Thirty years later we still answer to the same neighbourhood, one street at a time, from the same stretch of road.'),
|
|
341
|
-
proseParagraph('demo-about-2', 'The hall came in 2001, bought outright with money raised over six years of jumble sales and sponsored walks, so that no landlord could ever end the food distribution with a rent notice. The homework club followed in 2009, started by a parent who noticed the hall sat empty on weekday afternoons while her own children had nowhere quiet to do their reading. The community garden — three raised beds when it began — now runs the length of the car park behind the hall.'),
|
|
342
|
-
// `mediaFigure.media` is contract-B `required: true` — omit the whole
|
|
343
|
-
// block rather than emit one with no image, the same rule
|
|
344
|
-
// `gallery`/`logoStrip` already follow above when media wasn't seeded
|
|
345
|
-
// (e.g. this function's own `{}` call in `blueprint-demo-blocks
|
|
346
|
-
// .test.ts`).
|
|
347
|
-
...(media['event-volunteer-orientation-evening'] === undefined
|
|
348
|
-
? []
|
|
349
|
-
: [
|
|
350
|
-
{
|
|
351
|
-
_key: 'demo-about-orientation',
|
|
352
|
-
_type: 'mediaFigure',
|
|
353
|
-
_version: BLOCK_VERSION,
|
|
354
|
-
...mediaField('event-volunteer-orientation-evening'),
|
|
355
|
-
caption: 'New volunteers meet around this table on their first evening — no forms, just introductions.',
|
|
356
|
-
},
|
|
357
|
-
]),
|
|
358
|
-
proseParagraph('demo-about-3', 'Today four programmes run entirely on volunteer hours and neighbour donations: weekly food distribution, the homework club, the community garden, and a neighbour-to-neighbour scheme for shopping and paperwork. None of them means-test anyone who turns up — the founders’ own rule, kept without exception since 1994, is that asking someone to prove their need is worse than the cost of occasionally helping someone who didn’t strictly need it.'),
|
|
359
|
-
{
|
|
360
|
-
_key: 'demo-about-since',
|
|
361
|
-
_type: 'statCounter',
|
|
362
|
-
_version: BLOCK_VERSION,
|
|
363
|
-
title: 'Since 1994',
|
|
364
|
-
stats: [
|
|
365
|
-
{ _key: 'c1', value: '32', label: 'years serving the community' },
|
|
366
|
-
{ _key: 'c2', value: '4', label: 'programmes running today' },
|
|
367
|
-
],
|
|
368
|
-
},
|
|
369
|
-
proseParagraph('demo-about-4', 'Everything on this page — the schema, the content, the skin — is a normal part of this site and is meant to be edited, renamed or deleted the moment the defaults stop fitting your own organisation’s history.'),
|
|
370
|
-
{
|
|
371
|
-
_key: 'demo-about-testimonial',
|
|
372
|
-
_type: 'quote',
|
|
373
|
-
_version: BLOCK_VERSION,
|
|
374
|
-
text: 'This hall has fed my family through two hard winters. Nobody ever asked us to prove anything.',
|
|
375
|
-
author: 'A neighbour',
|
|
376
|
-
role: 'Weekly visitor',
|
|
377
|
-
},
|
|
378
|
-
],
|
|
379
|
-
},
|
|
380
|
-
{
|
|
381
|
-
title: 'Programmes',
|
|
382
|
-
slug: 'programmes',
|
|
383
|
-
blocks: [
|
|
384
|
-
proseParagraph('demo-programmes-intro', 'Four programmes, all volunteer-run, all funded by the gifts and hours neighbours give directly — no council grant and no corporate sponsor pays for any of what follows. Each one started because someone here noticed a specific gap, not because a template said a community fund should run four things.'),
|
|
385
|
-
{
|
|
386
|
-
_key: 'demo-programmes-grid',
|
|
387
|
-
_type: 'featureGrid',
|
|
388
|
-
_version: BLOCK_VERSION,
|
|
389
|
-
items: [
|
|
390
|
-
{
|
|
391
|
-
_key: 'p1',
|
|
392
|
-
icon: 'heart',
|
|
393
|
-
title: 'Weekly food distribution',
|
|
394
|
-
text: 'Every Thursday from 6pm, from the hall — no referral, no paperwork, no means test, just turn up with a bag. We buy fresh bread and vegetables to fill whatever tinned donations don’t cover, so a family leaves with a proper week’s worth of meals, not just what happened to be given.',
|
|
395
|
-
},
|
|
396
|
-
{
|
|
397
|
-
_key: 'p2',
|
|
398
|
-
icon: 'book',
|
|
399
|
-
title: 'Homework club',
|
|
400
|
-
text: 'Tuesday and Thursday afternoons, 3:30 to 5:30, for children in years 6 to 9. Run entirely by volunteers — two retired teachers and a rotating group of university students home for the holidays — with quiet space, real supervision, and biscuits, for anyone whose house isn’t quiet enough to concentrate in.',
|
|
401
|
-
},
|
|
402
|
-
{
|
|
403
|
-
_key: 'p3',
|
|
404
|
-
icon: 'leaf',
|
|
405
|
-
title: 'Community garden',
|
|
406
|
-
text: 'Raised beds anyone in the neighbourhood can plant, tend and harvest from, no allotment waiting list required. What grows there in summer — usually more courgettes and runner beans than anyone expects — goes straight into Thursday’s food distribution alongside the tinned goods.',
|
|
407
|
-
},
|
|
408
|
-
{
|
|
409
|
-
_key: 'p4',
|
|
410
|
-
icon: 'users',
|
|
411
|
-
title: 'Neighbour to neighbour',
|
|
412
|
-
text: 'Shopping runs, help with council paperwork, and a bit of company for people who cannot easily get out — mostly older neighbours living alone. Volunteers are matched to the same person each fortnight wherever possible, so it becomes a friendship rather than a rota.',
|
|
413
|
-
},
|
|
414
|
-
],
|
|
415
|
-
},
|
|
416
|
-
// `mediaFigure.media` is contract-B `required: true` — omit the whole
|
|
417
|
-
// block rather than emit one with no image, the same rule
|
|
418
|
-
// `gallery`/`logoStrip` already follow on the home page above when
|
|
419
|
-
// media wasn't seeded (e.g. this function's own `{}` call in
|
|
420
|
-
// `blueprint-demo-blocks.test.ts`).
|
|
421
|
-
...(media['event-neighbourhood-garden-planting-day'] === undefined
|
|
422
|
-
? []
|
|
423
|
-
: [
|
|
424
|
-
{
|
|
425
|
-
_key: 'demo-programmes-garden',
|
|
426
|
-
_type: 'mediaFigure',
|
|
427
|
-
_version: BLOCK_VERSION,
|
|
428
|
-
...mediaField('event-neighbourhood-garden-planting-day'),
|
|
429
|
-
caption: 'The community garden on a planting weekend — three beds in 2009, twelve today.',
|
|
430
|
-
},
|
|
431
|
-
]),
|
|
432
|
-
proseParagraph('demo-programmes-outro', 'None of the four is means-tested and none asks a question it doesn’t need the answer to. If you’d like to fund an hour of any of them, or spend one yourself, the Get involved page has both a donation and a sign-up sheet.'),
|
|
433
|
-
],
|
|
434
|
-
},
|
|
435
|
-
{
|
|
436
|
-
title: 'Events',
|
|
437
|
-
slug: 'events',
|
|
438
|
-
blocks: [
|
|
439
|
-
proseParagraph('demo-events-intro', 'Every upcoming date, in one place — come to one, or come to all of them. Most take an hour or two, need no booking beyond turning up, and end with tea back at the hall for anyone who wants to stay and talk.'),
|
|
440
|
-
{
|
|
441
|
-
_key: 'demo-events-list',
|
|
442
|
-
_type: 'collectionList',
|
|
443
|
-
_version: BLOCK_VERSION,
|
|
444
|
-
collection: 'event',
|
|
445
|
-
sort: { field: 'createdAt', direction: 'asc' },
|
|
446
|
-
limit: 100,
|
|
447
|
-
layout: 'grid',
|
|
448
|
-
},
|
|
449
|
-
],
|
|
450
|
-
},
|
|
451
|
-
{
|
|
452
|
-
title: 'Get involved',
|
|
453
|
-
slug: 'get-involved',
|
|
454
|
-
blocks: [
|
|
455
|
-
{
|
|
456
|
-
_key: 'demo-involved-cta',
|
|
457
|
-
_type: 'cta',
|
|
458
|
-
_version: BLOCK_VERSION,
|
|
459
|
-
title: 'Every gift counts',
|
|
460
|
-
text: 'A one-off gift keeps the lights on for a week. A monthly one lets us plan — and every euro goes to a named programme, never to overheads we don’t have.',
|
|
461
|
-
actions: [
|
|
462
|
-
{
|
|
463
|
-
label: 'Donate now',
|
|
464
|
-
target: { href: 'https://example.org/donate' },
|
|
465
|
-
emphasis: 'primary',
|
|
466
|
-
},
|
|
467
|
-
// A real, working page rather than an in-page `#membership`
|
|
468
|
-
// fragment: no block in this theme's vocabulary ever renders an
|
|
469
|
-
// `id`, so a same-page anchor here was a dead link on every
|
|
470
|
-
// theme — found on this page's own audit. The volunteer
|
|
471
|
-
// orientation evening is the concrete next step for "I'd rather
|
|
472
|
-
// give time than money", and it is a real routed entry.
|
|
473
|
-
{
|
|
474
|
-
label: 'Volunteer instead',
|
|
475
|
-
target: { href: '/events/volunteer-orientation-evening' },
|
|
476
|
-
},
|
|
477
|
-
],
|
|
478
|
-
},
|
|
479
|
-
proseParagraph('demo-involved-volunteer', 'No experience needed for any shift — a returning volunteer is always paired with someone new, and every task is named before you arrive, not discovered on the day. Most people start at a monthly orientation evening (see the Events page for the next date), then pick one recurring slot — Thursday food distribution, homework club, or the garden — that fits around their own week.'),
|
|
480
|
-
{
|
|
481
|
-
_key: 'demo-involved-membership',
|
|
482
|
-
_type: 'pricingTable',
|
|
483
|
-
_version: BLOCK_VERSION,
|
|
484
|
-
title: 'Become a member',
|
|
485
|
-
tiers: [
|
|
486
|
-
{
|
|
487
|
-
_key: 'friend',
|
|
488
|
-
name: 'Friend',
|
|
489
|
-
price: '€5',
|
|
490
|
-
interval: '/month',
|
|
491
|
-
features: ['Our quarterly newsletter', 'An invitation to the annual dinner'],
|
|
492
|
-
action: { label: 'Join as a Friend', target: { href: 'https://example.org/join' } },
|
|
493
|
-
},
|
|
494
|
-
{
|
|
495
|
-
_key: 'sustainer',
|
|
496
|
-
name: 'Sustainer',
|
|
497
|
-
price: '€20',
|
|
498
|
-
interval: '/month',
|
|
499
|
-
features: [
|
|
500
|
-
'Everything in Friend',
|
|
501
|
-
'A named seat at the AGM',
|
|
502
|
-
'Priority booking for the summer camp',
|
|
503
|
-
],
|
|
504
|
-
action: {
|
|
505
|
-
label: 'Become a Sustainer',
|
|
506
|
-
target: { href: 'https://example.org/join' },
|
|
507
|
-
emphasis: 'primary',
|
|
508
|
-
},
|
|
509
|
-
highlighted: true,
|
|
510
|
-
},
|
|
511
|
-
],
|
|
512
|
-
},
|
|
513
|
-
// `mediaFigure.media` is contract-B `required: true` — omit the
|
|
514
|
-
// whole block rather than emit one with no image, the same rule
|
|
515
|
-
// `gallery`/`logoStrip` already follow on the home page above when
|
|
516
|
-
// media wasn't seeded (e.g. this function's own `{}` call in
|
|
517
|
-
// `blueprint-demo-blocks.test.ts`).
|
|
518
|
-
...(media['event-harvest-food-drive'] === undefined
|
|
519
|
-
? []
|
|
520
|
-
: [
|
|
521
|
-
{
|
|
522
|
-
_key: 'demo-involved-sorting',
|
|
523
|
-
_type: 'mediaFigure',
|
|
524
|
-
_version: BLOCK_VERSION,
|
|
525
|
-
...mediaField('event-harvest-food-drive'),
|
|
526
|
-
caption: 'Sorting a Saturday’s donations into family-sized crates before Thursday’s distribution.',
|
|
527
|
-
},
|
|
528
|
-
]),
|
|
529
|
-
{
|
|
530
|
-
_key: 'demo-involved-hours',
|
|
531
|
-
_type: 'accordion',
|
|
532
|
-
_version: BLOCK_VERSION,
|
|
533
|
-
title: 'Before you sign up',
|
|
534
|
-
items: [
|
|
535
|
-
{
|
|
536
|
-
_key: 'hours-1',
|
|
537
|
-
question: 'Do I have to commit to a regular slot?',
|
|
538
|
-
answer: richTextParagraph('hours-1-a', 'No — some people come every week for years, some come twice a year. Both are genuinely useful, and nobody keeps score.'),
|
|
539
|
-
},
|
|
540
|
-
{
|
|
541
|
-
_key: 'hours-2',
|
|
542
|
-
question: 'What should I bring?',
|
|
543
|
-
answer: richTextParagraph('hours-2-a', 'Closed shoes and clothes you do not mind getting dirty. Gloves and tools are provided for every outdoor shift, and the hall has a kettle for everyone else.'),
|
|
544
|
-
},
|
|
545
|
-
{
|
|
546
|
-
_key: 'hours-3',
|
|
547
|
-
question: 'Can under-16s help?',
|
|
548
|
-
answer: richTextParagraph('hours-3-a', 'Yes, alongside a parent or guardian, on the garden and food-drive days — those two are the ones we can supervise safely for younger volunteers. The homework club and food distribution are adult shifts.'),
|
|
549
|
-
},
|
|
550
|
-
{
|
|
551
|
-
_key: 'hours-4',
|
|
552
|
-
question: 'Is there parking?',
|
|
553
|
-
answer: richTextParagraph('hours-4-a', 'The hall’s own car park is small — cycling or walking is easier on a Thursday evening. For the clean-up and garden days, Riverside Park and Elm Street both have free parking within a few minutes’ walk.'),
|
|
554
|
-
},
|
|
555
|
-
],
|
|
556
|
-
},
|
|
557
|
-
],
|
|
558
|
-
},
|
|
559
|
-
{
|
|
560
|
-
title: 'Privacy',
|
|
561
|
-
slug: 'privacy',
|
|
562
|
-
blocks: [
|
|
563
|
-
proseParagraph('demo-privacy-1', 'We keep only what a donation or a volunteer sign-up needs: a name, a contact detail, and a record for our own accounts. We never sell or share it, and we delete it on request.'),
|
|
564
|
-
proseParagraph('demo-privacy-2', 'Donation records are kept for six years, the minimum our accountant asks for at tax time. Volunteer contact details are kept only while you are an active volunteer, and removed within a month of your last shift unless you ask us to keep them for a specific reason — an upcoming DBS check, for instance.'),
|
|
565
|
-
proseParagraph('demo-privacy-3', 'This page is a real, honest starting point — replace it with your own policy once you know exactly what your site collects.'),
|
|
566
|
-
],
|
|
567
|
-
},
|
|
568
|
-
];
|
|
569
|
-
}
|
|
570
|
-
/** Header/footer navigation and the header call-to-action button. */
|
|
571
|
-
export const ASSOCIATION_MENUS = {
|
|
572
|
-
header: [
|
|
573
|
-
{ label: 'About', url: '/about' },
|
|
574
|
-
{ label: 'Programmes', url: '/programmes' },
|
|
575
|
-
{ label: 'Events', url: '/events' },
|
|
576
|
-
{ label: 'Get involved', url: '/get-involved' },
|
|
577
|
-
],
|
|
578
|
-
footer: [
|
|
579
|
-
{ label: 'About', url: '/about' },
|
|
580
|
-
{ label: 'Events', url: '/events' },
|
|
581
|
-
{ label: 'Donate', url: '/get-involved' },
|
|
582
|
-
{ label: 'Privacy', url: '/privacy' },
|
|
583
|
-
],
|
|
584
|
-
headerAction: { label: 'Donate', url: '/get-involved' },
|
|
585
|
-
};
|
|
586
|
-
export const ASSOCIATION_SITE_SETTINGS = {
|
|
587
|
-
'general.tagline': 'Working together, close to home.',
|
|
588
|
-
'general.socialLinks': [
|
|
589
|
-
{ label: 'Facebook', url: 'https://facebook.com/example' },
|
|
590
|
-
{ label: 'Instagram', url: 'https://instagram.com/example' },
|
|
591
|
-
{ label: 'LinkedIn', url: 'https://linkedin.com/company/example' },
|
|
592
|
-
],
|
|
593
|
-
'general.footerNote': 'Riverside Community Fund is a registered charity, no. 1029384. 220 Elm Street.',
|
|
594
|
-
};
|
|
595
|
-
/**
|
|
596
|
-
* `association`'s own starting skin (`starting-skins.js`) — asserted
|
|
597
|
-
* present with a real check, not a `!`, since `STARTING_SKINS` is keyed by
|
|
598
|
-
* blueprint id and TypeScript cannot see that this particular key is always
|
|
599
|
-
* populated.
|
|
600
|
-
*/
|
|
601
|
-
function associationPalette() {
|
|
602
|
-
const skin = STARTING_SKINS.association;
|
|
603
|
-
if (skin === undefined) {
|
|
604
|
-
throw new CogentaError({
|
|
605
|
-
code: 'BLUEPRINT_REGISTRY_CORRUPT',
|
|
606
|
-
message: 'STARTING_SKINS.association is missing.',
|
|
607
|
-
hint: 'The "association" entry must stay declared in starting-skins.ts for this blueprint to render its demo art.',
|
|
608
|
-
});
|
|
609
|
-
}
|
|
610
|
-
return skin.color;
|
|
611
|
-
}
|
|
612
|
-
/**
|
|
613
|
-
* Procedural demo visuals (L25 D1): a warm hero backdrop, six event covers,
|
|
614
|
-
* six gallery photos, one volunteer avatar and five neutral partner marks —
|
|
615
|
-
* all from the same starting-skin palette this blueprint ships.
|
|
616
|
-
*
|
|
617
|
-
* `heroArt` has no literal "warm" variant (`demo-art/compositions.ts` names
|
|
618
|
-
* `mesh`/`geometric`/`diagonal`/`radial` only, and this task's scope forbids
|
|
619
|
-
* editing that module) — `mesh` is the closest of the four to a soft, warm
|
|
620
|
-
* wash, and is used here exactly as the brief's own "if available else
|
|
621
|
-
* mesh" fallback names.
|
|
622
|
-
*/
|
|
623
|
-
/** Bundled photography (`assets/photos/association/`), keyed by the same slug `ASSOCIATION_DEMO_EVENTS` uses. */
|
|
624
|
-
const ASSOCIATION_EVENT_PHOTOS = {
|
|
625
|
-
'volunteer-orientation-evening': 'association/volunteer-orientation.jpg',
|
|
626
|
-
'community-clean-up-day': 'association/community-cleanup.jpg',
|
|
627
|
-
'harvest-food-drive': 'association/harvest-food-drive.jpg',
|
|
628
|
-
'winter-coat-collection': 'association/winter-coat-collection.jpg',
|
|
629
|
-
'annual-fundraising-dinner': 'association/fundraising-dinner.jpg',
|
|
630
|
-
'neighbourhood-garden-planting-day': 'association/garden-planting.jpg',
|
|
631
|
-
};
|
|
632
|
-
export const ASSOCIATION_MEDIA_SPECS = [
|
|
633
|
-
{
|
|
634
|
-
name: 'hero',
|
|
635
|
-
spec: heroArt(associationPalette(), 'mesh', 21),
|
|
636
|
-
alt: 'Volunteers working together',
|
|
637
|
-
photo: 'association/hero.jpg',
|
|
638
|
-
},
|
|
639
|
-
...ASSOCIATION_DEMO_EVENTS.map((demo, index) => {
|
|
640
|
-
const photo = ASSOCIATION_EVENT_PHOTOS[demo.slug];
|
|
641
|
-
return {
|
|
642
|
-
name: `event-${demo.slug}`,
|
|
643
|
-
spec: coverArt(associationPalette(), index + 1),
|
|
644
|
-
alt: `Cover image for ${demo.title}`,
|
|
645
|
-
...(photo === undefined ? {} : { photo }),
|
|
646
|
-
};
|
|
647
|
-
}),
|
|
648
|
-
...[1, 2, 3, 4, 5, 6].map((n) => ({
|
|
649
|
-
name: `gallery-${n}`,
|
|
650
|
-
spec: coverArt(associationPalette(), n + 10),
|
|
651
|
-
alt: `Photo ${n} from a Riverside Community Fund event`,
|
|
652
|
-
})),
|
|
653
|
-
{
|
|
654
|
-
name: 'avatar',
|
|
655
|
-
spec: avatarArt(associationPalette(), 1),
|
|
656
|
-
// Not decorative (`ingestMediaUpload` requires either real alt text or
|
|
657
|
-
// an explicit decorative justification, and `DemoMediaSpec` carries no
|
|
658
|
-
// such flag) — a short, honest description of the abstract mark itself.
|
|
659
|
-
alt: 'Abstract portrait mark standing in for a volunteer’s photo',
|
|
660
|
-
},
|
|
661
|
-
...[1, 2, 3, 4, 5].map((n) => ({
|
|
662
|
-
name: `partner-${n}`,
|
|
663
|
-
spec: logoArt(n),
|
|
664
|
-
alt: `Partner organisation ${n}`,
|
|
665
|
-
})),
|
|
666
|
-
];
|
|
667
|
-
export const ASSOCIATION_RECOMMENDED_AGENTS = [
|
|
668
|
-
{
|
|
669
|
-
name: 'contentAgent',
|
|
670
|
-
package: '@cogenta/agents-builtin',
|
|
671
|
-
reason: 'Flags terminology drift across event descriptions written by different volunteers.',
|
|
672
|
-
},
|
|
673
|
-
{
|
|
674
|
-
name: 'seoAgent',
|
|
675
|
-
package: '@cogenta/agents-builtin',
|
|
676
|
-
reason: 'Audits the events and programmes pages so newcomers can find them from a search engine.',
|
|
677
|
-
},
|
|
678
|
-
];
|
|
679
|
-
/**
|
|
680
|
-
* Inserts the `association` blueprint's demo content through the real
|
|
681
|
-
* `ContentStore` — never mocked (house rule). Each event's `coverImage` and
|
|
682
|
-
* its own "When / Where" `blocks` panel, the home page's hero/gallery/
|
|
683
|
-
* testimonial/partner media, all come from `ctx.media`
|
|
684
|
-
* (`seedDemoMedia`/`ASSOCIATION_MEDIA_SPECS`) — absent (e.g. a blueprint
|
|
685
|
-
* seeded with `seedDemoContent: false`) simply leaves those fields unset,
|
|
686
|
-
* since none is `required`.
|
|
687
|
-
*/
|
|
688
|
-
async function seedAssociationDemoContent(ctx) {
|
|
689
|
-
const { db, defaultLocale, adminId, media } = ctx;
|
|
690
|
-
const eventStore = createContentStore({ db, collection: event, defaultLocale });
|
|
691
|
-
const pageStore = createContentStore({ db, collection: page, defaultLocale });
|
|
692
|
-
for (const demo of ASSOCIATION_DEMO_EVENTS) {
|
|
693
|
-
const iso = futureIso(demo.daysFromNow, demo.hour, demo.minute);
|
|
694
|
-
const cover = media[`event-${demo.slug}`];
|
|
695
|
-
await eventStore.create({
|
|
696
|
-
status: 'published',
|
|
697
|
-
createdBy: adminId,
|
|
698
|
-
values: {
|
|
699
|
-
title: demo.title,
|
|
700
|
-
slug: demo.slug,
|
|
701
|
-
date: iso,
|
|
702
|
-
location: demo.location,
|
|
703
|
-
description: demo.description,
|
|
704
|
-
...(cover === undefined ? {} : { coverImage: cover }),
|
|
705
|
-
},
|
|
706
|
-
blocks: {
|
|
707
|
-
blocks: [
|
|
708
|
-
whenWhereBlock(iso, demo.location),
|
|
709
|
-
proseParagraph(`${demo.slug}-expect`, demo.whatToExpect),
|
|
710
|
-
].map(toBlockZoneEntry),
|
|
711
|
-
},
|
|
712
|
-
});
|
|
713
|
-
}
|
|
714
|
-
for (const demo of buildAssociationDemoPages(media)) {
|
|
715
|
-
await pageStore.create({
|
|
716
|
-
status: 'published',
|
|
717
|
-
createdBy: adminId,
|
|
718
|
-
values: { title: demo.title, slug: demo.slug },
|
|
719
|
-
blocks: { blocks: demo.blocks.map(toBlockZoneEntry) },
|
|
720
|
-
});
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
|
-
export const associationContentPack = {
|
|
724
|
-
collections: ASSOCIATION_COLLECTIONS,
|
|
725
|
-
recommendedAgents: ASSOCIATION_RECOMMENDED_AGENTS,
|
|
726
|
-
seedDemoContent: seedAssociationDemoContent,
|
|
727
|
-
defaultTheme: '@cogenta/theme-association',
|
|
728
|
-
menus: ASSOCIATION_MENUS,
|
|
729
|
-
siteSettings: ASSOCIATION_SITE_SETTINGS,
|
|
730
|
-
mediaSpecs: ASSOCIATION_MEDIA_SPECS,
|
|
731
|
-
};
|
|
732
|
-
//# sourceMappingURL=association.js.map
|