create-cogenta 0.2.1 → 0.5.0
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.d.ts.map +1 -1
- package/dist/blueprint-defaults.js +6 -0
- package/dist/blueprint-defaults.js.map +1 -1
- 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 +93 -15
- package/dist/blueprints/association.d.ts.map +1 -1
- package/dist/blueprints/association.js +637 -130
- package/dist/blueprints/association.js.map +1 -1
- package/dist/blueprints/blog.d.ts +81 -94
- package/dist/blueprints/blog.d.ts.map +1 -1
- package/dist/blueprints/blog.js +513 -177
- package/dist/blueprints/blog.js.map +1 -1
- package/dist/blueprints/content-pack.d.ts +83 -2
- package/dist/blueprints/content-pack.d.ts.map +1 -1
- package/dist/blueprints/content-pack.js +54 -1
- package/dist/blueprints/content-pack.js.map +1 -1
- package/dist/blueprints/content-packs.d.ts +4 -3
- package/dist/blueprints/content-packs.d.ts.map +1 -1
- package/dist/blueprints/content-packs.js +6 -3
- package/dist/blueprints/content-packs.js.map +1 -1
- package/dist/blueprints/demo-media.d.ts +39 -0
- package/dist/blueprints/demo-media.d.ts.map +1 -0
- package/dist/blueprints/demo-media.js +30 -0
- package/dist/blueprints/demo-media.js.map +1 -0
- package/dist/blueprints/documentation.d.ts +78 -15
- package/dist/blueprints/documentation.d.ts.map +1 -1
- package/dist/blueprints/documentation.js +585 -104
- package/dist/blueprints/documentation.js.map +1 -1
- package/dist/blueprints/magazine.d.ts +81 -15
- package/dist/blueprints/magazine.d.ts.map +1 -1
- package/dist/blueprints/magazine.js +431 -85
- package/dist/blueprints/magazine.js.map +1 -1
- package/dist/blueprints/menus.d.ts +25 -0
- package/dist/blueprints/menus.d.ts.map +1 -0
- package/dist/blueprints/menus.js +33 -0
- package/dist/blueprints/menus.js.map +1 -0
- package/dist/blueprints/photo-assets.d.ts +3 -0
- package/dist/blueprints/photo-assets.d.ts.map +1 -0
- package/dist/blueprints/photo-assets.js +33 -0
- package/dist/blueprints/photo-assets.js.map +1 -0
- package/dist/blueprints/portfolio.d.ts +81 -13
- package/dist/blueprints/portfolio.d.ts.map +1 -1
- package/dist/blueprints/portfolio.js +605 -102
- package/dist/blueprints/portfolio.js.map +1 -1
- package/dist/blueprints/registry.d.ts +3 -1
- package/dist/blueprints/registry.d.ts.map +1 -1
- package/dist/blueprints/registry.js +4 -1
- package/dist/blueprints/registry.js.map +1 -1
- package/dist/blueprints/restaurant.d.ts +65 -20
- package/dist/blueprints/restaurant.d.ts.map +1 -1
- package/dist/blueprints/restaurant.js +350 -117
- package/dist/blueprints/restaurant.js.map +1 -1
- package/dist/blueprints/saas.d.ts +81 -14
- package/dist/blueprints/saas.d.ts.map +1 -1
- package/dist/blueprints/saas.js +469 -132
- package/dist/blueprints/saas.js.map +1 -1
- package/dist/blueprints/site-settings-seed.d.ts +17 -0
- package/dist/blueprints/site-settings-seed.d.ts.map +1 -0
- package/dist/blueprints/site-settings-seed.js +45 -0
- package/dist/blueprints/site-settings-seed.js.map +1 -0
- package/dist/blueprints/starting-skins.d.ts +19 -0
- package/dist/blueprints/starting-skins.d.ts.map +1 -0
- package/dist/blueprints/starting-skins.js +301 -0
- package/dist/blueprints/starting-skins.js.map +1 -0
- package/dist/blueprints/store.d.ts +173 -0
- package/dist/blueprints/store.d.ts.map +1 -0
- package/dist/blueprints/store.js +643 -0
- package/dist/blueprints/store.js.map +1 -0
- package/dist/blueprints/vitrine.d.ts +94 -16
- package/dist/blueprints/vitrine.d.ts.map +1 -1
- package/dist/blueprints/vitrine.js +421 -142
- package/dist/blueprints/vitrine.js.map +1 -1
- package/dist/demo-art/compositions.d.ts +48 -0
- package/dist/demo-art/compositions.d.ts.map +1 -0
- package/dist/demo-art/compositions.js +690 -0
- package/dist/demo-art/compositions.js.map +1 -0
- package/dist/demo-art/index.d.ts +8 -0
- package/dist/demo-art/index.d.ts.map +1 -0
- package/dist/demo-art/index.js +5 -0
- package/dist/demo-art/index.js.map +1 -0
- package/dist/demo-art/oklch.d.ts +39 -0
- package/dist/demo-art/oklch.d.ts.map +1 -0
- package/dist/demo-art/oklch.js +79 -0
- package/dist/demo-art/oklch.js.map +1 -0
- package/dist/demo-art/png.d.ts +24 -0
- package/dist/demo-art/png.d.ts.map +1 -0
- package/dist/demo-art/png.js +110 -0
- package/dist/demo-art/png.js.map +1 -0
- package/dist/demo-art/render.d.ts +228 -0
- package/dist/demo-art/render.d.ts.map +1 -0
- package/dist/demo-art/render.js +478 -0
- package/dist/demo-art/render.js.map +1 -0
- package/dist/llm-setup.d.ts +10 -1
- package/dist/llm-setup.d.ts.map +1 -1
- package/dist/llm-setup.js +12 -2
- package/dist/llm-setup.js.map +1 -1
- package/dist/playground-reset.d.ts.map +1 -1
- package/dist/playground-reset.js +22 -4
- package/dist/playground-reset.js.map +1 -1
- package/dist/prompts.d.ts +12 -0
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +32 -0
- package/dist/prompts.js.map +1 -1
- package/dist/recap.d.ts.map +1 -1
- package/dist/recap.js +6 -0
- package/dist/recap.js.map +1 -1
- package/dist/scaffold.d.ts +22 -2
- package/dist/scaffold.d.ts.map +1 -1
- package/dist/scaffold.js +185 -23
- package/dist/scaffold.js.map +1 -1
- package/dist/wizard.d.ts.map +1 -1
- package/dist/wizard.js +4 -1
- package/dist/wizard.js.map +1 -1
- package/package.json +14 -11
|
@@ -1,23 +1,41 @@
|
|
|
1
|
+
import { CogentaError } from '@cogenta/core';
|
|
1
2
|
import { createContentStore, defineCollection, f, validateCollectionSet, } from '@cogenta/schema';
|
|
2
|
-
import {
|
|
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';
|
|
3
6
|
/**
|
|
4
|
-
* The `vitrine` blueprint's content model (L9 task 8, batch A
|
|
5
|
-
* one-pager showcase site for a small
|
|
6
|
-
* services and a few testimonials,
|
|
7
|
-
* than data baked into the page
|
|
7
|
+
* The `vitrine` blueprint's content model (L9 task 8, batch A; raised to a
|
|
8
|
+
* pro template by L25): the classic one-pager showcase site for a small
|
|
9
|
+
* business or consultancy — a list of services and a few testimonials,
|
|
10
|
+
* both real, editable collections rather than data baked into the page
|
|
11
|
+
* itself.
|
|
12
|
+
*
|
|
13
|
+
* `icon` (a symbol name `@cogenta/theme-kit`'s `renderIcon` recognises) and
|
|
14
|
+
* `coverImage` (contract D `theme@1.4`'s `entryImage`) are what let
|
|
15
|
+
* `theme-entreprise`'s `featureGrid` and `collectionList` show a service
|
|
16
|
+
* the same way `theme-saas`'s own `feature` collection already does.
|
|
8
17
|
*/
|
|
9
18
|
export const service = defineCollection({
|
|
10
19
|
name: 'service',
|
|
11
20
|
labels: { singular: 'Service', plural: 'Services' },
|
|
12
21
|
// Routed, not just listed: `collectionList` (used on the home page below)
|
|
13
22
|
// always builds a link for every entry it renders (`entryHref`,
|
|
14
|
-
// `@cogenta/theme-
|
|
15
|
-
//
|
|
23
|
+
// `@cogenta/theme-kit`), so a collection it targets must have a route or
|
|
24
|
+
// that render call throws.
|
|
16
25
|
routing: { pattern: '/services/:slug' },
|
|
17
26
|
fields: {
|
|
18
27
|
name: f.text({ required: true, max: 120 }),
|
|
19
28
|
slug: f.slug({ from: 'name', unique: true }),
|
|
20
29
|
description: f.text({ max: 400, multiline: true }),
|
|
30
|
+
icon: f.text({
|
|
31
|
+
max: 64,
|
|
32
|
+
admin: {
|
|
33
|
+
label: 'Icon',
|
|
34
|
+
help: 'One of the symbol names @cogenta/theme-kit recognises (e.g. "chart", "shield", "briefcase", "code", "trending-up", "tag"). Left blank, the service renders with no icon chip.',
|
|
35
|
+
},
|
|
36
|
+
}),
|
|
37
|
+
coverImage: f.media({ accept: ['image'] }),
|
|
38
|
+
...SEO_FIELDS,
|
|
21
39
|
},
|
|
22
40
|
indexes: [['slug']],
|
|
23
41
|
permissions: {
|
|
@@ -34,6 +52,7 @@ export const testimonial = defineCollection({
|
|
|
34
52
|
authorName: f.text({ required: true, max: 120 }),
|
|
35
53
|
authorRole: f.text({ max: 120 }),
|
|
36
54
|
quote: f.text({ required: true, max: 500, multiline: true }),
|
|
55
|
+
avatar: f.media({ accept: ['image'] }),
|
|
37
56
|
},
|
|
38
57
|
permissions: {
|
|
39
58
|
read: ['public'],
|
|
@@ -45,160 +64,317 @@ export const testimonial = defineCollection({
|
|
|
45
64
|
export const page = definePageCollection('/:slug');
|
|
46
65
|
export const VITRINE_COLLECTIONS = [service, testimonial, page];
|
|
47
66
|
validateCollectionSet(VITRINE_COLLECTIONS);
|
|
67
|
+
/**
|
|
68
|
+
* Six real B2B capabilities, each with the icon `featureGrid` (home page)
|
|
69
|
+
* and this same entry's own `icon` field both point at — a `collectionList`
|
|
70
|
+
* of `service` and the home page's `featureGrid` read as one system rather
|
|
71
|
+
* than two unrelated sections.
|
|
72
|
+
*/
|
|
48
73
|
export const VITRINE_DEMO_SERVICES = [
|
|
49
74
|
{
|
|
50
75
|
name: 'Brand strategy',
|
|
51
76
|
slug: 'brand-strategy',
|
|
52
|
-
description: '
|
|
77
|
+
description: 'We start every engagement here, because a redesign built on the wrong positioning just ships the confusion faster. Three weeks of interviews with your best customers and closest competitors end in a positioning document, a messaging framework, and a visual identity your team can defend in a board meeting without us in the room.',
|
|
78
|
+
icon: 'tag',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: 'Web design & build',
|
|
82
|
+
slug: 'web-design-build',
|
|
83
|
+
description: 'Most of the sites we replace took longer to explain than to load. We design and build on Cogenta itself, so your team edits copy and swaps testimonials without filing a ticket — and the finished site still says what you do in the first five seconds, on every screen size.',
|
|
84
|
+
icon: 'code',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: 'Growth marketing',
|
|
88
|
+
slug: 'growth-marketing',
|
|
89
|
+
description: 'We run paid, lifecycle and content programmes against one dashboard tied to closed revenue, not clicks. A channel that stops paying for itself gets cut inside a reporting cycle, not a fiscal quarter — most engagements end with a smaller media budget and a larger pipeline than they started with.',
|
|
90
|
+
icon: 'trending-up',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: 'Operations consulting',
|
|
94
|
+
slug: 'operations-consulting',
|
|
95
|
+
description: 'Most operations problems are three broken handoffs, not thirty. We map how work actually moves through your organisation, not how the org chart says it should, and fix the handful of handoffs that are really costing you cycle time — against a metric your leadership already tracks.',
|
|
96
|
+
icon: 'briefcase',
|
|
53
97
|
},
|
|
54
98
|
{
|
|
55
|
-
name: '
|
|
56
|
-
slug: '
|
|
57
|
-
description: '
|
|
99
|
+
name: 'Financial advisory',
|
|
100
|
+
slug: 'financial-advisory',
|
|
101
|
+
description: 'We build the model your finance team will still be using eighteen months from now, not a one-off deck. Every forecast ties back to the same general-ledger export your controller already trusts, so the numbers survive contact with a real board, and a real audit.',
|
|
102
|
+
icon: 'chart',
|
|
58
103
|
},
|
|
59
104
|
{
|
|
60
|
-
name: '
|
|
61
|
-
slug: '
|
|
62
|
-
description: '
|
|
105
|
+
name: 'Security & compliance',
|
|
106
|
+
slug: 'security-compliance',
|
|
107
|
+
description: 'We inherited more than one compliance programme that was a binder nobody had opened since the last audit. Ours ships with a named owner and a real audit trail for every control, mapped to SOC 2 or ISO 27001 depending on what your customers actually ask for.',
|
|
108
|
+
icon: 'shield',
|
|
63
109
|
},
|
|
64
110
|
];
|
|
65
111
|
export const VITRINE_DEMO_TESTIMONIALS = [
|
|
66
112
|
{
|
|
67
113
|
authorName: 'Amina Diallo',
|
|
68
114
|
authorRole: 'Founder, Atelier Diallo',
|
|
69
|
-
quote: '
|
|
115
|
+
quote: 'Northfield rebuilt our positioning before they touched a single page of the site, and it showed — the new site paid for itself in the first month, because for the first time people understood what we do before they ever called. We still edit it ourselves, weekly, without asking anyone for help.',
|
|
70
116
|
},
|
|
71
117
|
{
|
|
72
118
|
authorName: 'Marco Bellini',
|
|
73
119
|
authorRole: 'Owner, Bellini Consulting',
|
|
74
|
-
quote: 'Fast, clear, no surprises
|
|
120
|
+
quote: 'Fast, clear, no surprises, and a fixed quote that held from the first call to the last invoice — exactly what a small business needs from a consulting engagement and almost never gets. Northfield delivered the brand and the site in five weeks and has been one email away ever since.',
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
authorName: 'Priya Chandra',
|
|
124
|
+
authorRole: 'COO, Chandra & Partners',
|
|
125
|
+
quote: "Northfield's operations review took three weeks and changed how four teams hand off work to each other. We are still finding the recommendations landing a full quarter later, in meetings Northfield was never in the room for — that is the real test of whether a consultant fixed something.",
|
|
75
126
|
},
|
|
76
127
|
];
|
|
77
128
|
const BLOCK_VERSION = '1.0.0';
|
|
129
|
+
function proseParagraph(key, text) {
|
|
130
|
+
return {
|
|
131
|
+
_key: key,
|
|
132
|
+
_type: 'prose',
|
|
133
|
+
_version: BLOCK_VERSION,
|
|
134
|
+
body: richTextParagraph(`${key}-body`, text),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/** A multi-paragraph `prose` block — same shape convention as `restaurant.ts`'s own `proseBlock`, for the About page's real founding story rather than one thin paragraph. */
|
|
138
|
+
function proseBlock(key, paragraphs) {
|
|
139
|
+
return {
|
|
140
|
+
_key: key,
|
|
141
|
+
_type: 'prose',
|
|
142
|
+
_version: BLOCK_VERSION,
|
|
143
|
+
body: paragraphs.map((text, index) => ({
|
|
144
|
+
_key: `${key}-p${index}`,
|
|
145
|
+
_type: 'block',
|
|
146
|
+
style: 'normal',
|
|
147
|
+
children: [{ _key: `${key}-p${index}-s`, _type: 'span', text, marks: [] }],
|
|
148
|
+
markDefs: [],
|
|
149
|
+
})),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
78
152
|
/**
|
|
79
|
-
* `home` (
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
153
|
+
* `home` (eleven blocks, the "confident B2B one-pager" composition the L25
|
|
154
|
+
* brief asks for: hero → trust strip → services → numbers → a wide product
|
|
155
|
+
* shot → the full services grid with covers → client outcome → a second
|
|
156
|
+
* voice → questions → call to action → a short about teaser), `about` (the
|
|
157
|
+
* full story plus every real testimonial, mirrored as `quote` blocks so an
|
|
158
|
+
* edit to the collection is visible without touching a page), and
|
|
159
|
+
* `contact` (how to reach the business).
|
|
160
|
+
*
|
|
161
|
+
* A function of `media` (`SeedContext.media`) and the real ids
|
|
162
|
+
* `seedVitrineDemoContent` assigns its own services (`serviceIdBySlug`),
|
|
163
|
+
* not a static const: the hero's `media`, the trust strip's logos, the
|
|
164
|
+
* services grid's covers and the featureGrid's links all need ids only the
|
|
165
|
+
* scaffold knows at seed time. Both parameters default to empty so
|
|
166
|
+
* `buildVitrineDemoPages({})` (the blueprint test's own call, and every
|
|
167
|
+
* other blueprint's equivalent) still renders a complete, valid page —
|
|
168
|
+
* `logoStrip`/`mediaFigure`/the hero's own media are simply omitted rather
|
|
169
|
+
* than emitted with an empty required list.
|
|
87
170
|
*/
|
|
88
|
-
export
|
|
89
|
-
{
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
171
|
+
export function buildVitrineDemoPages(media = {}, serviceIdBySlug = new Map()) {
|
|
172
|
+
const serviceLink = (slug) => {
|
|
173
|
+
const id = serviceIdBySlug.get(slug);
|
|
174
|
+
return id === undefined ? undefined : { collection: 'service', id };
|
|
175
|
+
};
|
|
176
|
+
// `logoStrip` (blocks@2.0) requires at least one logo — a media map with
|
|
177
|
+
// no `logo-*` entries (a scaffold with no demo-art seeded, or this
|
|
178
|
+
// function called directly, as the blueprint test does) must therefore
|
|
179
|
+
// omit the whole block rather than emit an empty, contract-invalid one.
|
|
180
|
+
const logoItems = [0, 1, 2, 3, 4]
|
|
181
|
+
.map((index) => media[`logo-${index}`])
|
|
182
|
+
.filter((id) => id !== undefined)
|
|
183
|
+
.map((id, index) => ({ _key: `demo-logo-${index}`, media: id }));
|
|
184
|
+
const [testimonial1, testimonial2, testimonial3] = VITRINE_DEMO_TESTIMONIALS;
|
|
185
|
+
return [
|
|
186
|
+
{
|
|
187
|
+
title: 'Home',
|
|
188
|
+
slug: 'home',
|
|
189
|
+
blocks: [
|
|
190
|
+
{
|
|
191
|
+
_key: 'demo-home-hero',
|
|
192
|
+
_type: 'hero',
|
|
193
|
+
_version: BLOCK_VERSION,
|
|
194
|
+
eyebrow: 'Northfield Consulting · Est. 2011',
|
|
195
|
+
title: 'The consultancy growing companies call before their systems fall over',
|
|
196
|
+
subtitle: 'We handle the six functions that break first when headcount outpaces process — brand, web, growth, operations, finance and security — each led by a partner who has run it, not just advised on it.',
|
|
197
|
+
...(media.hero === undefined ? {} : { media: media.hero }),
|
|
198
|
+
actions: [
|
|
199
|
+
{ label: 'See our services', target: { href: '#services' }, emphasis: 'primary' },
|
|
200
|
+
{ label: 'Get a quote', target: { href: '/contact' } },
|
|
201
|
+
],
|
|
202
|
+
},
|
|
203
|
+
...(logoItems.length === 0
|
|
204
|
+
? []
|
|
205
|
+
: [
|
|
206
|
+
{
|
|
207
|
+
_key: 'demo-home-logos',
|
|
208
|
+
_type: 'logoStrip',
|
|
209
|
+
_version: BLOCK_VERSION,
|
|
210
|
+
logos: logoItems,
|
|
211
|
+
caption: 'Trusted by teams at',
|
|
212
|
+
},
|
|
213
|
+
]),
|
|
214
|
+
{
|
|
215
|
+
_key: 'demo-home-services',
|
|
216
|
+
_type: 'featureGrid',
|
|
217
|
+
_version: BLOCK_VERSION,
|
|
218
|
+
title: 'What we do',
|
|
219
|
+
items: VITRINE_DEMO_SERVICES.map((demo, index) => {
|
|
220
|
+
const link = serviceLink(demo.slug);
|
|
221
|
+
return {
|
|
222
|
+
_key: `demo-service-${index}`,
|
|
223
|
+
icon: demo.icon,
|
|
224
|
+
title: demo.name,
|
|
225
|
+
text: demo.description,
|
|
226
|
+
...(link === undefined ? {} : { link }),
|
|
227
|
+
};
|
|
228
|
+
}),
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
_key: 'demo-home-numbers',
|
|
232
|
+
_type: 'stats',
|
|
233
|
+
_version: BLOCK_VERSION,
|
|
234
|
+
items: [
|
|
235
|
+
{ _key: 'demo-home-stat-1', value: '3', unit: 'weeks', label: 'typical project' },
|
|
236
|
+
{ _key: 'demo-home-stat-2', value: '120', unit: '+', label: 'engagements delivered' },
|
|
237
|
+
{ _key: 'demo-home-stat-3', value: '100', unit: '%', label: 'content you can edit' },
|
|
238
|
+
{ _key: 'demo-home-stat-4', value: '0', label: 'lines of JavaScript shipped' },
|
|
239
|
+
],
|
|
240
|
+
},
|
|
241
|
+
// `mediaFigure.media` (blocks@2.0) is required — with no `shot`
|
|
242
|
+
// media seeded, the block is omitted rather than emitted invalid
|
|
243
|
+
// (same reasoning as `logoStrip` above).
|
|
244
|
+
...(media.shot === undefined
|
|
245
|
+
? []
|
|
246
|
+
: [
|
|
247
|
+
{
|
|
248
|
+
_key: 'demo-home-shot',
|
|
249
|
+
_type: 'mediaFigure',
|
|
250
|
+
_version: BLOCK_VERSION,
|
|
251
|
+
media: media.shot,
|
|
252
|
+
caption: 'The engagement dashboard every Northfield team works from — the same tracker the client sees.',
|
|
253
|
+
ratio: '16:9',
|
|
254
|
+
align: 'wide',
|
|
255
|
+
},
|
|
256
|
+
]),
|
|
257
|
+
{
|
|
258
|
+
_key: 'demo-home-services-grid',
|
|
259
|
+
_type: 'collectionList',
|
|
260
|
+
_version: BLOCK_VERSION,
|
|
261
|
+
title: 'Every service, in detail',
|
|
262
|
+
collection: 'service',
|
|
263
|
+
sort: { field: 'createdAt', direction: 'asc' },
|
|
264
|
+
limit: 10,
|
|
265
|
+
layout: 'grid',
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
_key: 'demo-home-testimonial',
|
|
269
|
+
_type: 'testimonial',
|
|
270
|
+
_version: BLOCK_VERSION,
|
|
271
|
+
quote: richTextParagraph('demo-home-testimonial-quote', testimonial1.quote),
|
|
272
|
+
attribution: {
|
|
273
|
+
name: testimonial1.authorName,
|
|
274
|
+
role: testimonial1.authorRole,
|
|
275
|
+
...(media['avatar-0'] === undefined ? {} : { avatar: media['avatar-0'] }),
|
|
137
276
|
},
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
_key: 'demo-home-quote',
|
|
280
|
+
_type: 'quote',
|
|
281
|
+
_version: BLOCK_VERSION,
|
|
282
|
+
text: testimonial2.quote,
|
|
283
|
+
author: testimonial2.authorName,
|
|
284
|
+
role: testimonial2.authorRole,
|
|
285
|
+
},
|
|
286
|
+
homeFaq(),
|
|
287
|
+
{
|
|
288
|
+
_key: 'demo-home-cta',
|
|
289
|
+
_type: 'cta',
|
|
290
|
+
_version: BLOCK_VERSION,
|
|
291
|
+
title: 'Ready to get started?',
|
|
292
|
+
text: 'Book a thirty-minute call and leave with a scoped, fixed-price plan — not a follow-up email promising one.',
|
|
293
|
+
actions: [{ label: 'Get a quote', target: { href: '/contact' }, emphasis: 'primary' }],
|
|
294
|
+
},
|
|
295
|
+
proseParagraph('demo-home-about-teaser', `${testimonial3.authorName}'s operations review is one of well over a hundred engagements like it since Northfield opened in 2011. Read the founding story, and the rest of our client list, on the About page.`),
|
|
296
|
+
],
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
title: 'About',
|
|
300
|
+
slug: 'about',
|
|
301
|
+
blocks: [
|
|
302
|
+
proseBlock('demo-about-prose', [
|
|
303
|
+
'Northfield Consulting opened in 2011 with a simple complaint: growing companies were buying six different kinds of help from six different vendors, none of whom talked to each other, and paying for the seams as much as the work.',
|
|
304
|
+
'We built one practice instead — brand, web, growth, operations, finance and security — staffed by partners who have actually run each function inside a company, not just advised one from the outside. A single point of contact means the web team knows what the brand team decided, and the finance model reflects what operations actually changed.',
|
|
305
|
+
'Fifteen years and well over a hundred engagements later, the test we hold ourselves to has not changed: does the client still need us in the room a quarter after we leave? Most of the answers on this page came from clients who told us no, and meant it as a compliment.',
|
|
306
|
+
]),
|
|
307
|
+
// Every testimonial from the real, editable collection, mirrored
|
|
308
|
+
// here as `quote` blocks — unlike `service` (routed above, so a
|
|
309
|
+
// link can point at it), a testimonial has no page of its own
|
|
310
|
+
// worth linking to, and `quote` — text/author/role, contract B's
|
|
311
|
+
// vocabulary block for exactly this — is the honest fit.
|
|
312
|
+
...VITRINE_DEMO_TESTIMONIALS.map((demo, index) => ({
|
|
313
|
+
_key: `demo-about-quote-${index + 1}`,
|
|
314
|
+
_type: 'quote',
|
|
315
|
+
_version: BLOCK_VERSION,
|
|
316
|
+
text: demo.quote,
|
|
317
|
+
author: demo.authorName,
|
|
318
|
+
role: demo.authorRole,
|
|
319
|
+
})),
|
|
320
|
+
],
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
title: 'Contact',
|
|
324
|
+
slug: 'contact',
|
|
325
|
+
blocks: [
|
|
326
|
+
proseParagraph('demo-contact-prose', 'Tell us what you are trying to get done and which of the six practices it touches — brand, web, growth, operations, finance, or security. We will tell you honestly whether we can help on the first call, no discovery deck required.'),
|
|
327
|
+
{
|
|
328
|
+
_key: 'demo-contact-cta',
|
|
329
|
+
_type: 'cta',
|
|
330
|
+
_version: BLOCK_VERSION,
|
|
331
|
+
title: 'Get a quote',
|
|
332
|
+
text: 'Thirty minutes, no obligation. We reply the same business day.',
|
|
333
|
+
actions: [
|
|
334
|
+
{
|
|
335
|
+
label: 'Email us',
|
|
336
|
+
target: { href: 'mailto:hello@example.com' },
|
|
337
|
+
emphasis: 'primary',
|
|
338
|
+
},
|
|
339
|
+
],
|
|
340
|
+
},
|
|
341
|
+
],
|
|
342
|
+
},
|
|
343
|
+
];
|
|
344
|
+
}
|
|
345
|
+
function homeFaq() {
|
|
346
|
+
const items = [
|
|
347
|
+
[
|
|
348
|
+
'How long does a typical engagement take?',
|
|
349
|
+
'Most engagements run three to six weeks end to end. We scope and price the whole thing on a single call before a single hour is billed, so there is no discovery-phase invoice waiting at the end.',
|
|
158
350
|
],
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
slug: 'about',
|
|
163
|
-
blocks: [
|
|
164
|
-
{
|
|
165
|
-
_key: 'demo-about-prose',
|
|
166
|
-
_type: 'prose',
|
|
167
|
-
_version: BLOCK_VERSION,
|
|
168
|
-
body: [
|
|
169
|
-
{
|
|
170
|
-
_key: 'demo-about-p1',
|
|
171
|
-
_type: 'block',
|
|
172
|
-
style: 'normal',
|
|
173
|
-
children: [
|
|
174
|
-
{
|
|
175
|
-
_key: 'demo-about-p1-span',
|
|
176
|
-
_type: 'span',
|
|
177
|
-
text: 'This is a demo showcase site, scaffolded by create-cogenta from the "vitrine" blueprint. Its services and testimonials were seeded by the installer so there is real content to look at from the first run.',
|
|
178
|
-
marks: [],
|
|
179
|
-
},
|
|
180
|
-
],
|
|
181
|
-
markDefs: [],
|
|
182
|
-
},
|
|
183
|
-
],
|
|
184
|
-
},
|
|
185
|
-
// Testimonials are static `quote` blocks here, not a `collectionList`:
|
|
186
|
-
// unlike `service` (routed above, so a link can point at it), a
|
|
187
|
-
// testimonial has no page of its own worth linking to, and `quote`
|
|
188
|
-
// — text/author/role, contract B's vocabulary block for exactly this
|
|
189
|
-
// — is the honest fit. The `testimonial` collection stays real and
|
|
190
|
-
// editable in the admin; these two mirror its demo rows.
|
|
191
|
-
...VITRINE_DEMO_TESTIMONIALS.map((demo, index) => ({
|
|
192
|
-
_key: `demo-about-quote-${index + 1}`,
|
|
193
|
-
_type: 'quote',
|
|
194
|
-
_version: BLOCK_VERSION,
|
|
195
|
-
text: demo.quote,
|
|
196
|
-
author: demo.authorName,
|
|
197
|
-
role: demo.authorRole,
|
|
198
|
-
})),
|
|
351
|
+
[
|
|
352
|
+
'Do we own everything once the project ships?',
|
|
353
|
+
'Yes — the site, the brand files, the models and the source are yours outright. Northfield keeps no retainer requirement and no lock-in: change a phone number, swap a testimonial, or walk away entirely, all without calling us first.',
|
|
199
354
|
],
|
|
200
|
-
|
|
201
|
-
|
|
355
|
+
[
|
|
356
|
+
'Can we start with just one service?',
|
|
357
|
+
'Most clients do. Brand strategy and web design & build are the two most common starting points, and roughly half of our clients come back for a second service once the first one has paid for itself.',
|
|
358
|
+
],
|
|
359
|
+
[
|
|
360
|
+
'How do you price a project?',
|
|
361
|
+
'A fixed quote after a short discovery call, scoped to the outcome you actually need — never an open-ended hourly rate with no ceiling and no way to budget against it.',
|
|
362
|
+
],
|
|
363
|
+
];
|
|
364
|
+
return {
|
|
365
|
+
_key: 'demo-home-faq',
|
|
366
|
+
_type: 'faq',
|
|
367
|
+
_version: BLOCK_VERSION,
|
|
368
|
+
title: 'Questions we hear often',
|
|
369
|
+
items: items.map(([question, answer], index) => ({
|
|
370
|
+
_key: `demo-home-faq-${index}`,
|
|
371
|
+
question,
|
|
372
|
+
answer: richTextParagraph(`demo-home-faq-${index}-a`, answer),
|
|
373
|
+
})),
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
/** `VITRINE_DEMO_PAGES` — the fixed-shape alias every existing caller (and `blueprint-demo-blocks.test.ts`) used before L25's media-driven rewrite. Equivalent to `buildVitrineDemoPages({})`. */
|
|
377
|
+
export const VITRINE_DEMO_PAGES = buildVitrineDemoPages({});
|
|
202
378
|
export const VITRINE_RECOMMENDED_AGENTS = [
|
|
203
379
|
{
|
|
204
380
|
name: 'seoAgent',
|
|
@@ -211,29 +387,128 @@ export const VITRINE_RECOMMENDED_AGENTS = [
|
|
|
211
387
|
reason: 'Catches oversized hero media and third-party scripts that would slow the landing page down.',
|
|
212
388
|
},
|
|
213
389
|
];
|
|
390
|
+
/**
|
|
391
|
+
* `vitrine`'s own starting skin (`starting-skins.js`) — asserted present
|
|
392
|
+
* with a real check, not a `!`, since `STARTING_SKINS` is keyed by
|
|
393
|
+
* blueprint id and TypeScript cannot see that this particular key is
|
|
394
|
+
* always populated.
|
|
395
|
+
*/
|
|
396
|
+
function vitrinePalette() {
|
|
397
|
+
const skin = STARTING_SKINS.vitrine;
|
|
398
|
+
if (skin === undefined) {
|
|
399
|
+
// Same code `resolveBlueprint` (`registry.ts`) uses for its own
|
|
400
|
+
// "this cannot happen unless the registry itself is broken" guard —
|
|
401
|
+
// this is a bug in starting-skins.ts, never a user-facing condition.
|
|
402
|
+
throw new CogentaError({
|
|
403
|
+
code: 'BLUEPRINT_REGISTRY_CORRUPT',
|
|
404
|
+
message: 'STARTING_SKINS.vitrine is missing.',
|
|
405
|
+
hint: 'The "vitrine" entry must stay declared in starting-skins.ts for this blueprint to render its demo art.',
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
return skin.color;
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Procedural visuals this blueprint seeds (L25): a flat geometric hero
|
|
412
|
+
* backdrop, five neutral client logos for the trust strip, one wide cover
|
|
413
|
+
* for the engagement-dashboard figure, one avatar per testimonial, and one
|
|
414
|
+
* cover photo per demo service — all from the same starting-skin palette
|
|
415
|
+
* (`starting-skins.js`) this blueprint already ships.
|
|
416
|
+
*/
|
|
417
|
+
export const VITRINE_MEDIA_SPECS = [
|
|
418
|
+
{
|
|
419
|
+
name: 'hero',
|
|
420
|
+
spec: heroArt(vitrinePalette(), 'sun', 61),
|
|
421
|
+
alt: 'A consulting team at work',
|
|
422
|
+
photo: 'vitrine/hero.jpg',
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
name: 'shot',
|
|
426
|
+
spec: coverArt(vitrinePalette(), 62),
|
|
427
|
+
alt: 'The engagement dashboard',
|
|
428
|
+
photo: 'vitrine/dashboard.jpg',
|
|
429
|
+
},
|
|
430
|
+
...[0, 1, 2, 3, 4].map((index) => ({
|
|
431
|
+
name: `logo-${index}`,
|
|
432
|
+
spec: logoArt(70 + index),
|
|
433
|
+
alt: `Client logo ${index + 1}`,
|
|
434
|
+
})),
|
|
435
|
+
...VITRINE_DEMO_TESTIMONIALS.map((demo, index) => ({
|
|
436
|
+
name: `avatar-${index}`,
|
|
437
|
+
spec: avatarArt(vitrinePalette(), 80 + index),
|
|
438
|
+
alt: `Portrait of ${demo.authorName}`,
|
|
439
|
+
photo: `vitrine/avatar-${index + 1}.jpg`,
|
|
440
|
+
})),
|
|
441
|
+
...VITRINE_DEMO_SERVICES.map((demo, index) => ({
|
|
442
|
+
name: `service-${demo.slug}`,
|
|
443
|
+
spec: coverArt(vitrinePalette(), 90 + index),
|
|
444
|
+
alt: `${demo.name} cover art`,
|
|
445
|
+
})),
|
|
446
|
+
];
|
|
447
|
+
/** Header/footer navigation and the header call-to-action button (L25, D4). */
|
|
448
|
+
export const VITRINE_MENUS = {
|
|
449
|
+
header: [
|
|
450
|
+
{ label: 'Services', url: '/services/brand-strategy' },
|
|
451
|
+
{ label: 'About', url: '/about' },
|
|
452
|
+
{ label: 'Case studies', url: '#' },
|
|
453
|
+
{ label: 'Contact', url: '/contact' },
|
|
454
|
+
],
|
|
455
|
+
footer: [
|
|
456
|
+
{ label: 'Services', url: '/services/brand-strategy' },
|
|
457
|
+
{ label: 'Company', url: '/about' },
|
|
458
|
+
{ label: 'Legal', url: '#' },
|
|
459
|
+
],
|
|
460
|
+
headerAction: { label: 'Get a quote', url: '/contact' },
|
|
461
|
+
};
|
|
462
|
+
export const VITRINE_SITE_SETTINGS = {
|
|
463
|
+
'general.tagline': 'A consultancy that runs like software.',
|
|
464
|
+
'general.socialLinks': [
|
|
465
|
+
{ label: 'LinkedIn', url: 'https://linkedin.com/company/example' },
|
|
466
|
+
{ label: 'X', url: 'https://x.com/example' },
|
|
467
|
+
{ label: 'YouTube', url: 'https://youtube.com/@example' },
|
|
468
|
+
],
|
|
469
|
+
'general.footerNote': '1 Market Street, Suite 400, San Francisco, CA 94105',
|
|
470
|
+
};
|
|
214
471
|
/**
|
|
215
472
|
* Inserts the `vitrine` blueprint's demo content through the real
|
|
216
|
-
* `ContentStore` — never mocked (house rule).
|
|
473
|
+
* `ContentStore` — never mocked (house rule). Services are created first so
|
|
474
|
+
* their real ids exist for the home page's `featureGrid` links and, via
|
|
475
|
+
* `media`, for their own `coverImage`.
|
|
217
476
|
*/
|
|
218
|
-
async function seedVitrineDemoContent(
|
|
477
|
+
async function seedVitrineDemoContent(ctx) {
|
|
478
|
+
const { db, defaultLocale, adminId, media } = ctx;
|
|
219
479
|
const serviceStore = createContentStore({ db, collection: service, defaultLocale });
|
|
220
480
|
const testimonialStore = createContentStore({ db, collection: testimonial, defaultLocale });
|
|
221
481
|
const pageStore = createContentStore({ db, collection: page, defaultLocale });
|
|
482
|
+
const serviceIdBySlug = new Map();
|
|
222
483
|
for (const demo of VITRINE_DEMO_SERVICES) {
|
|
223
|
-
|
|
484
|
+
const cover = media[`service-${demo.slug}`];
|
|
485
|
+
const created = await serviceStore.create({
|
|
224
486
|
status: 'published',
|
|
225
487
|
createdBy: adminId,
|
|
226
|
-
values: {
|
|
488
|
+
values: {
|
|
489
|
+
name: demo.name,
|
|
490
|
+
slug: demo.slug,
|
|
491
|
+
description: demo.description,
|
|
492
|
+
icon: demo.icon,
|
|
493
|
+
...(cover === undefined ? {} : { coverImage: cover }),
|
|
494
|
+
},
|
|
227
495
|
});
|
|
496
|
+
serviceIdBySlug.set(demo.slug, created.id);
|
|
228
497
|
}
|
|
229
|
-
for (const demo of VITRINE_DEMO_TESTIMONIALS) {
|
|
498
|
+
for (const [index, demo] of VITRINE_DEMO_TESTIMONIALS.entries()) {
|
|
499
|
+
const avatar = media[`avatar-${index}`];
|
|
230
500
|
await testimonialStore.create({
|
|
231
501
|
status: 'published',
|
|
232
502
|
createdBy: adminId,
|
|
233
|
-
values: {
|
|
503
|
+
values: {
|
|
504
|
+
authorName: demo.authorName,
|
|
505
|
+
authorRole: demo.authorRole,
|
|
506
|
+
quote: demo.quote,
|
|
507
|
+
...(avatar === undefined ? {} : { avatar }),
|
|
508
|
+
},
|
|
234
509
|
});
|
|
235
510
|
}
|
|
236
|
-
for (const demo of
|
|
511
|
+
for (const demo of buildVitrineDemoPages(media, serviceIdBySlug)) {
|
|
237
512
|
await pageStore.create({
|
|
238
513
|
status: 'published',
|
|
239
514
|
createdBy: adminId,
|
|
@@ -246,5 +521,9 @@ export const vitrineContentPack = {
|
|
|
246
521
|
collections: VITRINE_COLLECTIONS,
|
|
247
522
|
recommendedAgents: VITRINE_RECOMMENDED_AGENTS,
|
|
248
523
|
seedDemoContent: seedVitrineDemoContent,
|
|
524
|
+
defaultTheme: '@cogenta/theme-entreprise',
|
|
525
|
+
menus: VITRINE_MENUS,
|
|
526
|
+
siteSettings: VITRINE_SITE_SETTINGS,
|
|
527
|
+
mediaSpecs: VITRINE_MEDIA_SPECS,
|
|
249
528
|
};
|
|
250
529
|
//# sourceMappingURL=vitrine.js.map
|