@gradial/aci 0.1.50 → 0.1.51-ssr.2
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/CHANGELOG.md +0 -21
- package/README.md +13 -20
- package/dist/astro/assets.d.ts +6 -6
- package/dist/astro/assets.js +6 -6
- package/dist/astro/index.d.ts +0 -2
- package/dist/astro/index.js +0 -4
- package/dist/cli/emit-error-pages.mjs +0 -1
- package/dist/cli/verify-next-cdn-routes.mjs +3 -4
- package/dist/collect/aci.js +1 -1
- package/dist/collect/aci.js.sha256 +1 -1
- package/dist/collect/batcher.d.ts +0 -6
- package/dist/collect/index.js +0 -9
- package/dist/collect/webvitals.d.ts +0 -3
- package/dist/collect/webvitals.js +11 -21
- package/dist/content/cache.d.ts +1 -9
- package/dist/content/cache.js +2 -37
- package/dist/content/error-pages.d.ts +1 -2
- package/dist/content/index.d.ts +0 -1
- package/dist/content/index.js +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/internal/domain/edge/identity.d.ts +14 -0
- package/dist/internal/domain/edge/identity.js +214 -0
- package/dist/internal/domain/edge/index.d.ts +4 -0
- package/dist/internal/domain/edge/index.js +6 -0
- package/dist/internal/domain/edge/personalization-core.d.ts +24 -0
- package/dist/{edge → internal/domain/edge}/personalization-core.js +165 -64
- package/dist/internal/domain/edge/record/codec.d.ts +71 -0
- package/dist/internal/domain/edge/record/codec.js +401 -0
- package/dist/internal/domain/edge/resolve.d.ts +2 -0
- package/dist/internal/domain/edge/resolve.js +76 -0
- package/dist/{next/personalization-host.d.ts → internal/domain/edge/types.d.ts} +110 -63
- package/dist/internal/domain/edge/types.js +7 -0
- package/dist/internal/platform/collectionstore/errors.d.ts +5 -0
- package/dist/internal/platform/collectionstore/errors.js +7 -0
- package/dist/next/config.d.ts +0 -8
- package/dist/next/config.js +3 -78
- package/dist/next/error-pages.d.ts +2 -3
- package/dist/next/error-pages.js +5 -5
- package/dist/next/error-seat.d.ts +2 -3
- package/dist/next/index.d.ts +2 -2
- package/dist/next/index.js +1 -2
- package/dist/next/page.d.ts +3 -13
- package/dist/next/page.js +39 -51
- package/dist/next/server.d.ts +12 -32
- package/dist/next/server.js +66 -328
- package/dist/providers/object.d.ts +24 -0
- package/dist/providers/object.js +105 -0
- package/dist/providers/vercel-object-reader.d.ts +20 -0
- package/dist/providers/vercel-object-reader.js +45 -0
- package/dist/testing/conformance/checks.d.ts +1 -1
- package/dist/testing/conformance/checks.js +14 -152
- package/dist/testing/conformance/index.d.ts +1 -1
- package/dist/testing/conformance/index.js +1 -1
- package/dist/testing/conformance/preset.js +1 -1
- package/dist/testing/conformance/types.d.ts +1 -1
- package/dist/types/config.d.ts +0 -4
- package/dist/types/index.d.ts +0 -2
- package/dist/types/index.js +0 -2
- package/dist/types/page.d.ts +0 -10
- package/package.json +11 -35
- package/src/cli/emit-error-pages.mjs +0 -1
- package/src/cli/verify-next-cdn-routes.mjs +8 -11
- package/src/types/config.ts +0 -5
- package/src/types/index.ts +0 -2
- package/src/types/page.ts +0 -11
- package/templates/astro/template/.aci.yaml.tmpl +0 -11
- package/templates/common/.agents/skills/aci/SKILL.md +8 -9
- package/templates/common/.agents/skills/authoring/SKILL.md +3 -4
- package/templates/common/.agents/skills/authoring/references/block-registry.md +13 -36
- package/templates/common/.agents/skills/authoring/references/contracts.md +10 -17
- package/templates/common/.agents/skills/authoring/references/repo-structure.md +2 -2
- package/templates/common/.agents/skills/authoring/references/sdk-server-functions.md +45 -95
- package/templates/common/.agents/skills/migration/references/canon-migration.md +17 -37
- package/templates/nextjs/template/.aci.yaml.tmpl +0 -11
- package/templates/nextjs/template/README.md.tmpl +0 -1
- package/templates/nextjs/template/src/app/[[...slug]]/page.tsx +1 -1
- package/dist/collect/deviceclass.d.ts +0 -12
- package/dist/collect/deviceclass.js +0 -27
- package/dist/content/assets.d.ts +0 -18
- package/dist/content/assets.js +0 -66
- package/dist/edge/personalization-core.d.ts +0 -11
- package/dist/internal/render-proof.d.ts +0 -1
- package/dist/internal/render-proof.js +0 -197
- package/dist/next/asset-route.d.ts +0 -10
- package/dist/next/asset-route.js +0 -45
- package/dist/next/collect-route.d.ts +0 -19
- package/dist/next/collect-route.js +0 -459
- package/dist/next/edge-config.d.ts +0 -1
- package/dist/next/edge-config.js +0 -92
- package/dist/next/envelope-digest.d.ts +0 -21
- package/dist/next/envelope-digest.js +0 -58
- package/dist/next/middleware.d.ts +0 -40
- package/dist/next/middleware.js +0 -475
- package/dist/next/personalization-host.js +0 -270
- package/dist/next/vercel-collect-sdk-route.d.ts +0 -27
- package/dist/next/vercel-collect-sdk-route.js +0 -181
- package/dist/next/vercel-edge-projection-v1.d.ts +0 -24
- package/dist/next/vercel-edge-projection-v1.js +0 -880
- package/dist/next/vercel-personalization.d.ts +0 -4
- package/dist/next/vercel-personalization.js +0 -4
- package/dist/next/vercel-s3-personalization.d.ts +0 -79
- package/dist/next/vercel-s3-personalization.js +0 -570
- package/dist/providers/s3.d.ts +0 -47
- package/dist/providers/s3.js +0 -434
- package/dist/types/render-mode.d.ts +0 -2
- package/dist/types/render-mode.js +0 -1
- package/dist/types/renderer.d.ts +0 -71
- package/dist/types/renderer.js +0 -1
- package/src/types/render-mode.ts +0 -10
- package/src/types/renderer.ts +0 -83
- package/templates/nextjs/starter-content/src/middleware.ts +0 -49
- package/templates/nextjs/template/src/app/gradial/assets/[...path]/route.ts +0 -1
- package/templates/nextjs/template/src/middleware.ts +0 -49
- package/templates/nextjs/template/src/middleware.ts.tmpl +0 -40
|
@@ -45,13 +45,10 @@ The SDK provides `createPage(registry)` which owns param normalization, content
|
|
|
45
45
|
loading, layout resolution, metadata generation, notFound handling, slot
|
|
46
46
|
resolution (including fragment defaults), and block rendering.
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
(not required `[...slug]`). Production middleware always rewrites to
|
|
53
|
-
`/__r/{releaseId}/routes/{path}`, but file-provider local dev passes requests
|
|
54
|
-
unrewritten so `/` arrives with an empty slug.
|
|
48
|
+
The filesystem uses an **optional catch-all** `[[...slug]]` (not required
|
|
49
|
+
`[...slug]`) so file-provider local development can render `/`. During publish,
|
|
50
|
+
the compiler invokes this route with an isolated render input; hosted CMS
|
|
51
|
+
traffic is served from the resulting immutable HTML and does not enter Next.
|
|
55
52
|
|
|
56
53
|
Chrome (Header/Footer) is **not** in `layout.tsx`. It is CMS-managed via
|
|
57
54
|
layout fragment defaults. The `layout.tsx` file is minimal and includes
|
|
@@ -197,41 +194,21 @@ the rewrite automatically.
|
|
|
197
194
|
| Storybook | `.storybook/main.ts`, `.storybook/preview.ts` |
|
|
198
195
|
| Assets | CloudFront function rewrite (automatic, no infrastructure changes needed) |
|
|
199
196
|
|
|
200
|
-
##
|
|
197
|
+
## Hosted routing
|
|
201
198
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
```ts
|
|
206
|
-
// src/middleware.ts
|
|
207
|
-
import { createGradialMiddleware } from '@gradial/aci/next/middleware';
|
|
208
|
-
export { config } from '@gradial/aci/next/middleware';
|
|
209
|
-
export default createGradialMiddleware({ siteId: 'your-tenant-id' });
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
The middleware rewrites public URLs to `/__r/{releaseId}/routes/{path}` for
|
|
213
|
-
the app-level route. The SDK extracts releaseId internally.
|
|
199
|
+
Do not add customer middleware for CMS routing. Provider edge bundles own
|
|
200
|
+
release/variant selection and protected immutable-artifact dispatch outside the
|
|
201
|
+
framework. Next receives neither the dispatch assertion nor a content reference.
|
|
214
202
|
|
|
215
203
|
## Asset Routes
|
|
216
204
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
205
|
+
Do not add an app-level asset route. Host adapters serve immutable browser and
|
|
206
|
+
DAM assets directly from S3/R2/CDN storage. Next's `withAci()` supports an
|
|
207
|
+
explicit direct asset-origin rewrite for local/custom builds.
|
|
220
208
|
|
|
221
209
|
DAM derivative assets are content-addressed and globally shared — staged once at
|
|
222
|
-
`{keyPrefix}/.gradial-dam/` and shared across all releases.
|
|
223
|
-
|
|
224
|
-
CloudFront function handles the rewrite automatically.
|
|
225
|
-
|
|
226
|
-
For transitional compatibility, the SDK still exports an asset route handler:
|
|
227
|
-
|
|
228
|
-
```ts
|
|
229
|
-
// src/app/gradial/assets/[...path]/route.ts (transitional)
|
|
230
|
-
export { GET, runtime, dynamic } from '@gradial/aci/next/asset-route';
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
**Note**: Asset URLs do NOT include `[releaseId]` in the path. DAM assets are
|
|
234
|
-
globally scoped and content-addressed via filename hashes.
|
|
210
|
+
`{keyPrefix}/.gradial-dam/` and shared across all releases. Asset URLs do not
|
|
211
|
+
need a release segment because their filenames bind content.
|
|
235
212
|
|
|
236
213
|
## Anti-Patterns
|
|
237
214
|
|
|
@@ -121,19 +121,11 @@ source:
|
|
|
121
121
|
componentRegistry: ./src/cms/contracts/components/index.ts
|
|
122
122
|
layoutRegistry: ./src/cms/contracts/layouts/index.ts
|
|
123
123
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
ssr: true
|
|
127
|
-
ssrIslands: true
|
|
128
|
-
clientIslands: true
|
|
129
|
-
fragmentRender: true
|
|
124
|
+
# Optional for custom renderers; Astro/Next use framework conventions.
|
|
125
|
+
# rendererEntry: ./src/cms/renderer.ts
|
|
130
126
|
|
|
131
127
|
routes:
|
|
132
128
|
cmsManaged: "/[[...slug]]"
|
|
133
|
-
frameworkOwned:
|
|
134
|
-
- "/api/*"
|
|
135
|
-
- "/_next/*" # Next.js
|
|
136
|
-
- "/.gradial-dam/*"
|
|
137
129
|
|
|
138
130
|
rendererProtocol: stdio-json
|
|
139
131
|
```
|
|
@@ -150,20 +142,21 @@ rendererProtocol: stdio-json
|
|
|
150
142
|
| `source.publicDir` | Public assets directory (Astro) |
|
|
151
143
|
| `componentRegistry` | Path to component contract barrel |
|
|
152
144
|
| `layoutRegistry` | Path to layout contract barrel |
|
|
153
|
-
| `
|
|
145
|
+
| `rendererEntry` | Optional renderer entry override; omit for framework conventions |
|
|
154
146
|
| `routes.cmsManaged` | Catch-all route pattern for CMS pages |
|
|
155
|
-
| `routes.frameworkOwned` | Route patterns excluded from CMS routing |
|
|
156
147
|
| `rendererProtocol` | Renderer communication protocol |
|
|
157
148
|
|
|
158
|
-
###
|
|
149
|
+
### Retired fields
|
|
159
150
|
|
|
160
|
-
- `
|
|
151
|
+
- `capabilities` is rejected. Deterministic CMS delivery always produces
|
|
152
|
+
complete static HTML.
|
|
153
|
+
- `routes.frameworkOwned` is rejected. Application-owned routes are a separate
|
|
154
|
+
hosting contract, not a fallback from CMS delivery.
|
|
161
155
|
|
|
162
156
|
### Rules
|
|
163
157
|
|
|
164
158
|
- `componentRegistry` and `layoutRegistry` point to contract-only modules.
|
|
165
159
|
- No secrets in `.aci.yaml`, docs, fixtures, or generated files.
|
|
166
160
|
- The `cmsManaged` route pattern should match the filesystem: use `/[[...slug]]`
|
|
167
|
-
(optional catch-all) for Next.js repos
|
|
168
|
-
|
|
169
|
-
local dev passes requests unrewritten so `/` arrives with an empty slug.
|
|
161
|
+
(optional catch-all) for Next.js repos so local `/` arrives with an empty
|
|
162
|
+
slug. Hosted routing selects already-rendered artifacts outside Next.
|
|
@@ -104,8 +104,8 @@ Only Next.js and Astro are supported. SvelteKit support has been removed.
|
|
|
104
104
|
| Root layout | `src/app/layout.tsx` (minimal — imports CSS, includes `<DevRefresh />`, no chrome) |
|
|
105
105
|
| Config | `next.config.ts` with bare `withAci()` |
|
|
106
106
|
| Registry | `src/cms/registry.ts` (shared, `createRegistry` with `[contract, component]` tuples) |
|
|
107
|
-
| Middleware |
|
|
108
|
-
| Asset route |
|
|
107
|
+
| Middleware | None for CMS routing; the provider host bundle selects immutable artifacts outside Next |
|
|
108
|
+
| Asset route | None; host gateways serve immutable browser/DAM assets directly and conformance rejects request-time Next asset routes |
|
|
109
109
|
|
|
110
110
|
### Astro
|
|
111
111
|
|
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
## `@gradial/aci/next` Exports
|
|
4
4
|
|
|
5
|
-
The SDK provides server-side functions
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
The SDK provides server-side functions for the publish-time Next renderer and
|
|
6
|
+
local file-backed development. They resolve either a compiler-injected render
|
|
7
|
+
input or `.aci/compiled` content. Hosted CMS requests do not enter Next and
|
|
8
|
+
these functions never resolve a mutable provider pointer or fetch deployed page
|
|
9
|
+
content from S3.
|
|
9
10
|
|
|
10
11
|
### `createPage(registry, options?)`
|
|
11
12
|
|
|
@@ -14,11 +15,9 @@ normalization, content loading via render input, metadata generation,
|
|
|
14
15
|
`notFound` handling, layout resolution, and block rendering via the
|
|
15
16
|
registry.
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
arrives with an empty/undefined slug. The filesystem uses an **optional catch-all**
|
|
21
|
-
`[[...slug]]` to handle both shapes.
|
|
18
|
+
The filesystem uses an **optional catch-all** `[[...slug]]` so local `/`
|
|
19
|
+
requests arrive with an empty slug. During publish, the compiler invokes the
|
|
20
|
+
same route against an isolated render input and captures complete HTML.
|
|
22
21
|
|
|
23
22
|
```tsx
|
|
24
23
|
// src/app/[[...slug]]/page.tsx
|
|
@@ -38,11 +37,10 @@ fragments.
|
|
|
38
37
|
|
|
39
38
|
### `withAci(nextConfig?, options?)`
|
|
40
39
|
|
|
41
|
-
Next.js config wrapper
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
rely on SDK defaults.
|
|
40
|
+
Next.js config wrapper for the local-dev and publish-time renderer capsule. It
|
|
41
|
+
owns standalone output, `outputFileTracingRoot`, optional direct asset-origin
|
|
42
|
+
rewrites, content watching, and error-page build payloads. Repos should pass a
|
|
43
|
+
bare `withAci()` call unless they have an explicit CDN asset origin.
|
|
46
44
|
|
|
47
45
|
```ts
|
|
48
46
|
// next.config.ts
|
|
@@ -51,22 +49,15 @@ import { withAci } from '@gradial/aci/next/config';
|
|
|
51
49
|
export default withAci();
|
|
52
50
|
```
|
|
53
51
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
export default withAci({
|
|
58
|
-
passthroughRoutes: ['/api/*', '/admin/*'],
|
|
59
|
-
});
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
Do not manually configure outputFileTracing, base-path, build-mode, dist-dir,
|
|
63
|
-
or custom rewrites/redirects for ACI concerns. The SDK handles these.
|
|
52
|
+
Do not add routing middleware or request-time content rewrites for CMS routes.
|
|
53
|
+
Provider hosting bundles own public route selection and immutable artifact
|
|
54
|
+
delivery outside the Next application.
|
|
64
55
|
|
|
65
56
|
### `getSiteConfig<T>()`
|
|
66
57
|
|
|
67
|
-
Loads the site configuration
|
|
68
|
-
|
|
69
|
-
|
|
58
|
+
Loads the site configuration from the current compiler render input, then from
|
|
59
|
+
the local file provider. **MUST be used in `layout.tsx` instead of constructing
|
|
60
|
+
a provider directly.**
|
|
70
61
|
|
|
71
62
|
```tsx
|
|
72
63
|
import { getSiteConfig } from '@gradial/aci/next';
|
|
@@ -79,23 +70,21 @@ Generic: pass your site config interface for typed access:
|
|
|
79
70
|
|
|
80
71
|
### `getFragment(name)`
|
|
81
72
|
|
|
82
|
-
Loads a fragment by name
|
|
83
|
-
provider fallback.
|
|
73
|
+
Loads a fragment by name from the compiler render input or local files.
|
|
84
74
|
|
|
85
75
|
### `getLayout(name)`
|
|
86
76
|
|
|
87
|
-
Loads a layout by name
|
|
88
|
-
provider fallback.
|
|
77
|
+
Loads a layout by name from the compiler render input or local files.
|
|
89
78
|
|
|
90
79
|
### `getPage(route)`
|
|
91
80
|
|
|
92
|
-
Loads page content for a specific route
|
|
93
|
-
|
|
81
|
+
Loads page content for a specific route from the compiler render input or local
|
|
82
|
+
files.
|
|
94
83
|
|
|
95
84
|
### `getRenderInput(route)`
|
|
96
85
|
|
|
97
86
|
Loads the full render input (page + siteConfig + domain + locale). Used
|
|
98
|
-
internally by `createPage`. Available for custom
|
|
87
|
+
internally by `createPage`. Available for custom publish-time rendering when
|
|
99
88
|
you need the full render context.
|
|
100
89
|
|
|
101
90
|
### `routeFromNextParams(params)`
|
|
@@ -113,37 +102,13 @@ const previewRelease = await isPreviewMode();
|
|
|
113
102
|
if (previewRelease) { /* preview-specific logic */ }
|
|
114
103
|
```
|
|
115
104
|
|
|
116
|
-
###
|
|
117
|
-
|
|
118
|
-
Creates Next.js middleware for ACI sites. Requires explicit `siteId`.
|
|
119
|
-
|
|
120
|
-
```ts
|
|
121
|
-
// src/middleware.ts
|
|
122
|
-
import { createGradialMiddleware } from '@gradial/aci/next/middleware';
|
|
123
|
-
|
|
124
|
-
export default createGradialMiddleware({ siteId: 'your-tenant-id' });
|
|
125
|
-
export { config } from '@gradial/aci/next/middleware';
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
The SDK exports a canonical middleware matcher via the `config` export. Repos
|
|
129
|
-
should re-export it verbatim. Do not hand-roll custom matcher patterns unless
|
|
130
|
-
site-specific static paths require exclusions.
|
|
105
|
+
### Provider-owned routing
|
|
131
106
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
edgeConfig?: string;
|
|
138
|
-
previewSignKey?: string;
|
|
139
|
-
deploymentId?: string;
|
|
140
|
-
deploymentProtectionBypass?: string;
|
|
141
|
-
}
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
The middleware rewrites public URLs to `/__r/{releaseId}/routes/{path}` for
|
|
145
|
-
the app-level route. The SDK extracts releaseId and resolves the content route
|
|
146
|
-
internally.
|
|
107
|
+
Do not add `src/middleware.ts` for CMS routing. Vercel's composed Build Output
|
|
108
|
+
contains host-owned middleware and a protected static gateway; CloudFront and
|
|
109
|
+
Cloudflare have equivalent provider adapters. They select and serve an
|
|
110
|
+
immutable artifact without passing a release selector, content reference, or
|
|
111
|
+
dispatch assertion into Next.
|
|
147
112
|
|
|
148
113
|
### `DevRefresh`
|
|
149
114
|
|
|
@@ -172,50 +137,35 @@ import { DevRefresh } from '@gradial/aci/next';
|
|
|
172
137
|
`createPage` catches `PageNotFoundError` and calls `notFound()`
|
|
173
138
|
automatically.
|
|
174
139
|
|
|
175
|
-
##
|
|
140
|
+
## Two Build-Time Content Inputs
|
|
176
141
|
|
|
177
|
-
Every SDK server function follows the same resolution chain:
|
|
142
|
+
Every SDK server function follows the same local/publish-time resolution chain:
|
|
178
143
|
|
|
179
|
-
### Tier 1: Render Input
|
|
144
|
+
### Tier 1: Compiler Render Input
|
|
180
145
|
|
|
181
146
|
When the Go harness sends a render request, it sets the
|
|
182
147
|
`x-gradial-render-input-id` header. The SDK checks the
|
|
183
148
|
`pendingRenderInputs` in-process map for a matching render input and
|
|
184
|
-
returns page data directly from the Go harness's render payload. This
|
|
185
|
-
|
|
186
|
-
|
|
149
|
+
returns page data directly from the Go harness's render payload. This is how
|
|
150
|
+
preview and publish render a finite content snapshot without giving the
|
|
151
|
+
framework live storage authority.
|
|
187
152
|
|
|
188
153
|
### Tier 2: File Provider (`ACI_CONTENT_PROVIDER=file`)
|
|
189
154
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
no render input header is present.
|
|
194
|
-
|
|
195
|
-
### Tier 3: S3 Provider (Deployed SSR)
|
|
196
|
-
|
|
197
|
-
When neither render input nor file provider is active, the SDK reads
|
|
198
|
-
from S3. The release ID is resolved from (in order):
|
|
199
|
-
|
|
200
|
-
1. `x-gradial-release-id` header (set by middleware)
|
|
201
|
-
2. `ACI_RELEASE_ID` environment variable
|
|
202
|
-
3. Vercel Edge Config active release pointer
|
|
155
|
+
Without a compiler render input, the SDK reads compiled content from
|
|
156
|
+
`.aci/compiled/` on disk. This is the local development path. There is no third
|
|
157
|
+
request-time S3 or Edge Config tier.
|
|
203
158
|
|
|
204
159
|
## Critical Rule
|
|
205
160
|
|
|
206
|
-
**NEVER
|
|
207
|
-
|
|
161
|
+
**NEVER construct a content provider directly in app code.** Always use
|
|
162
|
+
`getPage()`, `getSiteConfig()`, `getFragment()`,
|
|
208
163
|
`getLayout()`, or `getRenderInput()` from `@gradial/aci/next`. The SDK
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
`getReleaseAssetResponse` for S3 assets. The preferred path is to use no
|
|
215
|
-
app-level asset route at all (`withAci()` handles rewrites for Next.js;
|
|
216
|
-
CloudFront function rewrite for Astro). DAM derivative assets are
|
|
217
|
-
content-addressed and globally shared — staged once at `{keyPrefix}/.gradial-dam/`
|
|
218
|
-
and shared across all releases.
|
|
164
|
+
keeps the compiler-input and local-file boundary explicit.
|
|
165
|
+
|
|
166
|
+
Do not add an app-level asset route. Host gateways serve immutable browser and
|
|
167
|
+
DAM assets directly; `withAci()` may rewrite to an explicitly configured asset
|
|
168
|
+
origin for local/custom builds.
|
|
219
169
|
|
|
220
170
|
## Layout.tsx Pattern
|
|
221
171
|
|
|
@@ -47,19 +47,11 @@ export default defineConfig({
|
|
|
47
47
|
Delete manual env-var plumbing, outputFileTracing, custom rewrites/redirects
|
|
48
48
|
for ACI concerns.
|
|
49
49
|
|
|
50
|
-
### 4. Middleware:
|
|
50
|
+
### 4. Middleware: Remove Customer Ownership
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
// src/middleware.ts
|
|
56
|
-
import { createGradialMiddleware } from '@gradial/aci/next/middleware';
|
|
57
|
-
export { config } from '@gradial/aci/next/middleware';
|
|
58
|
-
export default createGradialMiddleware({ siteId: 'your-tenant-id' });
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
Re-export the SDK's canonical matcher via `config`. Delete custom matchers
|
|
62
|
-
unless site-specific static paths require exclusions.
|
|
52
|
+
Delete `src/middleware.ts` when it performs CMS routing. The provider host bundle
|
|
53
|
+
owns release/variant selection and protected immutable-artifact delivery outside
|
|
54
|
+
the framework; customer code must not implement a second decision path.
|
|
63
55
|
|
|
64
56
|
### 5. Path Shape: `[[...slug]]` (Optional Catch-All)
|
|
65
57
|
|
|
@@ -76,10 +68,9 @@ routes:
|
|
|
76
68
|
cmsManaged: "/[[...slug]]"
|
|
77
69
|
```
|
|
78
70
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
the dev homepage.
|
|
71
|
+
File-provider local development sends `/` to the framework with an empty slug,
|
|
72
|
+
so a required catch-all 404s the dev homepage. Hosted CMS requests use the
|
|
73
|
+
provider's immutable artifact path and do not enter this Next route.
|
|
83
74
|
|
|
84
75
|
### 6. DevRefresh Mandated
|
|
85
76
|
|
|
@@ -235,22 +226,14 @@ conformancePreset({
|
|
|
235
226
|
|
|
236
227
|
4. **Remove Custom Asset Route**
|
|
237
228
|
|
|
238
|
-
Delete `src/app/gradial/assets
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
```ts
|
|
242
|
-
// src/app/gradial/assets/[...path]/route.ts
|
|
243
|
-
export { GET, runtime, dynamic } from '@gradial/aci/next/asset-route';
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
The SDK asset-route handler resolves releaseId internally. No need for an
|
|
247
|
-
explicit path segment.
|
|
229
|
+
Delete every `src/app/gradial/assets/**/route.ts` form. Do not replace it;
|
|
230
|
+
provider gateways serve immutable browser and DAM assets directly.
|
|
248
231
|
|
|
249
232
|
5. **Delete `content-assets` Route and `.gradial-dam` Rewrite**
|
|
250
233
|
|
|
251
|
-
Delete `src/app/content-assets/[...key]/route.ts` and
|
|
252
|
-
`.gradial-dam` rewrite
|
|
253
|
-
|
|
234
|
+
Delete `src/app/content-assets/[...key]/route.ts` and any hand-written
|
|
235
|
+
request-time `.gradial-dam` rewrite. The SDK adapter owns local development;
|
|
236
|
+
provider gateways own deployed asset delivery.
|
|
254
237
|
|
|
255
238
|
6. **Delete Runtime `layouts.ts`**
|
|
256
239
|
|
|
@@ -313,13 +296,10 @@ conformancePreset({
|
|
|
313
296
|
];
|
|
314
297
|
```
|
|
315
298
|
|
|
316
|
-
2. **
|
|
317
|
-
|
|
318
|
-
Update middleware to pass explicit `siteId`:
|
|
299
|
+
2. **Remove Customer Middleware**
|
|
319
300
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
```
|
|
301
|
+
Delete `src/middleware.ts` when it implements CMS release or variant
|
|
302
|
+
selection. Provider routing occurs outside the framework.
|
|
323
303
|
|
|
324
304
|
3. **General Migration Steps**
|
|
325
305
|
|
|
@@ -444,10 +424,10 @@ The preset validates (default checks):
|
|
|
444
424
|
- `config` -- `withAci()` present in config
|
|
445
425
|
- `registry` -- `createRegistry()` usage (no hand-rolled maps)
|
|
446
426
|
- `pageEntry` -- `createPage(registry)` usage in catch-all route
|
|
447
|
-
- `middleware` --
|
|
427
|
+
- `middleware` -- no customer middleware implementing a second CMS decision path
|
|
448
428
|
- `noFileContentProvider` -- no direct `FileContentProvider` imports in app code
|
|
449
429
|
- `noCustomContent` -- no `src/lib/content.ts` shim
|
|
450
|
-
- `
|
|
430
|
+
- `noRequestTimeAssetRoute` -- no Next asset-delivery route
|
|
451
431
|
- `sdkVersion` -- SDK version >= 0.1.31
|
|
452
432
|
|
|
453
433
|
Optional (disabled by default, shell out):
|
|
@@ -9,18 +9,7 @@ source:
|
|
|
9
9
|
componentRegistry: ./src/cms/contracts/components/index.ts
|
|
10
10
|
layoutRegistry: ./src/cms/contracts/layouts/index.ts
|
|
11
11
|
|
|
12
|
-
capabilities:
|
|
13
|
-
staticRender: true
|
|
14
|
-
ssr: true
|
|
15
|
-
ssrIslands: true
|
|
16
|
-
clientIslands: true
|
|
17
|
-
fragmentRender: true
|
|
18
|
-
|
|
19
12
|
routes:
|
|
20
13
|
cmsManaged: "/[...slug]"
|
|
21
|
-
frameworkOwned:
|
|
22
|
-
- "/api/*"
|
|
23
|
-
- "/_next/*"
|
|
24
|
-
- "/.gradial-dam/*"
|
|
25
14
|
|
|
26
15
|
rendererProtocol: stdio-json
|
|
@@ -47,6 +47,5 @@ src/cms/ Contracts and component registry
|
|
|
47
47
|
src/components/ Runtime React components
|
|
48
48
|
src/design-system/ Design tokens and global styles
|
|
49
49
|
src/app/ Next.js App Router pages and routes
|
|
50
|
-
src/middleware.ts ACI middleware (siteId, release routing)
|
|
51
50
|
.agents/skills/ Skills for humans and agents
|
|
52
51
|
```
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export type DeviceClass = "desktop" | "mobile" | "tablet" | "unknown";
|
|
2
|
-
export declare const MOBILE_MAX_VIEWPORT_WIDTH = 767;
|
|
3
|
-
export declare const TABLET_MAX_VIEWPORT_WIDTH = 1024;
|
|
4
|
-
export interface DeviceClassEnv {
|
|
5
|
-
/** navigator.userAgentData — absent on Firefox and Safari. */
|
|
6
|
-
userAgentData?: {
|
|
7
|
-
mobile?: unknown;
|
|
8
|
-
} | null;
|
|
9
|
-
/** window.innerWidth at init (layout viewport, CSS px). */
|
|
10
|
-
innerWidth?: unknown;
|
|
11
|
-
}
|
|
12
|
-
export declare function computeDeviceClass(env: DeviceClassEnv): DeviceClass;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
// Device class (personalization-reporting D-PR-22): one coarse, closed-enum
|
|
2
|
-
// classification computed ONCE at init and stamped on every batched event.
|
|
3
|
-
// Server-side UA parsing is deliberately absent — CloudFront strips
|
|
4
|
-
// User-Agent before the origin, and a parsing dependency is unwarranted for
|
|
5
|
-
// four bounded values that eventually join a rollup primary key.
|
|
6
|
-
//
|
|
7
|
-
// Precedence: navigator.userAgentData.mobile (UA-CH) wins where supported;
|
|
8
|
-
// the layout-viewport width is the fallback for Firefox/Safari. The fallback
|
|
9
|
-
// is intentionally crude — a narrow desktop window can misclassify — which
|
|
10
|
-
// is why UA-CH always wins when present.
|
|
11
|
-
export const MOBILE_MAX_VIEWPORT_WIDTH = 767;
|
|
12
|
-
export const TABLET_MAX_VIEWPORT_WIDTH = 1024;
|
|
13
|
-
export function computeDeviceClass(env) {
|
|
14
|
-
const uaMobile = env.userAgentData?.mobile;
|
|
15
|
-
if (uaMobile === true)
|
|
16
|
-
return "mobile";
|
|
17
|
-
if (uaMobile === false)
|
|
18
|
-
return "desktop";
|
|
19
|
-
if (typeof env.innerWidth === "number" && Number.isFinite(env.innerWidth) && env.innerWidth > 0) {
|
|
20
|
-
if (env.innerWidth <= MOBILE_MAX_VIEWPORT_WIDTH)
|
|
21
|
-
return "mobile";
|
|
22
|
-
if (env.innerWidth <= TABLET_MAX_VIEWPORT_WIDTH)
|
|
23
|
-
return "tablet";
|
|
24
|
-
return "desktop";
|
|
25
|
-
}
|
|
26
|
-
return "unknown";
|
|
27
|
-
}
|
package/dist/content/assets.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export interface ReleaseAssetConfig {
|
|
2
|
-
bucket?: string;
|
|
3
|
-
keyPrefix?: string;
|
|
4
|
-
region?: string;
|
|
5
|
-
accessKeyId?: string;
|
|
6
|
-
secretAccessKey?: string;
|
|
7
|
-
sessionToken?: string;
|
|
8
|
-
roleArn?: string;
|
|
9
|
-
endpoint?: string;
|
|
10
|
-
}
|
|
11
|
-
export declare class ReleaseAssetNotFoundError extends Error {
|
|
12
|
-
constructor(releaseId: string, assetPath: string, cause?: unknown);
|
|
13
|
-
}
|
|
14
|
-
export declare function getReleaseAssetResponse(input: {
|
|
15
|
-
releaseId: string;
|
|
16
|
-
assetPath: string;
|
|
17
|
-
config?: ReleaseAssetConfig;
|
|
18
|
-
}): Promise<Response>;
|
package/dist/content/assets.js
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { S3ContentProvider } from '../providers/s3.js';
|
|
2
|
-
export class ReleaseAssetNotFoundError extends Error {
|
|
3
|
-
constructor(releaseId, assetPath, cause) {
|
|
4
|
-
super(`ACI release asset not found: ${releaseId}/${assetPath}`);
|
|
5
|
-
this.name = 'ReleaseAssetNotFoundError';
|
|
6
|
-
this.cause = cause;
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
export async function getReleaseAssetResponse(input) {
|
|
10
|
-
const clean = cleanAssetPath(input.assetPath);
|
|
11
|
-
if (!input.releaseId || !clean) {
|
|
12
|
-
throw new ReleaseAssetNotFoundError(input.releaseId, input.assetPath);
|
|
13
|
-
}
|
|
14
|
-
const config = input.config ?? {};
|
|
15
|
-
const provider = new S3ContentProvider({
|
|
16
|
-
bucket: config.bucket,
|
|
17
|
-
keyPrefix: releaseKey(config, input.releaseId),
|
|
18
|
-
region: config.region,
|
|
19
|
-
accessKeyId: config.accessKeyId,
|
|
20
|
-
secretAccessKey: config.secretAccessKey,
|
|
21
|
-
sessionToken: config.sessionToken,
|
|
22
|
-
roleArn: config.roleArn,
|
|
23
|
-
endpoint: config.endpoint,
|
|
24
|
-
});
|
|
25
|
-
const key = joinKey(provider.config.keyPrefix, 'assets', clean);
|
|
26
|
-
const res = await provider.fetchRaw(key);
|
|
27
|
-
if (!res.ok || !res.body) {
|
|
28
|
-
throw new ReleaseAssetNotFoundError(input.releaseId, clean, await safeResponseText(res));
|
|
29
|
-
}
|
|
30
|
-
const headers = new Headers();
|
|
31
|
-
copyHeader(res.headers, headers, 'content-type');
|
|
32
|
-
copyHeader(res.headers, headers, 'content-length');
|
|
33
|
-
copyHeader(res.headers, headers, 'etag');
|
|
34
|
-
copyHeader(res.headers, headers, 'last-modified');
|
|
35
|
-
headers.set('cache-control', 'public, max-age=300, must-revalidate');
|
|
36
|
-
return new Response(res.body, { status: 200, headers });
|
|
37
|
-
}
|
|
38
|
-
function cleanAssetPath(value) {
|
|
39
|
-
const clean = value.replace(/^\/+|\/+$/g, '').replace(/\/+/g, '/');
|
|
40
|
-
if (!clean || clean.split('/').some((segment) => segment === '..' || segment === '.'))
|
|
41
|
-
return '';
|
|
42
|
-
return clean;
|
|
43
|
-
}
|
|
44
|
-
function copyHeader(from, to, name) {
|
|
45
|
-
const value = from.get(name);
|
|
46
|
-
if (value)
|
|
47
|
-
to.set(name, value);
|
|
48
|
-
}
|
|
49
|
-
async function safeResponseText(res) {
|
|
50
|
-
try {
|
|
51
|
-
return await res.text();
|
|
52
|
-
}
|
|
53
|
-
catch {
|
|
54
|
-
return '';
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
function releaseKey(config, releaseId) {
|
|
58
|
-
return joinKey(config.keyPrefix || process.env.ACI_S3_KEY_PREFIX || '', 'releases', releaseId);
|
|
59
|
-
}
|
|
60
|
-
function joinKey(...parts) {
|
|
61
|
-
return parts
|
|
62
|
-
.filter(Boolean)
|
|
63
|
-
.map((part) => part.replace(/^\/+|\/+$/g, ''))
|
|
64
|
-
.filter(Boolean)
|
|
65
|
-
.join('/');
|
|
66
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export function selectPersonalizationVariant(request: any, route: any, claims: any, experiments: any, identity: any): any;
|
|
2
|
-
export function resolvePersonalizationDecision(request: any, route: any, claims: any, experiments: any, identity: any): {
|
|
3
|
-
variant: any;
|
|
4
|
-
experiment: {
|
|
5
|
-
experimentId: any;
|
|
6
|
-
armId: any;
|
|
7
|
-
allocationVersion: string;
|
|
8
|
-
variantKey: any;
|
|
9
|
-
bucket: number;
|
|
10
|
-
} | null;
|
|
11
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|