@getvitops/create 0.1.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/README.md +65 -0
- package/package.json +22 -0
- package/templates/emdash/.agents/skills/promote/SKILL.md +70 -0
- package/templates/emdash/.claude/hooks/session-start.sh +40 -0
- package/templates/emdash/.claude/settings.json +14 -0
- package/templates/emdash/.github/workflows/deploy-dev.yml +41 -0
- package/templates/emdash/.github/workflows/deploy-prod.yml +36 -0
- package/templates/emdash/.github/workflows/promote.yml +49 -0
- package/templates/emdash/.mcp.json +12 -0
- package/templates/emdash/AGENTS.md +50 -0
- package/templates/emdash/README.md +136 -0
- package/templates/emdash/_gitignore +25 -0
- package/templates/emdash/astro.config.mjs +41 -0
- package/templates/emdash/design-system.json +148 -0
- package/templates/emdash/package.json +46 -0
- package/templates/emdash/pnpm-workspace.yaml +34 -0
- package/templates/emdash/scripts/build-dev-wrangler.mjs +75 -0
- package/templates/emdash/seed/seed.json +343 -0
- package/templates/emdash/src/assets/logo.svg +6 -0
- package/templates/emdash/src/layouts/Layout.astro +133 -0
- package/templates/emdash/src/live.config.ts +12 -0
- package/templates/emdash/src/pages/404.astro +11 -0
- package/templates/emdash/src/pages/[...slug].astro +20 -0
- package/templates/emdash/src/pages/index.astro +27 -0
- package/templates/emdash/src/worker.ts +4 -0
- package/templates/emdash/tsconfig.json +5 -0
- package/templates/emdash/vite.config.ts +17 -0
- package/templates/emdash/wrangler.jsonc +34 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://unpkg.com/@getvitops/generator/schema.json",
|
|
3
|
+
"colors": {
|
|
4
|
+
"palette": {
|
|
5
|
+
"brand": { "seed": "#2e9b73" },
|
|
6
|
+
"ink": { "seed": "#3f4a5c" },
|
|
7
|
+
"sky": { "seed": "#2f7bc0" },
|
|
8
|
+
"sun": { "seed": "#d08a1f" },
|
|
9
|
+
"rose": { "seed": "#c74a42" }
|
|
10
|
+
},
|
|
11
|
+
"roles": {
|
|
12
|
+
"neutral": "ink",
|
|
13
|
+
"surface": "ink",
|
|
14
|
+
"ui-primary": "brand",
|
|
15
|
+
"brand-primary": "brand",
|
|
16
|
+
"info": "sky",
|
|
17
|
+
"success": "brand",
|
|
18
|
+
"warning": "sun",
|
|
19
|
+
"danger": "rose"
|
|
20
|
+
},
|
|
21
|
+
"utilities": ["bg", "text", "border"]
|
|
22
|
+
},
|
|
23
|
+
"shadows": {
|
|
24
|
+
"sm": "0 1px 2px rgb(0 0 0 / 0.08)",
|
|
25
|
+
"md": "0 4px 6px rgb(0 0 0 / 0.12)",
|
|
26
|
+
"lg": "0 10px 15px rgb(0 0 0 / 0.18)"
|
|
27
|
+
},
|
|
28
|
+
"fonts": {
|
|
29
|
+
"display": "system-ui, -apple-system, \"Segoe UI\", sans-serif",
|
|
30
|
+
"sans": "system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif",
|
|
31
|
+
"mono": "ui-monospace, \"SF Mono\", Menlo, monospace"
|
|
32
|
+
},
|
|
33
|
+
"typeScale": {
|
|
34
|
+
"base": "1rem",
|
|
35
|
+
"names": ["2xs", "xs", "s", "m", "l", "xl", "2xl", "3xl"],
|
|
36
|
+
"baseStep": 4,
|
|
37
|
+
"baseline": "m",
|
|
38
|
+
"ratio": 1.2,
|
|
39
|
+
"fluid": { "minVw": "22.5rem", "maxVw": "80rem", "minRatio": 1.12 }
|
|
40
|
+
},
|
|
41
|
+
"spaceScale": {
|
|
42
|
+
"base": "1rem",
|
|
43
|
+
"names": ["2xs", "xs", "s", "m", "l", "xl", "2xl", "3xl"],
|
|
44
|
+
"baseStep": 4,
|
|
45
|
+
"baseline": "m",
|
|
46
|
+
"ratio": 1.25,
|
|
47
|
+
"fluid": { "minVw": "22.5rem", "maxVw": "80rem", "minRatio": 1.2 }
|
|
48
|
+
},
|
|
49
|
+
"patterns": {
|
|
50
|
+
"defaults": {
|
|
51
|
+
"ds": "none",
|
|
52
|
+
"b": "1px solid var(--color-surface-xl)",
|
|
53
|
+
"br": "0.375rem",
|
|
54
|
+
"p": "1rem",
|
|
55
|
+
"fs": "1rem"
|
|
56
|
+
},
|
|
57
|
+
"radii": { "pill": "999px", "circle": "50%", "card": "0.5rem" },
|
|
58
|
+
"groups": {
|
|
59
|
+
"control": {
|
|
60
|
+
"ds": "var(--ds-default)",
|
|
61
|
+
"b": "var(--b-default)",
|
|
62
|
+
"br": "var(--br-default)",
|
|
63
|
+
"p": "0.5em 1em",
|
|
64
|
+
"fs": "var(--fs-default)"
|
|
65
|
+
},
|
|
66
|
+
"panel": {
|
|
67
|
+
"ds": "var(--shadow-md)",
|
|
68
|
+
"b": "var(--b-default)",
|
|
69
|
+
"br": "0.5rem",
|
|
70
|
+
"p": "1rem",
|
|
71
|
+
"fs": "var(--fs-default)"
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"z": { "raised": 1, "sticky": 100, "overlay": 200, "top": 1000 },
|
|
75
|
+
"items": {
|
|
76
|
+
"button": {
|
|
77
|
+
"group": "control",
|
|
78
|
+
"element": "button",
|
|
79
|
+
"default_role": "brand-primary",
|
|
80
|
+
"base": {
|
|
81
|
+
"padding": "0.6em 1.2em",
|
|
82
|
+
"border-radius": "var(--br-control, 0.25rem)",
|
|
83
|
+
"border": "none",
|
|
84
|
+
"font-weight": "600",
|
|
85
|
+
"color": "#fff",
|
|
86
|
+
"cursor": "pointer",
|
|
87
|
+
"box-shadow": "var(--shadow-sm)"
|
|
88
|
+
},
|
|
89
|
+
"states": {
|
|
90
|
+
"hover": { "step": 1 },
|
|
91
|
+
"active": { "scale": 0.97 },
|
|
92
|
+
"focus-visible": { "ring": true }
|
|
93
|
+
},
|
|
94
|
+
"roles": []
|
|
95
|
+
},
|
|
96
|
+
"card": {
|
|
97
|
+
"group": "panel",
|
|
98
|
+
"class": "card",
|
|
99
|
+
"base": {
|
|
100
|
+
"border-radius": "var(--br-card-group)",
|
|
101
|
+
"padding": "1.5rem",
|
|
102
|
+
"background": "var(--color-surface-xxl)",
|
|
103
|
+
"border": "var(--b-card-group)",
|
|
104
|
+
"box-shadow": "var(--ds-card-group)"
|
|
105
|
+
},
|
|
106
|
+
"states": {},
|
|
107
|
+
"roles": []
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"typography": {
|
|
112
|
+
"families": {
|
|
113
|
+
"display": "var(--font-display)",
|
|
114
|
+
"sans": "var(--font-sans)",
|
|
115
|
+
"code": "var(--font-mono, ui-monospace, monospace)"
|
|
116
|
+
},
|
|
117
|
+
"roles": {
|
|
118
|
+
"display": {
|
|
119
|
+
"family": "display",
|
|
120
|
+
"size": "var(--text-3xl)",
|
|
121
|
+
"weight": 700,
|
|
122
|
+
"line-height": "1.05",
|
|
123
|
+
"tracking": "-0.03em"
|
|
124
|
+
},
|
|
125
|
+
"heading": {
|
|
126
|
+
"family": "display",
|
|
127
|
+
"size": "var(--text-xl)",
|
|
128
|
+
"weight": 600,
|
|
129
|
+
"line-height": "1.3"
|
|
130
|
+
},
|
|
131
|
+
"body": { "family": "sans", "size": "var(--text-m)", "weight": 400, "line-height": "1.55" }
|
|
132
|
+
},
|
|
133
|
+
"headings": { "h1": "display", "h2": "heading", "h3": "heading" }
|
|
134
|
+
},
|
|
135
|
+
"animations": {
|
|
136
|
+
"effects": {
|
|
137
|
+
"fade-in": { "kf": "composite", "vars": { "opacity-from": 0 } },
|
|
138
|
+
"slide-up": {
|
|
139
|
+
"kf": "composite",
|
|
140
|
+
"vars": { "translate-y-from": "var(--slide-distance, 2rem)" }
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
"journeys": {
|
|
144
|
+
"base": { "fade": { "opacity-from": 0 }, "slide": {} },
|
|
145
|
+
"compose": [["fade"], ["slide"], ["fade", "slide"]]
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "my-emdash-site",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "astro dev",
|
|
8
|
+
"build": "astro build",
|
|
9
|
+
"preview": "astro preview",
|
|
10
|
+
"deploy": "astro build && wrangler deploy",
|
|
11
|
+
"deploy:dev": "astro build && node scripts/build-dev-wrangler.mjs && wrangler deploy --config dist/server/wrangler.dev.json",
|
|
12
|
+
"typecheck": "astro check",
|
|
13
|
+
"build:css": "vitops generate -i design-system.json -f tailwind -o src/styles",
|
|
14
|
+
"prepare": "vp config"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@astrojs/cloudflare": "^14.0.0",
|
|
18
|
+
"@astrojs/react": "^6.0.0",
|
|
19
|
+
"@emdash-cms/cloudflare": "^0.31.0",
|
|
20
|
+
"@getvitops/astro": "^0.4.0",
|
|
21
|
+
"@getvitops/emdash": "^0.1.0",
|
|
22
|
+
"astro": "^7.1.2",
|
|
23
|
+
"emdash": "^0.31.0",
|
|
24
|
+
"react": "^19.2.4",
|
|
25
|
+
"react-dom": "^19.2.4"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@astrojs/check": "^0.9.7",
|
|
29
|
+
"@cloudflare/workers-types": "^4.20260305.1",
|
|
30
|
+
"@getvitops/cli": "^0.4.0",
|
|
31
|
+
"typescript": "^6.0.3",
|
|
32
|
+
"vite-plus": "catalog:",
|
|
33
|
+
"wrangler": "^4.111.0"
|
|
34
|
+
},
|
|
35
|
+
"devEngines": {
|
|
36
|
+
"runtime": {
|
|
37
|
+
"name": "node",
|
|
38
|
+
"version": "24.18.0",
|
|
39
|
+
"onFail": "download"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"packageManager": "pnpm@11.9.0",
|
|
43
|
+
"emdash": {
|
|
44
|
+
"seed": "seed/seed.json"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Build scripts: allow only what each runtime needs; rest false so
|
|
2
|
+
# strictDepBuilds (pnpm >=10.26 / 11) passes.
|
|
3
|
+
allowBuilds:
|
|
4
|
+
esbuild: true
|
|
5
|
+
workerd: true
|
|
6
|
+
better-sqlite3: false
|
|
7
|
+
sharp: false
|
|
8
|
+
|
|
9
|
+
# Supply-chain hardening: cooldown on brand-new releases (toolchain exempt)
|
|
10
|
+
# and no non-registry transitive sources.
|
|
11
|
+
minimumReleaseAge: 1440
|
|
12
|
+
minimumReleaseAgeExclude:
|
|
13
|
+
- '@getvitops/*'
|
|
14
|
+
- emdash
|
|
15
|
+
- '@emdash-cms/*'
|
|
16
|
+
- vite-plus
|
|
17
|
+
- '@voidzero-dev/*'
|
|
18
|
+
- oxlint
|
|
19
|
+
- '@oxlint/*'
|
|
20
|
+
- oxlint-tsgolint
|
|
21
|
+
- '@oxlint-tsgolint/*'
|
|
22
|
+
- oxfmt
|
|
23
|
+
- '@oxfmt/*'
|
|
24
|
+
blockExoticSubdeps: true
|
|
25
|
+
catalog:
|
|
26
|
+
vite: npm:@voidzero-dev/vite-plus-core@latest
|
|
27
|
+
vite-plus: latest
|
|
28
|
+
overrides:
|
|
29
|
+
vite: 'catalog:'
|
|
30
|
+
peerDependencyRules:
|
|
31
|
+
allowAny:
|
|
32
|
+
- vite
|
|
33
|
+
allowedVersions:
|
|
34
|
+
vite: '*'
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// Post-build step for the DEV deploy target.
|
|
2
|
+
//
|
|
3
|
+
// Why this exists: the @astrojs/cloudflare adapter regenerates
|
|
4
|
+
// dist/server/wrangler.json at build time and drops any top-level `env` block,
|
|
5
|
+
// so wrangler's native `--env dev` cannot be used. Instead we take the
|
|
6
|
+
// adapter's generated (prod) config — which already carries the injected
|
|
7
|
+
// ASSETS / SESSION / Durable Object / triggers bindings — and rewrite only the
|
|
8
|
+
// identity + data targets so the dev worker is fully isolated:
|
|
9
|
+
//
|
|
10
|
+
// name <name> → <name>-dev
|
|
11
|
+
// routes <domain> → dev.<domain> (only if a custom domain is set)
|
|
12
|
+
// D1 binding DB → <name>-dev (id from $DEV_D1_ID)
|
|
13
|
+
// R2 binding MEDIA → <bucket>-dev
|
|
14
|
+
//
|
|
15
|
+
// Run after `astro build`, then deploy the emitted flat config explicitly:
|
|
16
|
+
// node scripts/build-dev-wrangler.mjs
|
|
17
|
+
// wrangler deploy --config dist/server/wrangler.dev.json
|
|
18
|
+
//
|
|
19
|
+
// SAFETY: refuses to run without $DEV_D1_ID. Falling back to the prod D1 id
|
|
20
|
+
// would bind the dev worker to the PRODUCTION database — the exact thing this
|
|
21
|
+
// split exists to prevent. One-time setup:
|
|
22
|
+
// wrangler d1 create <name>-dev → export DEV_D1_ID=<the id it prints>
|
|
23
|
+
// wrangler r2 bucket create <bucket>-dev
|
|
24
|
+
|
|
25
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
26
|
+
|
|
27
|
+
const GENERATED = 'dist/server/wrangler.json';
|
|
28
|
+
const OUT = 'dist/server/wrangler.dev.json';
|
|
29
|
+
|
|
30
|
+
const DEV_D1_ID = process.env.DEV_D1_ID;
|
|
31
|
+
if (!DEV_D1_ID) {
|
|
32
|
+
console.error(
|
|
33
|
+
'ERROR: DEV_D1_ID is not set.\n' +
|
|
34
|
+
'Create the isolated dev database and export its id first:\n' +
|
|
35
|
+
' wrangler d1 create <your-worker-name>-dev\n' +
|
|
36
|
+
' export DEV_D1_ID=<the id it prints>\n' +
|
|
37
|
+
'Refusing to continue — without it the dev worker could bind the prod DB.',
|
|
38
|
+
);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
let cfg;
|
|
43
|
+
try {
|
|
44
|
+
cfg = JSON.parse(readFileSync(GENERATED, 'utf8'));
|
|
45
|
+
} catch (err) {
|
|
46
|
+
console.error(`ERROR: could not read ${GENERATED}. Run \`astro build\` first.\n${err}`);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const devName = `${cfg.name}-dev`;
|
|
51
|
+
cfg.name = devName;
|
|
52
|
+
|
|
53
|
+
// Custom domain → dev.<domain>. Without one, the dev worker just serves from
|
|
54
|
+
// its workers.dev subdomain (<name>-dev.<account>.workers.dev).
|
|
55
|
+
if (Array.isArray(cfg.routes)) {
|
|
56
|
+
cfg.routes = cfg.routes.map((route) =>
|
|
57
|
+
route?.pattern ? { ...route, pattern: `dev.${route.pattern}` } : route,
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
cfg.d1_databases = (cfg.d1_databases ?? []).map((d) =>
|
|
62
|
+
d.binding === 'DB' ? { ...d, database_name: devName, database_id: DEV_D1_ID } : d,
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
cfg.r2_buckets = (cfg.r2_buckets ?? []).map((r) =>
|
|
66
|
+
r.binding === 'MEDIA' ? { ...r, bucket_name: `${r.bucket_name}-dev` } : r,
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
// Flat config — no nested environments.
|
|
70
|
+
delete cfg.env;
|
|
71
|
+
|
|
72
|
+
writeFileSync(OUT, `${JSON.stringify(cfg, null, 2)}\n`);
|
|
73
|
+
console.log(
|
|
74
|
+
`Wrote ${OUT}\n name: ${cfg.name}\n routes: ${JSON.stringify(cfg.routes ?? [])}\n D1: ${devName} (${DEV_D1_ID})`,
|
|
75
|
+
);
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://emdashcms.com/seed.schema.json",
|
|
3
|
+
"version": "1",
|
|
4
|
+
"meta": {
|
|
5
|
+
"name": "Vitops Starter",
|
|
6
|
+
"description": "An EmDash website wired to the Vitops design system",
|
|
7
|
+
"author": "Vitops"
|
|
8
|
+
},
|
|
9
|
+
"settings": {
|
|
10
|
+
"title": "My EmDash Site",
|
|
11
|
+
"tagline": "An EmDash website with the Vitops design system"
|
|
12
|
+
},
|
|
13
|
+
"collections": [
|
|
14
|
+
{
|
|
15
|
+
"slug": "pages",
|
|
16
|
+
"label": "Pages",
|
|
17
|
+
"labelSingular": "Page",
|
|
18
|
+
"supports": ["drafts", "revisions", "seo"],
|
|
19
|
+
"fields": [
|
|
20
|
+
{
|
|
21
|
+
"slug": "title",
|
|
22
|
+
"label": "Title",
|
|
23
|
+
"type": "string",
|
|
24
|
+
"required": true
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"slug": "content",
|
|
28
|
+
"label": "Content",
|
|
29
|
+
"type": "portableText"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"menus": [
|
|
35
|
+
{
|
|
36
|
+
"name": "primary",
|
|
37
|
+
"label": "Primary Navigation",
|
|
38
|
+
"items": [
|
|
39
|
+
{ "type": "custom", "label": "Home", "url": "/" },
|
|
40
|
+
{ "type": "custom", "label": "About", "url": "/about" }
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "footer",
|
|
45
|
+
"label": "Footer",
|
|
46
|
+
"items": [
|
|
47
|
+
{ "type": "custom", "label": "Terms & Conditions", "url": "/terms" },
|
|
48
|
+
{ "type": "custom", "label": "Privacy Policy", "url": "/privacy" }
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
"content": {
|
|
53
|
+
"pages": [
|
|
54
|
+
{
|
|
55
|
+
"id": "home",
|
|
56
|
+
"slug": "home",
|
|
57
|
+
"status": "published",
|
|
58
|
+
"data": {
|
|
59
|
+
"title": "Home",
|
|
60
|
+
"content": [
|
|
61
|
+
{
|
|
62
|
+
"_type": "block",
|
|
63
|
+
"_key": "intro-heading",
|
|
64
|
+
"style": "h2",
|
|
65
|
+
"markDefs": [],
|
|
66
|
+
"children": [
|
|
67
|
+
{
|
|
68
|
+
"_type": "span",
|
|
69
|
+
"_key": "intro-heading-1",
|
|
70
|
+
"text": "Your site is running",
|
|
71
|
+
"marks": []
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"_type": "block",
|
|
77
|
+
"_key": "intro-body",
|
|
78
|
+
"style": "normal",
|
|
79
|
+
"markDefs": [],
|
|
80
|
+
"children": [
|
|
81
|
+
{
|
|
82
|
+
"_type": "span",
|
|
83
|
+
"_key": "intro-body-1",
|
|
84
|
+
"text": "This page is served from the EmDash database. Edit it in the admin at /_emdash/admin — the Vitops design-system blocks are available from the editor's slash menu.",
|
|
85
|
+
"marks": []
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"_type": "vitops.banner",
|
|
91
|
+
"_key": "welcome-banner",
|
|
92
|
+
"message": "This banner is a Vitops block — dismiss it, then edit this page in the EmDash admin.",
|
|
93
|
+
"tone": "info",
|
|
94
|
+
"dismissible": true
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"_type": "vitops.details",
|
|
98
|
+
"_key": "next-steps",
|
|
99
|
+
"summary": "Next steps",
|
|
100
|
+
"body": "Adjust design-system.json to your brand (colors, type, patterns), replace src/assets/logo.svg, then deploy with `pnpm deploy`.",
|
|
101
|
+
"open": false
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"id": "about",
|
|
108
|
+
"slug": "about",
|
|
109
|
+
"status": "published",
|
|
110
|
+
"data": {
|
|
111
|
+
"title": "About",
|
|
112
|
+
"content": [
|
|
113
|
+
{
|
|
114
|
+
"_type": "block",
|
|
115
|
+
"_key": "about-body",
|
|
116
|
+
"style": "normal",
|
|
117
|
+
"markDefs": [],
|
|
118
|
+
"children": [
|
|
119
|
+
{
|
|
120
|
+
"_type": "span",
|
|
121
|
+
"_key": "about-body-1",
|
|
122
|
+
"text": "This page is rendered by the catch-all route (src/pages/[...slug].astro). Any page you create in the pages collection appears at its slug automatically.",
|
|
123
|
+
"marks": []
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"id": "terms",
|
|
132
|
+
"slug": "terms",
|
|
133
|
+
"status": "published",
|
|
134
|
+
"data": {
|
|
135
|
+
"title": "Terms & Conditions",
|
|
136
|
+
"content": [
|
|
137
|
+
{
|
|
138
|
+
"_type": "vitops.banner",
|
|
139
|
+
"_key": "terms-placeholder",
|
|
140
|
+
"message": "Placeholder text — replace with your own terms before launch. This is not legal advice.",
|
|
141
|
+
"tone": "warning",
|
|
142
|
+
"dismissible": false
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"_type": "block",
|
|
146
|
+
"_key": "terms-intro",
|
|
147
|
+
"style": "normal",
|
|
148
|
+
"markDefs": [],
|
|
149
|
+
"children": [
|
|
150
|
+
{
|
|
151
|
+
"_type": "span",
|
|
152
|
+
"_key": "terms-intro-1",
|
|
153
|
+
"text": "These terms and conditions govern your use of this website. By accessing or using the site, you agree to be bound by them. If you disagree with any part of these terms, please do not use the site.",
|
|
154
|
+
"marks": []
|
|
155
|
+
}
|
|
156
|
+
]
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"_type": "block",
|
|
160
|
+
"_key": "terms-use-h",
|
|
161
|
+
"style": "h2",
|
|
162
|
+
"markDefs": [],
|
|
163
|
+
"children": [
|
|
164
|
+
{ "_type": "span", "_key": "terms-use-h-1", "text": "Use of the site", "marks": [] }
|
|
165
|
+
]
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"_type": "block",
|
|
169
|
+
"_key": "terms-use",
|
|
170
|
+
"style": "normal",
|
|
171
|
+
"markDefs": [],
|
|
172
|
+
"children": [
|
|
173
|
+
{
|
|
174
|
+
"_type": "span",
|
|
175
|
+
"_key": "terms-use-1",
|
|
176
|
+
"text": "Content on this site is provided for general information only and may change without notice. You may not use the site in any way that causes, or may cause, damage to the site or impairment of its availability.",
|
|
177
|
+
"marks": []
|
|
178
|
+
}
|
|
179
|
+
]
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"_type": "block",
|
|
183
|
+
"_key": "terms-liability-h",
|
|
184
|
+
"style": "h2",
|
|
185
|
+
"markDefs": [],
|
|
186
|
+
"children": [
|
|
187
|
+
{
|
|
188
|
+
"_type": "span",
|
|
189
|
+
"_key": "terms-liability-h-1",
|
|
190
|
+
"text": "Limitation of liability",
|
|
191
|
+
"marks": []
|
|
192
|
+
}
|
|
193
|
+
]
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"_type": "block",
|
|
197
|
+
"_key": "terms-liability",
|
|
198
|
+
"style": "normal",
|
|
199
|
+
"markDefs": [],
|
|
200
|
+
"children": [
|
|
201
|
+
{
|
|
202
|
+
"_type": "span",
|
|
203
|
+
"_key": "terms-liability-1",
|
|
204
|
+
"text": "The site is provided \"as is\" without warranties of any kind. To the fullest extent permitted by law, we exclude all liability for any loss or damage arising from use of the site.",
|
|
205
|
+
"marks": []
|
|
206
|
+
}
|
|
207
|
+
]
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"_type": "block",
|
|
211
|
+
"_key": "terms-contact",
|
|
212
|
+
"style": "normal",
|
|
213
|
+
"markDefs": [],
|
|
214
|
+
"children": [
|
|
215
|
+
{
|
|
216
|
+
"_type": "span",
|
|
217
|
+
"_key": "terms-contact-1",
|
|
218
|
+
"text": "Questions about these terms? Contact the site owner. Edit this page in the EmDash admin.",
|
|
219
|
+
"marks": []
|
|
220
|
+
}
|
|
221
|
+
]
|
|
222
|
+
}
|
|
223
|
+
]
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"id": "privacy",
|
|
228
|
+
"slug": "privacy",
|
|
229
|
+
"status": "published",
|
|
230
|
+
"data": {
|
|
231
|
+
"title": "Privacy Policy",
|
|
232
|
+
"content": [
|
|
233
|
+
{
|
|
234
|
+
"_type": "vitops.banner",
|
|
235
|
+
"_key": "privacy-placeholder",
|
|
236
|
+
"message": "Placeholder text — replace with your own privacy policy before launch. This is not legal advice.",
|
|
237
|
+
"tone": "warning",
|
|
238
|
+
"dismissible": false
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
"_type": "block",
|
|
242
|
+
"_key": "privacy-intro",
|
|
243
|
+
"style": "normal",
|
|
244
|
+
"markDefs": [],
|
|
245
|
+
"children": [
|
|
246
|
+
{
|
|
247
|
+
"_type": "span",
|
|
248
|
+
"_key": "privacy-intro-1",
|
|
249
|
+
"text": "This policy describes what information this website collects, how it is used, and the choices you have. We collect only what we need to operate the site.",
|
|
250
|
+
"marks": []
|
|
251
|
+
}
|
|
252
|
+
]
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"_type": "block",
|
|
256
|
+
"_key": "privacy-collect-h",
|
|
257
|
+
"style": "h2",
|
|
258
|
+
"markDefs": [],
|
|
259
|
+
"children": [
|
|
260
|
+
{
|
|
261
|
+
"_type": "span",
|
|
262
|
+
"_key": "privacy-collect-h-1",
|
|
263
|
+
"text": "What we collect",
|
|
264
|
+
"marks": []
|
|
265
|
+
}
|
|
266
|
+
]
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
"_type": "block",
|
|
270
|
+
"_key": "privacy-collect",
|
|
271
|
+
"style": "normal",
|
|
272
|
+
"markDefs": [],
|
|
273
|
+
"children": [
|
|
274
|
+
{
|
|
275
|
+
"_type": "span",
|
|
276
|
+
"_key": "privacy-collect-1",
|
|
277
|
+
"text": "Standard server logs (IP address, browser type, pages visited) used for security and troubleshooting, and any information you submit through forms on the site.",
|
|
278
|
+
"marks": []
|
|
279
|
+
}
|
|
280
|
+
]
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
"_type": "block",
|
|
284
|
+
"_key": "privacy-use-h",
|
|
285
|
+
"style": "h2",
|
|
286
|
+
"markDefs": [],
|
|
287
|
+
"children": [
|
|
288
|
+
{
|
|
289
|
+
"_type": "span",
|
|
290
|
+
"_key": "privacy-use-h-1",
|
|
291
|
+
"text": "How we use it",
|
|
292
|
+
"marks": []
|
|
293
|
+
}
|
|
294
|
+
]
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
"_type": "block",
|
|
298
|
+
"_key": "privacy-use",
|
|
299
|
+
"style": "normal",
|
|
300
|
+
"markDefs": [],
|
|
301
|
+
"children": [
|
|
302
|
+
{
|
|
303
|
+
"_type": "span",
|
|
304
|
+
"_key": "privacy-use-1",
|
|
305
|
+
"text": "To operate and secure the site and to respond to your enquiries. We do not sell personal information. Third-party services used to host this site (e.g. Cloudflare) process data under their own policies.",
|
|
306
|
+
"marks": []
|
|
307
|
+
}
|
|
308
|
+
]
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
"_type": "block",
|
|
312
|
+
"_key": "privacy-rights-h",
|
|
313
|
+
"style": "h2",
|
|
314
|
+
"markDefs": [],
|
|
315
|
+
"children": [
|
|
316
|
+
{
|
|
317
|
+
"_type": "span",
|
|
318
|
+
"_key": "privacy-rights-h-1",
|
|
319
|
+
"text": "Your rights",
|
|
320
|
+
"marks": []
|
|
321
|
+
}
|
|
322
|
+
]
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
"_type": "block",
|
|
326
|
+
"_key": "privacy-rights",
|
|
327
|
+
"style": "normal",
|
|
328
|
+
"markDefs": [],
|
|
329
|
+
"children": [
|
|
330
|
+
{
|
|
331
|
+
"_type": "span",
|
|
332
|
+
"_key": "privacy-rights-1",
|
|
333
|
+
"text": "You may request access to, correction of, or deletion of your personal information by contacting the site owner. Edit this page in the EmDash admin.",
|
|
334
|
+
"marks": []
|
|
335
|
+
}
|
|
336
|
+
]
|
|
337
|
+
}
|
|
338
|
+
]
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
]
|
|
342
|
+
}
|
|
343
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
|
2
|
+
<!-- Placeholder mark — replace with your brand. This file is also the
|
|
3
|
+
favicon/PWA source (see astro.config.mjs → getvitops({ favicon })). -->
|
|
4
|
+
<rect width="64" height="64" rx="14" fill="#2e9b73" />
|
|
5
|
+
<path d="M18 24l14 20 14-20" fill="none" stroke="#fff" stroke-width="6" stroke-linecap="round" stroke-linejoin="round" />
|
|
6
|
+
</svg>
|