@o-a/cms-agent 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/LICENSE +105 -0
- package/README.md +132 -0
- package/dist/boot.d.ts +15 -0
- package/dist/boot.js +33 -0
- package/dist/config.d.ts +19 -0
- package/dist/config.js +45 -0
- package/dist/create-site/cli.d.ts +2 -0
- package/dist/create-site/cli.js +31 -0
- package/dist/create-site/generate-site.d.ts +9 -0
- package/dist/create-site/generate-site.js +109 -0
- package/dist/create-site/mint-token-cli.d.ts +2 -0
- package/dist/create-site/mint-token-cli.js +26 -0
- package/dist/create-site/mint-token.d.ts +7 -0
- package/dist/create-site/mint-token.js +49 -0
- package/dist/create-site/template/content/menus/footerCompany.json +9 -0
- package/dist/create-site/template/content/menus/footerProduct.json +9 -0
- package/dist/create-site/template/content/menus/footerResources.json +9 -0
- package/dist/create-site/template/content/menus/main.json +9 -0
- package/dist/create-site/template/content/pages/404.json +22 -0
- package/dist/create-site/template/content/pages/about/careers.json +21 -0
- package/dist/create-site/template/content/pages/about/team.json +21 -0
- package/dist/create-site/template/content/pages/about.json +21 -0
- package/dist/create-site/template/content/pages/docs/deployment.json +21 -0
- package/dist/create-site/template/content/pages/docs/getting-started/quickstart.json +21 -0
- package/dist/create-site/template/content/pages/docs/getting-started.json +23 -0
- package/dist/create-site/template/content/pages/docs.json +21 -0
- package/dist/create-site/template/content/pages/index.json +181 -0
- package/dist/create-site/template/content/redirects.json +4 -0
- package/dist/create-site/template/dockerignore +6 -0
- package/dist/create-site/template/gitignore +11 -0
- package/dist/create-site/template/theme/assets/site.js +49 -0
- package/dist/create-site/template/theme/assets/style.css +1153 -0
- package/dist/create-site/template/theme/blocks/button.liquid +21 -0
- package/dist/create-site/template/theme/blocks/comparison-row.liquid +19 -0
- package/dist/create-site/template/theme/blocks/faq-item.liquid +22 -0
- package/dist/create-site/template/theme/blocks/feature-card.liquid +23 -0
- package/dist/create-site/template/theme/blocks/logo-mark.liquid +13 -0
- package/dist/create-site/template/theme/blocks/pricing-tier.liquid +42 -0
- package/dist/create-site/template/theme/blocks/step-card.liquid +19 -0
- package/dist/create-site/template/theme/blocks/testimonial-card.liquid +25 -0
- package/dist/create-site/template/theme/layouts/theme.liquid +99 -0
- package/dist/create-site/template/theme/sections/comparison.liquid +41 -0
- package/dist/create-site/template/theme/sections/cta-banner.liquid +27 -0
- package/dist/create-site/template/theme/sections/faq.liquid +27 -0
- package/dist/create-site/template/theme/sections/feature-grid.liquid +27 -0
- package/dist/create-site/template/theme/sections/hero.liquid +36 -0
- package/dist/create-site/template/theme/sections/how-it-works.liquid +27 -0
- package/dist/create-site/template/theme/sections/pricing.liquid +27 -0
- package/dist/create-site/template/theme/sections/social-proof.liquid +21 -0
- package/dist/create-site/template/theme/sections/testimonials.liquid +27 -0
- package/dist/create-site/template/theme/snippets/icon.liquid +24 -0
- package/dist/create-site/template/theme/snippets/logo.liquid +7 -0
- package/dist/create-site/template/theme/snippets/site-name.liquid +1 -0
- package/dist/create-site/template/vhost/Dockerfile +33 -0
- package/dist/create-site/template/vhost/docker-entrypoint.sh +30 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4 -0
- package/dist/media/drivers/driver.d.ts +11 -0
- package/dist/media/drivers/driver.js +1 -0
- package/dist/media/drivers/local-fs-driver.d.ts +3 -0
- package/dist/media/drivers/local-fs-driver.js +81 -0
- package/dist/media/filename.d.ts +1 -0
- package/dist/media/filename.js +31 -0
- package/dist/media/manage-media.d.ts +19 -0
- package/dist/media/manage-media.js +45 -0
- package/dist/migrations/index.d.ts +3 -0
- package/dist/migrations/index.js +49 -0
- package/dist/renderer/engine.d.ts +2 -0
- package/dist/renderer/engine.js +48 -0
- package/dist/renderer/render-page.d.ts +28 -0
- package/dist/renderer/render-page.js +143 -0
- package/dist/renderer/theme-templates.d.ts +7 -0
- package/dist/renderer/theme-templates.js +82 -0
- package/dist/routes/assets.d.ts +6 -0
- package/dist/routes/assets.js +30 -0
- package/dist/routes/batch.d.ts +10 -0
- package/dist/routes/batch.js +148 -0
- package/dist/routes/capabilities.d.ts +5 -0
- package/dist/routes/capabilities.js +27 -0
- package/dist/routes/content.d.ts +8 -0
- package/dist/routes/content.js +166 -0
- package/dist/routes/drafts.d.ts +10 -0
- package/dist/routes/drafts.js +73 -0
- package/dist/routes/git.d.ts +8 -0
- package/dist/routes/git.js +158 -0
- package/dist/routes/index.d.ts +19 -0
- package/dist/routes/index.js +84 -0
- package/dist/routes/media-public.d.ts +5 -0
- package/dist/routes/media-public.js +48 -0
- package/dist/routes/media.d.ts +9 -0
- package/dist/routes/media.js +84 -0
- package/dist/routes/menus.d.ts +8 -0
- package/dist/routes/menus.js +77 -0
- package/dist/routes/preview-revision.d.ts +13 -0
- package/dist/routes/preview-revision.js +109 -0
- package/dist/routes/preview.d.ts +13 -0
- package/dist/routes/preview.js +52 -0
- package/dist/routes/public.d.ts +11 -0
- package/dist/routes/public.js +117 -0
- package/dist/routes/publish.d.ts +10 -0
- package/dist/routes/publish.js +105 -0
- package/dist/routes/redirects.d.ts +8 -0
- package/dist/routes/redirects.js +132 -0
- package/dist/routes/search.d.ts +8 -0
- package/dist/routes/search.js +11 -0
- package/dist/routes/sitemap.d.ts +6 -0
- package/dist/routes/sitemap.js +79 -0
- package/dist/routes/theme.d.ts +10 -0
- package/dist/routes/theme.js +17 -0
- package/dist/schemas/instance.schema.json +17 -0
- package/dist/schemas/menu.schema.json +23 -0
- package/dist/schemas/page.schema.json +20 -0
- package/dist/schemas/post.schema.json +25 -0
- package/dist/schemas/redirects.schema.json +24 -0
- package/dist/search/drivers/driver.d.ts +9 -0
- package/dist/search/drivers/driver.js +1 -0
- package/dist/search/drivers/node-sqlite-driver.d.ts +3 -0
- package/dist/search/drivers/node-sqlite-driver.js +19 -0
- package/dist/search/query-index.d.ts +5 -0
- package/dist/search/query-index.js +21 -0
- package/dist/search/rebuild-index.d.ts +2 -0
- package/dist/search/rebuild-index.js +111 -0
- package/dist/server-config.d.ts +22 -0
- package/dist/server-config.js +196 -0
- package/dist/server.d.ts +13 -0
- package/dist/server.js +163 -0
- package/dist/services/batch.d.ts +35 -0
- package/dist/services/batch.js +136 -0
- package/dist/services/checkpoint.d.ts +4 -0
- package/dist/services/checkpoint.js +45 -0
- package/dist/services/content-read.d.ts +27 -0
- package/dist/services/content-read.js +156 -0
- package/dist/services/delete-content.d.ts +12 -0
- package/dist/services/delete-content.js +174 -0
- package/dist/services/dev-tunnel.d.ts +5 -0
- package/dist/services/dev-tunnel.js +5 -0
- package/dist/services/drafts.d.ts +15 -0
- package/dist/services/drafts.js +155 -0
- package/dist/services/etag.d.ts +2 -0
- package/dist/services/etag.js +30 -0
- package/dist/services/fs-walk.d.ts +1 -0
- package/dist/services/fs-walk.js +26 -0
- package/dist/services/git-commit.d.ts +3 -0
- package/dist/services/git-commit.js +12 -0
- package/dist/services/git-history.d.ts +28 -0
- package/dist/services/git-history.js +131 -0
- package/dist/services/git-revert.d.ts +12 -0
- package/dist/services/git-revert.js +140 -0
- package/dist/services/git.d.ts +16 -0
- package/dist/services/git.js +127 -0
- package/dist/services/interval-job.d.ts +4 -0
- package/dist/services/interval-job.js +9 -0
- package/dist/services/ip-allowlist.d.ts +7 -0
- package/dist/services/ip-allowlist.js +31 -0
- package/dist/services/manage-menus.d.ts +10 -0
- package/dist/services/manage-menus.js +84 -0
- package/dist/services/manage-redirects.d.ts +25 -0
- package/dist/services/manage-redirects.js +166 -0
- package/dist/services/menus.d.ts +8 -0
- package/dist/services/menus.js +42 -0
- package/dist/services/migration-runner.d.ts +13 -0
- package/dist/services/migration-runner.js +123 -0
- package/dist/services/mime-types.d.ts +3 -0
- package/dist/services/mime-types.js +36 -0
- package/dist/services/move.d.ts +16 -0
- package/dist/services/move.js +175 -0
- package/dist/services/path-safety.d.ts +6 -0
- package/dist/services/path-safety.js +112 -0
- package/dist/services/post-urls.d.ts +3 -0
- package/dist/services/post-urls.js +27 -0
- package/dist/services/prepared-operation.d.ts +4 -0
- package/dist/services/prepared-operation.js +1 -0
- package/dist/services/publish.d.ts +14 -0
- package/dist/services/publish.js +254 -0
- package/dist/services/rate-limit-config.d.ts +9 -0
- package/dist/services/rate-limit-config.js +20 -0
- package/dist/services/redirects.d.ts +27 -0
- package/dist/services/redirects.js +175 -0
- package/dist/services/resolve-blog-url.d.ts +11 -0
- package/dist/services/resolve-blog-url.js +31 -0
- package/dist/services/resolve-url.d.ts +11 -0
- package/dist/services/resolve-url.js +20 -0
- package/dist/services/startup-checks.d.ts +10 -0
- package/dist/services/startup-checks.js +81 -0
- package/dist/services/static-file.d.ts +7 -0
- package/dist/services/static-file.js +37 -0
- package/dist/services/theme-component-file.d.ts +5 -0
- package/dist/services/theme-component-file.js +32 -0
- package/dist/services/theme-page-templates.d.ts +7 -0
- package/dist/services/theme-page-templates.js +53 -0
- package/dist/services/theme-schemas.d.ts +2 -0
- package/dist/services/theme-schemas.js +63 -0
- package/dist/services/token-auth.d.ts +10 -0
- package/dist/services/token-auth.js +64 -0
- package/dist/services/urls.d.ts +2 -0
- package/dist/services/urls.js +20 -0
- package/dist/services/validation.d.ts +24 -0
- package/dist/services/validation.js +158 -0
- package/dist/services/write-queue.d.ts +1 -0
- package/dist/services/write-queue.js +14 -0
- package/package.json +53 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 4,
|
|
3
|
+
"title": "Page not found — Granite CMS",
|
|
4
|
+
"type": "page",
|
|
5
|
+
"layout": "theme",
|
|
6
|
+
"published": true,
|
|
7
|
+
"sections": [
|
|
8
|
+
{
|
|
9
|
+
"id": "sec-hero",
|
|
10
|
+
"type": "hero",
|
|
11
|
+
"settings": {
|
|
12
|
+
"eyebrow": "404",
|
|
13
|
+
"heading": "This page didn't make it into the build.",
|
|
14
|
+
"subheading": "The page you're looking for doesn't exist, or has moved. Check the URL, or head back to solid ground."
|
|
15
|
+
},
|
|
16
|
+
"blocks": [
|
|
17
|
+
{ "id": "blk-home", "type": "button", "settings": { "label": "Back to home", "url": "/", "style": "primary" } },
|
|
18
|
+
{ "id": "blk-docs", "type": "button", "settings": { "label": "View the docs", "url": "/docs", "style": "secondary" } }
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 4,
|
|
3
|
+
"title": "Careers — Granite CMS",
|
|
4
|
+
"type": "page",
|
|
5
|
+
"layout": "theme",
|
|
6
|
+
"published": true,
|
|
7
|
+
"sections": [
|
|
8
|
+
{
|
|
9
|
+
"id": "sec-hero",
|
|
10
|
+
"type": "hero",
|
|
11
|
+
"settings": {
|
|
12
|
+
"eyebrow": "About / Careers",
|
|
13
|
+
"heading": "We're not hiring right now.",
|
|
14
|
+
"subheading": "Granite CMS is a small, deliberately lean team. When that changes, openings will show up here first."
|
|
15
|
+
},
|
|
16
|
+
"blocks": [
|
|
17
|
+
{ "id": "blk-careers-cta", "type": "button", "settings": { "label": "Back to About", "url": "/about", "style": "secondary" } }
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 4,
|
|
3
|
+
"title": "Team — Granite CMS",
|
|
4
|
+
"type": "page",
|
|
5
|
+
"layout": "theme",
|
|
6
|
+
"published": true,
|
|
7
|
+
"sections": [
|
|
8
|
+
{
|
|
9
|
+
"id": "sec-hero",
|
|
10
|
+
"type": "hero",
|
|
11
|
+
"settings": {
|
|
12
|
+
"eyebrow": "About / Team",
|
|
13
|
+
"heading": "A small team, on purpose.",
|
|
14
|
+
"subheading": "Granite CMS is maintained by a handful of people who'd rather ship a focused tool than manage a plugin marketplace."
|
|
15
|
+
},
|
|
16
|
+
"blocks": [
|
|
17
|
+
{ "id": "blk-team-cta", "type": "button", "settings": { "label": "Back to About", "url": "/about", "style": "secondary" } }
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 4,
|
|
3
|
+
"title": "About — Granite CMS",
|
|
4
|
+
"type": "page",
|
|
5
|
+
"layout": "theme",
|
|
6
|
+
"published": true,
|
|
7
|
+
"sections": [
|
|
8
|
+
{
|
|
9
|
+
"id": "sec-hero",
|
|
10
|
+
"type": "hero",
|
|
11
|
+
"settings": {
|
|
12
|
+
"eyebrow": "About",
|
|
13
|
+
"heading": "Built by people tired of fighting their CMS.",
|
|
14
|
+
"subheading": "Granite CMS started as an internal tool for an agency shipping a dozen client sites a year, and grew into something worth open-sourcing."
|
|
15
|
+
},
|
|
16
|
+
"blocks": [
|
|
17
|
+
{ "id": "blk-about-cta", "type": "button", "settings": { "label": "Meet the team", "url": "/about/team", "style": "primary" } }
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 4,
|
|
3
|
+
"title": "Deployment — Granite CMS",
|
|
4
|
+
"type": "page",
|
|
5
|
+
"layout": "theme",
|
|
6
|
+
"published": true,
|
|
7
|
+
"sections": [
|
|
8
|
+
{
|
|
9
|
+
"id": "sec-hero",
|
|
10
|
+
"type": "hero",
|
|
11
|
+
"settings": {
|
|
12
|
+
"eyebrow": "Docs / Deployment",
|
|
13
|
+
"heading": "Ship it anywhere Node.js runs.",
|
|
14
|
+
"subheading": "A Granite site is a process and a folder of files - a VPS, a container, or the client's own hosting all work the same way."
|
|
15
|
+
},
|
|
16
|
+
"blocks": [
|
|
17
|
+
{ "id": "blk-deploy-cta", "type": "button", "settings": { "label": "Back to Docs", "url": "/docs", "style": "secondary" } }
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 4,
|
|
3
|
+
"title": "Quickstart — Granite CMS",
|
|
4
|
+
"type": "page",
|
|
5
|
+
"layout": "theme",
|
|
6
|
+
"published": true,
|
|
7
|
+
"sections": [
|
|
8
|
+
{
|
|
9
|
+
"id": "sec-hero",
|
|
10
|
+
"type": "hero",
|
|
11
|
+
"settings": {
|
|
12
|
+
"eyebrow": "Docs / Getting Started / Quickstart",
|
|
13
|
+
"heading": "The five-minute version.",
|
|
14
|
+
"subheading": "Install, scaffold, model your first content type, and deploy. No detours."
|
|
15
|
+
},
|
|
16
|
+
"blocks": [
|
|
17
|
+
{ "id": "blk-quickstart-cta", "type": "button", "settings": { "label": "Back to Getting Started", "url": "/docs/getting-started", "style": "secondary" } }
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 4,
|
|
3
|
+
"title": "Getting Started — Granite CMS",
|
|
4
|
+
"type": "page",
|
|
5
|
+
"layout": "theme",
|
|
6
|
+
"published": true,
|
|
7
|
+
"sections": [
|
|
8
|
+
{
|
|
9
|
+
"id": "sec-hero",
|
|
10
|
+
"type": "hero",
|
|
11
|
+
"settings": {
|
|
12
|
+
"eyebrow": "Docs / Getting Started",
|
|
13
|
+
"heading": "Scaffold your first site in under five minutes.",
|
|
14
|
+
"subheading": "One command sets up a theme folder, structured content and a vhost ready to deploy.",
|
|
15
|
+
"codeTitle": "terminal",
|
|
16
|
+
"codeSnippet": "$ npx granite create acme-corp\n✔ Scaffolded theme, content and vhost\n✔ Structured content models ready"
|
|
17
|
+
},
|
|
18
|
+
"blocks": [
|
|
19
|
+
{ "id": "blk-gs-cta", "type": "button", "settings": { "label": "Quickstart", "url": "/docs/getting-started/quickstart", "style": "primary" } }
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 4,
|
|
3
|
+
"title": "Docs — Granite CMS",
|
|
4
|
+
"type": "page",
|
|
5
|
+
"layout": "theme",
|
|
6
|
+
"published": true,
|
|
7
|
+
"sections": [
|
|
8
|
+
{
|
|
9
|
+
"id": "sec-hero",
|
|
10
|
+
"type": "hero",
|
|
11
|
+
"settings": {
|
|
12
|
+
"eyebrow": "Docs",
|
|
13
|
+
"heading": "Everything you need to run Granite CMS.",
|
|
14
|
+
"subheading": "Setup, content modelling and deployment guides, kept short enough to actually read."
|
|
15
|
+
},
|
|
16
|
+
"blocks": [
|
|
17
|
+
{ "id": "blk-docs-cta", "type": "button", "settings": { "label": "Getting started", "url": "/docs/getting-started", "style": "primary" } }
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 4,
|
|
3
|
+
"title": "Granite CMS — Solid foundations for client sites",
|
|
4
|
+
"type": "page",
|
|
5
|
+
"layout": "theme",
|
|
6
|
+
"published": true,
|
|
7
|
+
"sections": [
|
|
8
|
+
{
|
|
9
|
+
"id": "sec-hero",
|
|
10
|
+
"type": "hero",
|
|
11
|
+
"settings": {
|
|
12
|
+
"eyebrow": "Open source · self-hosted · git-based",
|
|
13
|
+
"heading": "Solid foundations for client sites.",
|
|
14
|
+
"subheading": "Granite CMS is a lightweight, developer-first CMS built for agencies and freelancers who'd rather ship clean git-based sites than fight plugin bloat. Model your content, hand off a client-friendly admin, deploy anywhere.",
|
|
15
|
+
"codeTitle": "terminal",
|
|
16
|
+
"codeSnippet": "$ npx granite create acme-corp\n✔ Scaffolded theme, content and vhost\n✔ Structured content models ready\n\n$ granite deploy\n✔ Built 42 pages in 380ms\n✔ Synced to production — done."
|
|
17
|
+
},
|
|
18
|
+
"blocks": [
|
|
19
|
+
{ "id": "blk-hero-cta-primary", "type": "button", "settings": { "label": "Get started", "url": "/docs", "style": "primary" } },
|
|
20
|
+
{ "id": "blk-hero-cta-secondary", "type": "button", "settings": { "label": "View the docs", "url": "/docs", "style": "secondary" } }
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "sec-social-proof",
|
|
25
|
+
"type": "social-proof",
|
|
26
|
+
"settings": {
|
|
27
|
+
"label": "Trusted by agencies and developers shipping client sites every week"
|
|
28
|
+
},
|
|
29
|
+
"blocks": [
|
|
30
|
+
{ "id": "blk-logo-1", "type": "logo-mark", "settings": { "name": "NORTHWARD" } },
|
|
31
|
+
{ "id": "blk-logo-2", "type": "logo-mark", "settings": { "name": "STUDIO PALE" } },
|
|
32
|
+
{ "id": "blk-logo-3", "type": "logo-mark", "settings": { "name": "FIELDNOTE" } },
|
|
33
|
+
{ "id": "blk-logo-4", "type": "logo-mark", "settings": { "name": "GOODHOUSE" } },
|
|
34
|
+
{ "id": "blk-logo-5", "type": "logo-mark", "settings": { "name": "GREYWORKS" } }
|
|
35
|
+
]
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"id": "sec-features",
|
|
39
|
+
"type": "feature-grid",
|
|
40
|
+
"settings": {
|
|
41
|
+
"eyebrow": "Why Granite",
|
|
42
|
+
"heading": "Everything a client site needs. Nothing it doesn't.",
|
|
43
|
+
"subheading": "Granite is built around a small set of clean primitives instead of a decade of accumulated core and plugin cruft."
|
|
44
|
+
},
|
|
45
|
+
"blocks": [
|
|
46
|
+
{ "id": "blk-feature-1", "type": "feature-card", "settings": { "icon": "structure", "heading": "Structured content modelling", "description": "Define content types with plain JSON Schema — no proprietary field builder, no black-box data model. What you write is what gets validated." } },
|
|
47
|
+
{ "id": "blk-feature-2", "type": "feature-card", "settings": { "icon": "git", "heading": "Git-based workflows", "description": "Content and theme live in git alongside your code. Branch a client's homepage redesign, review it in a PR, merge it like anything else you ship." } },
|
|
48
|
+
{ "id": "blk-feature-3", "type": "feature-card", "settings": { "icon": "bolt", "heading": "Blazing performance", "description": "No ORM, no plugin queue, no admin-panel tax on the front end. Pages render in milliseconds because there's nothing extra in the way." } },
|
|
49
|
+
{ "id": "blk-feature-4", "type": "feature-card", "settings": { "icon": "block", "heading": "No plugin bloat", "description": "There's no plugin marketplace to get lost in. Granite ships with exactly what a client site needs, and nothing you'll spend a weekend patching." } },
|
|
50
|
+
{ "id": "blk-feature-5", "type": "feature-card", "settings": { "icon": "admin", "heading": "Simple, client-friendly admin", "description": "Hand off access without a training session. Clients edit their own copy and images through a focused admin UI — no theme settings to break." } },
|
|
51
|
+
{ "id": "blk-feature-6", "type": "feature-card", "settings": { "icon": "portable", "heading": "Fully self-hosted and portable", "description": "Run it on your own infrastructure or the client's. Every site is a folder of files — move it, back it up, or migrate it without asking permission." } }
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"id": "sec-how-it-works",
|
|
56
|
+
"type": "how-it-works",
|
|
57
|
+
"settings": {
|
|
58
|
+
"eyebrow": "How it works",
|
|
59
|
+
"heading": "From new client to live site in three steps",
|
|
60
|
+
"subheading": "No scaffolding to hand-roll and no framework decisions to relitigate for every new engagement."
|
|
61
|
+
},
|
|
62
|
+
"blocks": [
|
|
63
|
+
{ "id": "blk-step-1", "type": "step-card", "settings": { "number": "01", "heading": "Scaffold a site", "description": "Run one command to generate a new site: theme folder, content structure and a vhost ready to deploy. No boilerplate to copy from your last project." } },
|
|
64
|
+
{ "id": "blk-step-2", "type": "step-card", "settings": { "number": "02", "heading": "Model your content", "description": "Define sections and blocks as plain templates with a JSON Schema for their settings. Content authors get a clean admin; you get a system you actually understand." } },
|
|
65
|
+
{ "id": "blk-step-3", "type": "step-card", "settings": { "number": "03", "heading": "Deploy anywhere", "description": "Granite is just a process and a folder of files. Ship it to a VPS, a container, or the client's own hosting — there's no vendor lock-in." } }
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"id": "sec-comparison",
|
|
70
|
+
"type": "comparison",
|
|
71
|
+
"settings": {
|
|
72
|
+
"eyebrow": "Granite CMS vs. traditional CMS platforms",
|
|
73
|
+
"heading": "Built lean, on purpose",
|
|
74
|
+
"subheading": "A side-by-side look at what changes when you drop the plugin ecosystem and two decades of legacy core.",
|
|
75
|
+
"criteriaLabel": "Criteria",
|
|
76
|
+
"graniteLabel": "Granite CMS",
|
|
77
|
+
"traditionalLabel": "Traditional CMS"
|
|
78
|
+
},
|
|
79
|
+
"blocks": [
|
|
80
|
+
{ "id": "blk-row-1", "type": "comparison-row", "settings": { "criteria": "Page load speed", "granite": "Sub-100ms, no plugin overhead", "traditional": "Often 1–3s under plugin load" } },
|
|
81
|
+
{ "id": "blk-row-2", "type": "comparison-row", "settings": { "criteria": "Security surface", "granite": "No third-party plugin ecosystem to patch", "traditional": "Large attack surface from plugins & extensions" } },
|
|
82
|
+
{ "id": "blk-row-3", "type": "comparison-row", "settings": { "criteria": "Maintenance overhead", "granite": "One lightweight core, occasional bump", "traditional": "Core, theme and dozens of plugins to keep current" } },
|
|
83
|
+
{ "id": "blk-row-4", "type": "comparison-row", "settings": { "criteria": "Portability", "granite": "Just files — move or self-host freely", "traditional": "Database-coupled, often host-locked" } }
|
|
84
|
+
]
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"id": "sec-testimonials",
|
|
88
|
+
"type": "testimonials",
|
|
89
|
+
"settings": {
|
|
90
|
+
"eyebrow": "From the field",
|
|
91
|
+
"heading": "What agencies say after switching",
|
|
92
|
+
"subheading": "Fewer support emails, cleaner handoffs, and a stack their whole team can reason about."
|
|
93
|
+
},
|
|
94
|
+
"blocks": [
|
|
95
|
+
{ "id": "blk-testimonial-1", "type": "testimonial-card", "settings": { "quote": "We used to budget half a day per client site just for plugin updates and conflicts. With Granite that's gone entirely — content lives in git, and deploys are boring in the best way.", "name": "Maya Okonkwo", "role": "Founder, Fieldnote Studio", "initials": "MO" } },
|
|
96
|
+
{ "id": "blk-testimonial-2", "type": "testimonial-card", "settings": { "quote": "Handing a finished site to a client used to mean signing them up for a support contract. Now we hand over an admin URL and a five-minute walkthrough. They edit their own copy, and we stop getting 'can you fix a typo' emails.", "name": "Tom Bregman", "role": "Lead Developer, Northward Digital", "initials": "TB" } }
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"id": "sec-pricing",
|
|
101
|
+
"type": "pricing",
|
|
102
|
+
"settings": {
|
|
103
|
+
"eyebrow": "Pricing",
|
|
104
|
+
"heading": "Plans that scale with your client roster",
|
|
105
|
+
"subheading": "Self-host for free, or let us handle updates and multi-site management for you."
|
|
106
|
+
},
|
|
107
|
+
"blocks": [
|
|
108
|
+
{
|
|
109
|
+
"id": "blk-tier-solo",
|
|
110
|
+
"type": "pricing-tier",
|
|
111
|
+
"settings": {
|
|
112
|
+
"name": "Solo",
|
|
113
|
+
"price": "$0",
|
|
114
|
+
"period": "forever, self-hosted",
|
|
115
|
+
"description": "For freelancers running a handful of client sites.",
|
|
116
|
+
"features": ["Unlimited self-hosted sites", "Structured content & git workflows", "Community support", "MIT-licensed core"],
|
|
117
|
+
"ctaLabel": "Get started",
|
|
118
|
+
"ctaUrl": "/docs",
|
|
119
|
+
"highlighted": false
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"id": "blk-tier-agency",
|
|
124
|
+
"type": "pricing-tier",
|
|
125
|
+
"settings": {
|
|
126
|
+
"name": "Agency",
|
|
127
|
+
"price": "$39",
|
|
128
|
+
"period": "per month",
|
|
129
|
+
"description": "For agencies managing a growing roster of client sites.",
|
|
130
|
+
"features": ["Everything in Solo", "Managed updates & security patches", "Multi-site admin dashboard", "Priority email support", "Client access management"],
|
|
131
|
+
"ctaLabel": "Start free trial",
|
|
132
|
+
"ctaUrl": "/docs",
|
|
133
|
+
"highlighted": true
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"id": "blk-tier-enterprise",
|
|
138
|
+
"type": "pricing-tier",
|
|
139
|
+
"settings": {
|
|
140
|
+
"name": "Enterprise",
|
|
141
|
+
"price": "Custom",
|
|
142
|
+
"period": "talk to us",
|
|
143
|
+
"description": "For teams with compliance, scale or white-label needs.",
|
|
144
|
+
"features": ["Everything in Agency", "SSO & audit logging", "White-label admin", "Dedicated support channel", "Custom SLAs"],
|
|
145
|
+
"ctaLabel": "Contact sales",
|
|
146
|
+
"ctaUrl": "/contact",
|
|
147
|
+
"highlighted": false
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
]
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"id": "sec-faq",
|
|
154
|
+
"type": "faq",
|
|
155
|
+
"settings": {
|
|
156
|
+
"eyebrow": "FAQ",
|
|
157
|
+
"heading": "Questions agencies ask before switching",
|
|
158
|
+
"subheading": "If you don't see yours here, the docs cover the rest."
|
|
159
|
+
},
|
|
160
|
+
"blocks": [
|
|
161
|
+
{ "id": "blk-faq-1", "type": "faq-item", "settings": { "question": "Do I need to host it myself?", "answer": "No — Granite runs anywhere Node.js does, including most managed platforms, but self-hosting is fully supported and often the whole point. Bring your own VPS, container platform, or hand it to your client's existing host." } },
|
|
162
|
+
{ "id": "blk-faq-2", "type": "faq-item", "settings": { "question": "Can I migrate an existing WordPress site?", "answer": "Yes. Granite includes a WordPress import script that pulls posts, pages and media into structured content JSON. Most agencies remap templates by hand afterward, since a Granite theme has a much smaller surface than a WordPress theme." } },
|
|
163
|
+
{ "id": "blk-faq-3", "type": "faq-item", "settings": { "question": "How do clients access their site?", "answer": "Each site ships with a lightweight, focused admin UI scoped to content — no theme settings, no plugin screens. You control what's editable per content type, so clients can't break the layout." } },
|
|
164
|
+
{ "id": "blk-faq-4", "type": "faq-item", "settings": { "question": "How do updates work?", "answer": "Granite has one small core and no plugin ecosystem to keep in sync, so updates are a single version bump with a changelog you can actually read in a minute." } },
|
|
165
|
+
{ "id": "blk-faq-5", "type": "faq-item", "settings": { "question": "What if I need help?", "answer": "Solo and Agency plans include community and priority support respectively; Enterprise gets a dedicated support channel. The docs also cover the vast majority of setup and theming questions directly." } }
|
|
166
|
+
]
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
"id": "sec-cta",
|
|
170
|
+
"type": "cta-banner",
|
|
171
|
+
"settings": {
|
|
172
|
+
"heading": "Ready to build on solid ground?",
|
|
173
|
+
"subheading": "Scaffold your first Granite site in under five minutes. No credit card, no plugin marketplace, no legacy baggage."
|
|
174
|
+
},
|
|
175
|
+
"blocks": [
|
|
176
|
+
{ "id": "blk-cta-primary", "type": "button", "settings": { "label": "Get started", "url": "/docs", "style": "primary" } },
|
|
177
|
+
{ "id": "blk-cta-secondary", "type": "button", "settings": { "label": "Talk to us", "url": "/contact", "style": "on-dark" } }
|
|
178
|
+
]
|
|
179
|
+
}
|
|
180
|
+
]
|
|
181
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Renamed to .dockerignore by scaffoldSite() (same trick as this
|
|
2
|
+
# template's own "gitignore" -> ".gitignore"). Deliberately does NOT
|
|
3
|
+
# exclude .git - the site root must be a real git repository at
|
|
4
|
+
# runtime (services/startup-checks.ts), so .git has to reach the image.
|
|
5
|
+
vhost/node_modules
|
|
6
|
+
vhost/data
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
node_modules/
|
|
2
|
+
|
|
3
|
+
# Search index (rebuilt on demand via POST /v1/search/rebuild, never committed)
|
|
4
|
+
data/
|
|
5
|
+
*.sqlite
|
|
6
|
+
*.sqlite3
|
|
7
|
+
|
|
8
|
+
# Uploaded media (constraint 2: binary uploads committed forever is
|
|
9
|
+
# unbounded repo bloat with no diffing or expiry benefit - copied
|
|
10
|
+
# separately when moving a site to a new server, never git-tracked)
|
|
11
|
+
/media/
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
var toggle = document.querySelector('[data-nav-toggle]');
|
|
3
|
+
var mobileNav = document.querySelector('[data-mobile-nav]');
|
|
4
|
+
|
|
5
|
+
if (toggle && mobileNav) {
|
|
6
|
+
toggle.addEventListener('click', function () {
|
|
7
|
+
var isOpen = mobileNav.classList.toggle('is-open');
|
|
8
|
+
toggle.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
mobileNav.querySelectorAll('a').forEach(function (link) {
|
|
12
|
+
link.addEventListener('click', function () {
|
|
13
|
+
mobileNav.classList.remove('is-open');
|
|
14
|
+
toggle.setAttribute('aria-expanded', 'false');
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
var header = document.querySelector('[data-site-header]');
|
|
20
|
+
if (header) {
|
|
21
|
+
var onScroll = function () {
|
|
22
|
+
header.classList.toggle('is-scrolled', window.scrollY > 8);
|
|
23
|
+
};
|
|
24
|
+
onScroll();
|
|
25
|
+
window.addEventListener('scroll', onScroll, { passive: true });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
var revealTargets = document.querySelectorAll('.reveal');
|
|
29
|
+
if ('IntersectionObserver' in window && revealTargets.length) {
|
|
30
|
+
var observer = new IntersectionObserver(
|
|
31
|
+
function (entries) {
|
|
32
|
+
entries.forEach(function (entry) {
|
|
33
|
+
if (entry.isIntersecting) {
|
|
34
|
+
entry.target.classList.add('is-visible');
|
|
35
|
+
observer.unobserve(entry.target);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
},
|
|
39
|
+
{ threshold: 0.12, rootMargin: '0px 0px -40px 0px' }
|
|
40
|
+
);
|
|
41
|
+
revealTargets.forEach(function (el) {
|
|
42
|
+
observer.observe(el);
|
|
43
|
+
});
|
|
44
|
+
} else {
|
|
45
|
+
revealTargets.forEach(function (el) {
|
|
46
|
+
el.classList.add('is-visible');
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
})();
|