@gradial/aci 0.1.46 → 0.1.47

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.
Files changed (56) hide show
  1. package/README.md +4 -4
  2. package/dist/astro/error-page.d.ts +56 -0
  3. package/dist/astro/error-page.js +79 -0
  4. package/dist/astro/index.d.ts +4 -0
  5. package/dist/astro/index.js +9 -0
  6. package/dist/cli/emit-error-pages.d.mts +39 -0
  7. package/dist/cli/emit-error-pages.mjs +402 -0
  8. package/dist/content/default-error-page-html.d.ts +2 -0
  9. package/dist/content/default-error-page-html.js +6 -0
  10. package/dist/content/default-error-page.d.ts +23 -0
  11. package/dist/content/default-error-page.js +34 -0
  12. package/dist/content/error-page-kind.d.ts +57 -0
  13. package/dist/content/error-page-kind.js +106 -0
  14. package/dist/content/error-pages.d.ts +88 -0
  15. package/dist/content/error-pages.js +120 -0
  16. package/dist/content/index.d.ts +2 -0
  17. package/dist/content/index.js +2 -0
  18. package/dist/content/types.d.ts +12 -0
  19. package/dist/next/config.js +17 -0
  20. package/dist/next/error-page-instrumentation.d.ts +23 -0
  21. package/dist/next/error-page-instrumentation.js +36 -0
  22. package/dist/next/error-page-marker.d.ts +11 -0
  23. package/dist/next/error-page-marker.js +20 -0
  24. package/dist/next/error-pages.d.ts +52 -0
  25. package/dist/next/error-pages.js +94 -0
  26. package/dist/next/error-seat-payload.d.ts +33 -0
  27. package/dist/next/error-seat-payload.js +143 -0
  28. package/dist/next/error-seat.d.ts +57 -0
  29. package/dist/next/error-seat.js +83 -0
  30. package/dist/next/index.d.ts +4 -0
  31. package/dist/next/index.js +8 -0
  32. package/package.json +14 -8
  33. package/src/cli/emit-error-pages.mjs +424 -0
  34. package/templates/astro/template/package.json.tmpl +1 -1
  35. package/templates/astro/template/src/aci/error-page-instrumentation.mjs +33 -0
  36. package/templates/astro/template/src/pages/404.astro +54 -0
  37. package/templates/astro/template/src/pages/500.astro +53 -0
  38. package/templates/astro/template/src/pages/[...slug].astro +15 -2
  39. package/templates/common/.agents/skills/authoring/SKILL.md +71 -0
  40. package/templates/common/.content/config/robots.txt +4 -0
  41. package/templates/common/.content/config/site.json.tmpl +4 -0
  42. package/templates/common/.content/pages/404/_index.json +31 -0
  43. package/templates/common/.content/pages/error/_index.json +31 -0
  44. package/templates/common/.content/schemas/site.schema.json +9 -0
  45. package/templates/common/starter-content/.content/config/robots.txt +2 -0
  46. package/templates/common/starter-content/.content/config/site.json +4 -0
  47. package/templates/common/starter-content/.content/pages/404/_index.json +31 -0
  48. package/templates/common/starter-content/.content/pages/about/_index.json +3 -6
  49. package/templates/common/starter-content/.content/pages/error/_index.json +31 -0
  50. package/templates/common/starter-content/.content/pages/home/_index.json +10 -19
  51. package/templates/common/starter-content/.content/schemas/site.schema.json +9 -0
  52. package/templates/nextjs/template/package.json.tmpl +1 -1
  53. package/templates/nextjs/template/src/aci/error-page-instrumentation.d.mts +4 -0
  54. package/templates/nextjs/template/src/aci/error-page-instrumentation.mjs +38 -0
  55. package/templates/nextjs/template/src/app/error.tsx +18 -0
  56. package/templates/nextjs/template/src/app/not-found.tsx +13 -0
@@ -0,0 +1,4 @@
1
+ User-agent: *
2
+ Allow: /
3
+ Disallow: /404/
4
+ Disallow: /error/
@@ -6,6 +6,10 @@
6
6
  "domain": "localhost",
7
7
  "defaultLocale": "en-us",
8
8
  "locales": ["en-us"],
9
+ "errorPages": {
10
+ "notFound": "/404/",
11
+ "catchAll": "/error/"
12
+ },
9
13
  "overlayResolution": ["locale"],
10
14
  "brandHref": "/",
11
15
  "seo": {
@@ -0,0 +1,31 @@
1
+ {
2
+ "$type": "page",
3
+ "id": "meridian-not-found",
4
+ "status": "published",
5
+ "layout": "default",
6
+ "metadata": {
7
+ "title": "Page not found — Meridian",
8
+ "description": "The page you are looking for does not exist.",
9
+ "sitemap": { "visible": false }
10
+ },
11
+ "regions": {
12
+ "main": [
13
+ {
14
+ "id": "not-found-hero",
15
+ "component": "home_hero",
16
+ "props": {
17
+ "eyebrow": "404",
18
+ "headline": "This page drifted out of orbit.",
19
+ "description": "The page you are looking for does not exist or has moved. Check the address, or head back to the homepage.",
20
+ "ctaLabel": "Back to home",
21
+ "ctaHref": "/",
22
+ "image": {
23
+ "$type": "dam.assetRef",
24
+ "assetId": "ast_site_home_hero",
25
+ "alt": "Light abstract background with satellite constellation"
26
+ }
27
+ }
28
+ }
29
+ ]
30
+ }
31
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "$type": "page",
3
+ "id": "meridian-error",
4
+ "status": "published",
5
+ "layout": "default",
6
+ "metadata": {
7
+ "title": "Something went wrong — Meridian",
8
+ "description": "An unexpected error occurred while serving this page.",
9
+ "sitemap": { "visible": false }
10
+ },
11
+ "regions": {
12
+ "main": [
13
+ {
14
+ "id": "error-hero",
15
+ "component": "home_hero",
16
+ "props": {
17
+ "eyebrow": "Temporary interruption",
18
+ "headline": "Something went wrong on our end.",
19
+ "description": "An unexpected error occurred while serving this page. Please try again in a moment, or head back to the homepage.",
20
+ "ctaLabel": "Back to home",
21
+ "ctaHref": "/",
22
+ "image": {
23
+ "$type": "dam.assetRef",
24
+ "assetId": "ast_site_home_hero",
25
+ "alt": "Light abstract background with satellite constellation"
26
+ }
27
+ }
28
+ }
29
+ ]
30
+ }
31
+ }
@@ -7,6 +7,15 @@
7
7
  "additionalProperties": true,
8
8
  "properties": {
9
9
  "$type": { "const": "site" },
10
+ "errorPages": {
11
+ "type": "object",
12
+ "required": ["notFound", "catchAll"],
13
+ "additionalProperties": false,
14
+ "properties": {
15
+ "notFound": { "type": "string", "pattern": "^/(?:[A-Za-z0-9._~-]+/)+$" },
16
+ "catchAll": { "type": "string", "pattern": "^/(?:[A-Za-z0-9._~-]+/)+$" }
17
+ }
18
+ },
10
19
  "id": { "type": "string", "minLength": 1 },
11
20
  "status": { "type": "string", "minLength": 1 },
12
21
  "title": { "type": "string", "minLength": 1 },
@@ -1,2 +1,4 @@
1
1
  User-agent: *
2
2
  Allow: /
3
+ Disallow: /404/
4
+ Disallow: /error/
@@ -6,6 +6,10 @@
6
6
  "domain": "www.meridian.local",
7
7
  "defaultLocale": "en-us",
8
8
  "locales": ["en-us"],
9
+ "errorPages": {
10
+ "notFound": "/404/",
11
+ "catchAll": "/error/"
12
+ },
9
13
  "overlayResolution": ["locale", "audience"],
10
14
  "brandHref": "/",
11
15
  "brandLogo": {
@@ -0,0 +1,31 @@
1
+ {
2
+ "$type": "page",
3
+ "id": "meridian-not-found",
4
+ "status": "published",
5
+ "layout": "default",
6
+ "metadata": {
7
+ "title": "Page not found — Meridian",
8
+ "description": "The page you are looking for does not exist.",
9
+ "sitemap": { "visible": false }
10
+ },
11
+ "regions": {
12
+ "main": [
13
+ {
14
+ "id": "not-found-hero",
15
+ "component": "home_hero",
16
+ "props": {
17
+ "eyebrow": "404",
18
+ "headline": "This page drifted out of orbit.",
19
+ "description": "The page you are looking for does not exist or has moved. Check the address, or head back to the homepage.",
20
+ "ctaLabel": "Back to home",
21
+ "ctaHref": "/",
22
+ "image": {
23
+ "$type": "dam.assetRef",
24
+ "assetId": "ast_site_home_hero",
25
+ "alt": "Light abstract background with satellite constellation"
26
+ }
27
+ }
28
+ }
29
+ ]
30
+ }
31
+ }
@@ -24,8 +24,7 @@
24
24
  "assetId": "ast_site_about_hero",
25
25
  "alt": "Meridian network coverage map with soft gradient"
26
26
  }
27
- },
28
- "$type": "component"
27
+ }
29
28
  },
30
29
  {
31
30
  "id": "about-actions",
@@ -42,12 +41,10 @@
42
41
  "variant": "primary",
43
42
  "icon": "arrow_forward",
44
43
  "iconPosition": "after"
45
- },
46
- "$type": "component"
44
+ }
47
45
  }
48
46
  ]
49
- },
50
- "$type": "component"
47
+ }
51
48
  }
52
49
  ]
53
50
  }
@@ -0,0 +1,31 @@
1
+ {
2
+ "$type": "page",
3
+ "id": "meridian-error",
4
+ "status": "published",
5
+ "layout": "default",
6
+ "metadata": {
7
+ "title": "Something went wrong — Meridian",
8
+ "description": "An unexpected error occurred while serving this page.",
9
+ "sitemap": { "visible": false }
10
+ },
11
+ "regions": {
12
+ "main": [
13
+ {
14
+ "id": "error-hero",
15
+ "component": "home_hero",
16
+ "props": {
17
+ "eyebrow": "Temporary interruption",
18
+ "headline": "Something went wrong on our end.",
19
+ "description": "An unexpected error occurred while serving this page. Please try again in a moment, or head back to the homepage.",
20
+ "ctaLabel": "Back to home",
21
+ "ctaHref": "/",
22
+ "image": {
23
+ "$type": "dam.assetRef",
24
+ "assetId": "ast_site_home_hero",
25
+ "alt": "Light abstract background with satellite constellation"
26
+ }
27
+ }
28
+ }
29
+ ]
30
+ }
31
+ }
@@ -4,7 +4,7 @@
4
4
  "status": "published",
5
5
  "layout": "default",
6
6
  "metadata": {
7
- "title": "Meridian — Global Satellite Internet",
7
+ "title": "Meridian \u2014 Global Satellite Internet",
8
8
  "description": "Connect from anywhere on Earth. Low-latency satellite internet for homes, businesses, and beyond.",
9
9
  "canonical": "https://www.meridian.local/"
10
10
  },
@@ -24,8 +24,7 @@
24
24
  "assetId": "ast_site_home_hero",
25
25
  "alt": "Light abstract hero background with satellite constellation"
26
26
  }
27
- },
28
- "$type": "component"
27
+ }
29
28
  },
30
29
  {
31
30
  "id": "why-meridian",
@@ -41,8 +40,7 @@
41
40
  "icon": "globe",
42
41
  "title": "Global coverage",
43
42
  "description": "A constellation of low-orbit satellites keeps you connected across continents, oceans, and remote terrain."
44
- },
45
- "$type": "component"
43
+ }
46
44
  },
47
45
  {
48
46
  "id": "low-latency",
@@ -51,8 +49,7 @@
51
49
  "icon": "speed",
52
50
  "title": "Low latency",
53
51
  "description": "Sub-50ms latency means video calls, gaming, and real-time control feel local, even in the middle of nowhere."
54
- },
55
- "$type": "component"
52
+ }
56
53
  },
57
54
  {
58
55
  "id": "easy-setup",
@@ -61,12 +58,10 @@
61
58
  "icon": "setup",
62
59
  "title": "Easy setup",
63
60
  "description": "A compact terminal and a phone app. Point at the sky, power on, and get online in minutes."
64
- },
65
- "$type": "component"
61
+ }
66
62
  }
67
63
  ]
68
- },
69
- "$type": "component"
64
+ }
70
65
  },
71
66
  {
72
67
  "id": "stats",
@@ -94,8 +89,7 @@
94
89
  "suffix": ""
95
90
  }
96
91
  ]
97
- },
98
- "$type": "component"
92
+ }
99
93
  },
100
94
  {
101
95
  "id": "cta",
@@ -113,8 +107,7 @@
113
107
  "variant": "primary",
114
108
  "icon": "arrow_forward",
115
109
  "iconPosition": "after"
116
- },
117
- "$type": "component"
110
+ }
118
111
  },
119
112
  {
120
113
  "id": "cta-secondary",
@@ -125,12 +118,10 @@
125
118
  "variant": "outline",
126
119
  "icon": "arrow_forward",
127
120
  "iconPosition": "after"
128
- },
129
- "$type": "component"
121
+ }
130
122
  }
131
123
  ]
132
- },
133
- "$type": "component"
124
+ }
134
125
  }
135
126
  ]
136
127
  }
@@ -7,6 +7,15 @@
7
7
  "additionalProperties": true,
8
8
  "properties": {
9
9
  "$type": { "const": "site" },
10
+ "errorPages": {
11
+ "type": "object",
12
+ "required": ["notFound", "catchAll"],
13
+ "additionalProperties": false,
14
+ "properties": {
15
+ "notFound": { "type": "string", "pattern": "^/(?:[A-Za-z0-9._~-]+/)+$" },
16
+ "catchAll": { "type": "string", "pattern": "^/(?:[A-Za-z0-9._~-]+/)+$" }
17
+ }
18
+ },
10
19
  "id": { "type": "string", "minLength": 1 },
11
20
  "status": { "type": "string", "minLength": 1 },
12
21
  "title": { "type": "string", "minLength": 1 },
@@ -5,7 +5,7 @@
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "ACI_CONTENT_PROVIDER=file next dev -H 0.0.0.0",
8
- "build": "next build",
8
+ "build": "node ./node_modules/@gradial/aci/src/cli/emit-error-pages.mjs prepare && next build && node ./node_modules/@gradial/aci/src/cli/emit-error-pages.mjs emit",
9
9
  "preview": "next start -H 0.0.0.0",
10
10
  "typecheck": "tsc --noEmit",
11
11
  "test": "node --import tsx --test tests/**/*.test.ts",
@@ -0,0 +1,4 @@
1
+ // Type surface for the customer-owned policy module beside this file
2
+ // (authorable-error-pages D-15). Edit the .mjs; this declaration only needs
3
+ // touching if you change the function's signature.
4
+ export declare function pushErrorPageView(pageType: 'not_found' | 'error'): void;
@@ -0,0 +1,38 @@
1
+ // Error-page analytics policy — THIS FILE IS YOURS (customer-owned;
2
+ // code-organization R-14 / authorable-error-pages D-15). The ACI SDK owns
3
+ // the delivery mechanism (when this runs, serialization, the
4
+ // data-aci-error-page marker); this file owns WHAT is pushed.
5
+ //
6
+ // Contract:
7
+ // - pushErrorPageView MUST stay self-contained: browser globals only — no
8
+ // imports, no closed-over identifiers. The Astro seats and the 500.html
9
+ // emitter execute it STRINGIFIED via toString(), so anything outside the
10
+ // function body is lost.
11
+ // - Emptying the body to a no-op disables error-page analytics on every
12
+ // surface (Next seats, Astro seats, 500.html) — the sanctioned
13
+ // alternative to GTM-container-side suppression.
14
+ // - Plain .mjs on purpose: it is consumed verbatim, never transpiled.
15
+ //
16
+ // 'use client' (Next only, inert elsewhere): the not-found seat is a server
17
+ // component and can only hand a function to the client-side instrumentation
18
+ // component as a client reference.
19
+ 'use client';
20
+
21
+ /**
22
+ * Pushes one `page_view` event per error-surface view (D-14 default
23
+ * payload). `page_path` is the visitor's requested path, so 404 reports
24
+ * double as a broken-link inventory.
25
+ *
26
+ * @param {'not_found' | 'error'} pageType
27
+ */
28
+ export function pushErrorPageView(pageType) {
29
+ window.dataLayer = window.dataLayer || [];
30
+ window.dataLayer.push({
31
+ event: 'page_view',
32
+ page_type: pageType,
33
+ page_path: window.location.pathname,
34
+ page_location: window.location.href,
35
+ page_referrer: document.referrer || '(direct)',
36
+ page_title: document.title,
37
+ });
38
+ }
@@ -0,0 +1,18 @@
1
+ 'use client';
2
+
3
+ import { ErrorSeat } from '@gradial/aci/next/error-seat';
4
+ import { registry } from '@/cms/registry';
5
+ import { pushErrorPageView } from '../aci/error-page-instrumentation.mjs';
6
+
7
+ // Next's app-error seat (client-only by contract). ErrorSeat renders the
8
+ // page bound by site.json#errorPages.catchAll from content serialized into
9
+ // the bundle at build time — nothing is fetched while the app is failing.
10
+ // The analytics push comes from the site-owned policy module (D-15):
11
+ // edit src/aci/error-page-instrumentation.mjs to customize or disable it.
12
+ //
13
+ // Coverage: render errors below the root layout. NOT covered here: root
14
+ // layout errors (global-error), middleware failures, and platform 5xx —
15
+ // those are served the static public/500.html emitted by the build.
16
+ export default function AppError({ error }: { error: Error & { digest?: string } }) {
17
+ return <ErrorSeat registry={registry} error={error} pushErrorPageView={pushErrorPageView} />;
18
+ }
@@ -0,0 +1,13 @@
1
+ import { createNotFound } from '@gradial/aci/next';
2
+ import { registry } from '@/cms/registry';
3
+ import { pushErrorPageView } from '../aci/error-page-instrumentation.mjs';
4
+
5
+ // Next's native not-found seat: the SDK catch-all invokes notFound() on
6
+ // missing content, and this renders the page bound by
7
+ // site.json#errorPages.notFound with a real HTTP 404. If that page is itself
8
+ // missing at request time, the SDK falls back to its shipped default inline —
9
+ // this seat never recurses and never throws.
10
+ //
11
+ // The analytics push comes from the site-owned policy module (D-15):
12
+ // edit src/aci/error-page-instrumentation.mjs to customize or disable it.
13
+ export default createNotFound(registry, { pushErrorPageView });