@gradial/aci 0.1.52-rc.9 → 0.1.52
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 +126 -0
- package/README.md +86 -5
- package/dist/astro/error-page.js +1 -0
- package/dist/astro/index.js +4 -0
- package/dist/astro/page.d.ts +5 -2
- package/dist/astro/page.js +35 -23
- package/dist/astro/preview.js +2 -17
- package/dist/audience-data-models.d.ts +308 -197
- package/dist/audience-data-models.js +313 -51
- package/dist/cli/compile-registry.mjs +6 -34
- package/dist/cli/mintlify-render.mjs +8 -0
- package/dist/collect/aci.js +1 -1
- package/dist/collect/aci.js.sha256 +1 -1
- package/dist/collect/api.d.ts +6 -7
- package/dist/collect/api.js +21 -8
- package/dist/collect/assignments.d.ts +7 -9
- package/dist/collect/assignments.js +23 -32
- package/dist/collect/batcher.d.ts +9 -7
- package/dist/collect/batcher.js +6 -5
- package/dist/collect/consent/envelope.d.ts +7 -1
- package/dist/collect/consent/envelope.js +3 -1
- package/dist/collect/consent/mapping.d.ts +2 -0
- package/dist/collect/consent/mapping.js +1 -0
- package/dist/collect/consenthold.d.ts +38 -0
- package/dist/collect/consenthold.js +82 -0
- package/dist/collect/declarative.js +7 -5
- package/dist/collect/gapbuffer.d.ts +13 -4
- package/dist/collect/gapbuffer.js +21 -10
- package/dist/collect/index.js +78 -21
- package/dist/collect/pageviews.d.ts +11 -11
- package/dist/collect/pageviews.js +27 -22
- package/dist/consent-banner/index.d.ts +17 -0
- package/dist/consent-banner/index.js +23 -0
- package/dist/content/index.d.ts +2 -1
- package/dist/content/index.js +4 -1
- package/dist/content/provider.d.ts +16 -2
- package/dist/content/provider.js +5 -1
- package/dist/content/resolve-slots.d.ts +24 -2
- package/dist/content/resolve-slots.js +127 -21
- package/dist/content/types.d.ts +5 -1
- package/dist/edge/expression-capabilities.v1.d.ts +106 -0
- package/dist/edge/expression-capabilities.v1.js +165 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.js +0 -1
- package/dist/internal/domain/edge/identity.d.ts +47 -4
- package/dist/internal/domain/edge/identity.js +130 -26
- package/dist/internal/domain/edge/index.d.ts +1 -1
- package/dist/internal/domain/edge/index.js +1 -1
- package/dist/internal/domain/edge/mimic_token.d.ts +14 -0
- package/dist/internal/domain/edge/mimic_token.js +125 -0
- package/dist/internal/domain/edge/personalization-core.d.ts +61 -22
- package/dist/internal/domain/edge/personalization-core.js +790 -200
- package/dist/internal/domain/edge/personalization_index.d.ts +17 -0
- package/dist/internal/domain/edge/personalization_index.js +55 -0
- package/dist/internal/domain/edge/resolve.js +76 -39
- package/dist/internal/domain/edge/testdata/flat_only_validator_v1.d.ts +10 -0
- package/dist/internal/domain/edge/testdata/flat_only_validator_v1.js +253 -0
- package/dist/internal/domain/edge/types.d.ts +82 -78
- package/dist/internal/domain/edge/types.js +3 -3
- package/dist/internal/domain/edge/variant_key.d.ts +4 -0
- package/dist/internal/domain/edge/variant_key.js +56 -0
- package/dist/internal/platform/collectionstore/errors.d.ts +24 -0
- package/dist/internal/platform/collectionstore/errors.js +48 -0
- package/dist/mintlify/blocks.d.ts +6 -0
- package/dist/mintlify/blocks.js +201 -0
- package/dist/mintlify/config.d.ts +3 -0
- package/dist/mintlify/config.js +77 -0
- package/dist/mintlify/index.d.ts +3 -0
- package/dist/mintlify/index.js +2 -0
- package/dist/mintlify/json.d.ts +8 -0
- package/dist/mintlify/json.js +37 -0
- package/dist/mintlify/materialize.d.ts +14 -0
- package/dist/mintlify/materialize.js +254 -0
- package/dist/mintlify/types.d.ts +74 -0
- package/dist/mintlify/types.js +1 -0
- package/dist/mintlify/validate.d.ts +7 -0
- package/dist/mintlify/validate.js +256 -0
- package/dist/next/assignments-navigation.d.ts +4 -0
- package/dist/next/assignments-navigation.js +18 -0
- package/dist/next/assignments-script.d.ts +3 -2
- package/dist/next/assignments-script.js +5 -5
- package/dist/next/error-pages.d.ts +4 -0
- package/dist/next/error-pages.js +4 -0
- package/dist/next/error-seat-payload.d.ts +2 -1
- package/dist/next/error-seat-payload.js +14 -24
- package/dist/next/error-seat.js +7 -2
- package/dist/next/index.d.ts +1 -1
- package/dist/next/index.js +3 -1
- package/dist/next/page.d.ts +2 -1
- package/dist/next/page.js +15 -4
- package/dist/next/release-context.d.ts +30 -0
- package/dist/next/release-context.js +56 -0
- package/dist/next/render.d.ts +1 -1
- package/dist/next/render.js +15 -5
- package/dist/next/server.d.ts +9 -3
- package/dist/next/server.js +17 -32
- package/dist/preview/core.d.ts +1 -0
- package/dist/preview/core.js +27 -0
- package/dist/react/VideoPlayer.d.ts +3 -3
- package/dist/react/index.d.ts +3 -3
- package/dist/registry.d.ts +4 -2
- package/dist/testing/conformance/checks.d.ts +2 -2
- package/dist/testing/conformance/checks.js +2 -0
- package/dist/testing/conformance/index.d.ts +1 -0
- package/dist/testing/conformance/index.js +1 -0
- package/dist/testing/conformance/next-stubs.d.ts +6 -0
- package/dist/testing/conformance/next-stubs.js +9 -0
- package/dist/testing/conformance/preset.d.ts +3 -2
- package/dist/testing/conformance/preset.js +15 -8
- package/dist/testing/conformance/root-identity.d.ts +31 -0
- package/dist/testing/conformance/root-identity.js +361 -0
- package/dist/testing/conformance/stubs/next-image.d.ts +7 -0
- package/dist/testing/conformance/stubs/next-image.js +5 -0
- package/dist/testing/conformance/stubs/next-link.d.ts +7 -0
- package/dist/testing/conformance/stubs/next-link.js +4 -0
- package/dist/testing/conformance/types.d.ts +5 -2
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.js +4 -3
- package/dist/types/block-ref.js +2 -2
- package/dist/types/component.d.ts +9 -0
- package/dist/types/config.d.ts +0 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/index.js +0 -1
- package/dist/types/page.d.ts +0 -1
- package/migrations/conformance-registry.md +22 -0
- package/migrations/experiment-goal-ids.md +43 -0
- package/package.json +21 -7
- package/src/cli/compile-registry.mjs +6 -30
- package/src/cli/mintlify-render.mjs +9 -0
- package/src/types/block-ref.test.ts +16 -1
- package/src/types/block-ref.ts +2 -2
- package/src/types/component.ts +10 -0
- package/src/types/config.ts +0 -1
- package/src/types/index.ts +0 -1
- package/src/types/page.ts +0 -1
- package/templates/astro/starter-content/src/components/chrome/Footer.astro +5 -3
- package/templates/astro/starter-content/src/components/chrome/Header.astro +5 -3
- package/templates/astro/starter-content/src/components/elements/Button.astro +5 -2
- package/templates/astro/starter-content/src/components/elements/ButtonBlock.astro +5 -3
- package/templates/astro/starter-content/src/components/sections/ContainerSection.astro +4 -3
- package/templates/astro/starter-content/src/components/sections/FeatureCard.astro +4 -3
- package/templates/astro/starter-content/src/components/sections/FeatureGrid.astro +4 -3
- package/templates/astro/starter-content/src/components/sections/HomeHero.astro +5 -3
- package/templates/astro/starter-content/src/components/sections/PersonalizationChoice.astro +4 -3
- package/templates/astro/starter-content/src/components/sections/StatsBar.astro +4 -3
- package/templates/astro/starter-content/src/fixtures/sections.ts +1 -1
- package/templates/astro/starter-content/src/stories/CompositionStoryFrame.astro +7 -2
- package/templates/astro/template/.aci.yaml.tmpl +0 -1
- package/templates/astro/template/package.json.tmpl +5 -5
- package/templates/astro/template/src/layouts/SiteLayout.astro +2 -2
- package/templates/common/.agents/skills/aci/SKILL.md +58 -1
- package/templates/common/.agents/skills/authoring/SKILL.md +194 -42
- package/templates/common/.agents/skills/authoring/references/block-registry.md +19 -3
- package/templates/common/.agents/skills/authoring/references/contracts.md +9 -30
- package/templates/common/.agents/skills/authoring/references/repo-structure.md +5 -4
- package/templates/common/.agents/skills/authoring/references/sdk-server-functions.md +3 -3
- package/templates/common/.agents/skills/dam-delivery/SKILL.md +216 -0
- package/templates/common/.agents/skills/dam-delivery/references/permalink-grammar.md +167 -0
- package/templates/common/.agents/skills/migration/references/canon-migration.md +18 -67
- package/templates/common/.agents/skills/migration/references/selector-map.md +1 -1
- package/templates/common/.content/fragments/navbar/_index.json +24 -0
- package/templates/common/.content/fragments/site-footer/_index.json +61 -0
- package/templates/common/.content/pages/404/_index.json +4 -2
- package/templates/common/.content/pages/_index.json +0 -1
- package/templates/common/.content/pages/error/_index.json +4 -2
- package/templates/common/.content/schemas/site.schema.json +11 -1
- package/templates/common/.content/templates/error.json +24 -0
- package/templates/common/.content/templates/home.json +28 -0
- package/templates/common/.content/templates/site.json +8 -0
- package/templates/common/.content/templates/standard.json +24 -0
- package/templates/common/.nvmrc +1 -1
- package/templates/common/starter-content/.content/config/site.json +1 -1
- package/templates/common/starter-content/.content/dam/README.md +74 -0
- package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000101}/asset.json +1 -1
- package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000102}/asset.json +1 -1
- package/templates/common/starter-content/.content/pages/404/_index.json +1 -2
- package/templates/common/starter-content/.content/pages/{home/_index.json → _index.json} +14 -3
- package/templates/common/starter-content/.content/pages/about/_index.json +2 -2
- package/templates/common/starter-content/.content/pages/error/_index.json +1 -2
- package/templates/common/starter-content/.content/patterns/components/button.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/container.json +8 -3
- package/templates/common/starter-content/.content/patterns/components/feature_card.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/feature_grid.json +5 -3
- package/templates/common/starter-content/.content/patterns/components/home_hero.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/personalization_choice.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/site-footer.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/site-navigation.json +2 -2
- package/templates/common/starter-content/.content/patterns/components/stats_bar.json +2 -2
- package/templates/common/starter-content/.content/schemas/site.schema.json +11 -1
- package/templates/nextjs/starter-content/src/components/chrome/Footer.tsx +4 -3
- package/templates/nextjs/starter-content/src/components/chrome/Header.tsx +4 -3
- package/templates/nextjs/starter-content/src/components/elements/Button.tsx +4 -3
- package/templates/nextjs/starter-content/src/components/elements/ButtonBlock.tsx +4 -3
- package/templates/nextjs/starter-content/src/components/sections/ContainerSection.tsx +4 -2
- package/templates/nextjs/starter-content/src/components/sections/FeatureCard.tsx +4 -3
- package/templates/nextjs/starter-content/src/components/sections/FeatureGrid.tsx +4 -2
- package/templates/nextjs/starter-content/src/components/sections/HomeHero.tsx +4 -3
- package/templates/nextjs/starter-content/src/components/sections/PersonalizationChoice.tsx +4 -2
- package/templates/nextjs/starter-content/src/components/sections/StatsBar.tsx +4 -3
- package/templates/nextjs/template/.aci.yaml +0 -1
- package/templates/nextjs/template/.aci.yaml.tmpl +0 -1
- package/templates/nextjs/template/package.json.tmpl +4 -3
- package/templates/nextjs/template/src/app/_components/c15t-bridge.ts +30 -0
- package/templates/nextjs/template/src/app/_components/c15t-consent-ui.tsx +37 -0
- package/templates/nextjs/template/src/app/_components/consent-manager.css +63 -0
- package/templates/nextjs/template/src/app/_components/consent-manager.tsx +76 -0
- package/templates/nextjs/template/src/app/fonts/inter/OFL.txt +93 -0
- package/templates/nextjs/template/src/app/fonts/inter/inter-latin.woff2 +0 -0
- package/templates/nextjs/template/src/app/fonts/space-grotesk/OFL.txt +93 -0
- package/templates/nextjs/template/src/app/fonts/space-grotesk/space-grotesk-latin.woff2 +0 -0
- package/templates/nextjs/template/src/app/layout.tsx +12 -7
- package/templates/nextjs/template/tests/conformance.test.ts.tmpl +1 -0
- package/dist/define-layout.d.ts +0 -6
- package/dist/define-layout.js +0 -14
- package/dist/edge/personalization-core.d.ts +0 -11
- package/dist/edge/personalization-core.js +0 -269
- package/dist/internal/domain/edge/compose.d.ts +0 -24
- package/dist/internal/domain/edge/compose.js +0 -89
- package/dist/internal/domain/edge/record/codec.d.ts +0 -71
- package/dist/internal/domain/edge/record/codec.js +0 -401
- 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.d.ts +0 -134
- package/dist/next/personalization-host.js +0 -270
- package/dist/next/root-layout.d.ts +0 -4
- package/dist/next/root-layout.js +0 -5
- 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/types/layout.d.ts +0 -24
- package/src/types/layout.ts +0 -29
- package/templates/astro/starter-content/src/render/RenderPage.astro +0 -67
- package/templates/astro/template/src/cms/contracts/layouts/index.ts +0 -18
- package/templates/common/starter-content/.content/patterns/layouts/default.json +0 -14
- package/templates/nextjs/starter-content/src/components/elements/AtomicBlock.tsx +0 -13
- package/templates/nextjs/template/src/cms/contracts/layouts/index.ts +0 -16
- /package/dist/{types/layout.js → cli/mintlify-render.d.mts} +0 -0
- /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000101}/editorial.json +0 -0
- /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000101}/governance.json +0 -0
- /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000101}/versions/v0001.json +0 -0
- /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000102}/editorial.json +0 -0
- /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000102}/governance.json +0 -0
- /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000102}/versions/v0001.json +0 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dam-delivery
|
|
3
|
+
description: Build and use public DAM asset links (`/dam/{assetId}`) with on-the-fly image shaping (resize, crop, format, quality). Use when a page, a CMS field, or an email needs a URL for an approved DAM asset, when choosing between pre-baked derivatives and a shaped public link, when making an asset public or taking it down, or when a `/dam/…` URL answers 301, 403, or 404 unexpectedly.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# DAM Delivery — Public Asset Links
|
|
7
|
+
|
|
8
|
+
Every approved DAM asset has one public address on the site's own domain:
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
https://{site}/dam/{assetId}
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Add a query to shape an image on the fly:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
https://{site}/dam/{assetId}?w=640&h=384&fit=crop&fm=jpg&q=80
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The link is built from the asset ID alone. Nothing is minted or signed and
|
|
21
|
+
nothing expires, so the same link can sit in a page, a CMS field, or an
|
|
22
|
+
email for years. It always serves the newest approved public version of
|
|
23
|
+
the asset.
|
|
24
|
+
|
|
25
|
+
## Retired — Do Not Use
|
|
26
|
+
|
|
27
|
+
Earlier SDK releases documented two delivery lanes that no longer exist.
|
|
28
|
+
If you meet any of these in old content, notes, or code, replace them with
|
|
29
|
+
the link above. They are not served and they do not redirect.
|
|
30
|
+
|
|
31
|
+
| Retired | Now |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| Signed URLs under `/dam/i/…`, `POST /v1/dam/assets/{assetId}/delivery-urls`, `aci dam delivery-url` | Build `/dam/{assetId}?…` yourself; there is nothing to mint |
|
|
34
|
+
| Permalinks under `/dam/a/…`, `GET /v1/dam/assets/{assetId}/permalinks`, recipe URLs | `/dam/{assetId}?…` |
|
|
35
|
+
| The `lifecycle.publicDelivery` flag | Approving a version makes it public (see below) |
|
|
36
|
+
| `width`, `height`, `gravity`, `dpr`, `quality`, `format` | `w`, `h`, `fit`, `fm`, `q` |
|
|
37
|
+
|
|
38
|
+
## The Link
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
/dam/{assetId}[/{slug}][?w=…&h=…&fit=…&fm=…&q=…]
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
- **`assetId`** is a raw 27-character ID made of digits and letters
|
|
45
|
+
(`0-9A-Za-z`), with no prefix. IDs that start with `ast_` are retired
|
|
46
|
+
and rejected; per ADR 0043 they are replaced by the breaking migration,
|
|
47
|
+
with no compatibility period.
|
|
48
|
+
- **`slug`** is optional and cosmetic: `/dam/{assetId}/spring-sale.jpg`
|
|
49
|
+
answers with a permanent redirect to `/dam/{assetId}`, keeping the query.
|
|
50
|
+
Use it when a tool insists on a URL that ends in a file extension. The
|
|
51
|
+
slug is never checked against anything, and its extension does not pick
|
|
52
|
+
the format.
|
|
53
|
+
- The CLI prints the path for an ID. It is a formatter only: it makes no
|
|
54
|
+
API call and does not tell you whether the asset is public.
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
aci dam permalink 2E9qL0001aBcDeFgHiJkLmNoPqR
|
|
58
|
+
# /dam/2E9qL0001aBcDeFgHiJkLmNoPqR
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The route is served by the deployed site's hosting edge. The site's own
|
|
62
|
+
dev server (`npm run dev`) only serves compiled derivatives under
|
|
63
|
+
`/dam/…`, so a public link answers 404 there — test it against the
|
|
64
|
+
deployed domain.
|
|
65
|
+
|
|
66
|
+
## Shaping an Image
|
|
67
|
+
|
|
68
|
+
Five query parameters, and only these. Full rules and worked examples:
|
|
69
|
+
`references/permalink-grammar.md`.
|
|
70
|
+
|
|
71
|
+
| Param | Values | Default | Notes |
|
|
72
|
+
| --- | --- | --- | --- |
|
|
73
|
+
| `w`, `h` | whole numbers | none | held to 16–3840, then snapped down to a fixed ladder of sizes |
|
|
74
|
+
| `fit` | `max` \| `crop` | `max` | `max` fits inside the box; `crop` fills it and needs both `w` and `h` |
|
|
75
|
+
| `fm` | `webp` \| `avif` \| `jpg` \| `png` | `webp` | the format is always this parameter, never the browser's `Accept` header |
|
|
76
|
+
| `q` | 5–100 | 80 | snapped down to steps of 5 |
|
|
77
|
+
|
|
78
|
+
Three things to know before writing a link:
|
|
79
|
+
|
|
80
|
+
- **Any one parameter turns shaping on, and the rest take their
|
|
81
|
+
defaults.** `?w=640` serves WebP at quality 80, not the original format.
|
|
82
|
+
To keep a JPEG a JPEG, say `fm=jpg`.
|
|
83
|
+
- **No parameters means the original.** `/dam/{assetId}` streams the
|
|
84
|
+
approved file byte for byte.
|
|
85
|
+
- **Nothing is rejected.** Unknown parameter names (`utm_*`, `mkt_tok`,
|
|
86
|
+
cache busters) are dropped. Out-of-range or unrecognised values are
|
|
87
|
+
snapped to an allowed one, sizes and quality always downward: `w=333`
|
|
88
|
+
serves 256, `q=77` serves 75, `fm=gif` serves WebP. Do not expect
|
|
89
|
+
pixel-exact sizes off the ladder. A `w`, `h`, or `q` that is not a
|
|
90
|
+
whole number (`w=abc`, `q=high`) is treated as if it had been left out,
|
|
91
|
+
so a typo never shrinks an image or lowers its quality.
|
|
92
|
+
|
|
93
|
+
The edge settles every link on one canonical form: the parameters in the
|
|
94
|
+
order `w`, `h`, `fit`, `fm`, `q`, after snapping, with `fit`, `fm`, and
|
|
95
|
+
`q` always present. A link written any other way still works. A request
|
|
96
|
+
already on `/dam/{assetId}` with a noncanonical query is answered with one
|
|
97
|
+
permanent redirect to the canonical link (sites hosted on CloudFront tidy
|
|
98
|
+
the query without a visible redirect). A request carrying a slug and a
|
|
99
|
+
noncanonical query can redirect twice: once to drop the slug, once to
|
|
100
|
+
canonicalize the query. Write the canonical form when you control the URL
|
|
101
|
+
and you skip those hops.
|
|
102
|
+
|
|
103
|
+
Shaping only applies to JPEG, PNG, WebP, and AVIF originals. Everything
|
|
104
|
+
else, SVG included, is served only as a file download, never displayed
|
|
105
|
+
inline. On AWS CloudFront this holds only once the hosting fix (PR #709)
|
|
106
|
+
has rolled out to the tenant; until then that lane may serve SVG or HTML
|
|
107
|
+
inline. See the reference for the size limits.
|
|
108
|
+
|
|
109
|
+
## What Makes a Link Serve
|
|
110
|
+
|
|
111
|
+
Approving a version is the "make public" act. There is no separate flag.
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
POST /v1/dam/assets/{assetId}/lifecycle
|
|
115
|
+
{ "action": "approve", "versionId": "…", "expectedHead": "…" }
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Read `effects` in the response to see what happened:
|
|
119
|
+
|
|
120
|
+
| Effect | Meaning |
|
|
121
|
+
| --- | --- |
|
|
122
|
+
| `live_published` | the link now serves this version |
|
|
123
|
+
| `public_admission_vetoed:<cause>` | the version is approved but **not public**: its expiry date has already passed, an embargo is still in force, a usage block, or a license that does not allow publication. A future expiry date does not veto; the link serves until that date. The link keeps serving the previous public version, if there is one |
|
|
124
|
+
| `live_plane_unconfigured` | a local or dev stack with no delivery wired; nothing was made public |
|
|
125
|
+
|
|
126
|
+
On the asset record (`GET /v1/dam/assets/{assetId}`), a public version
|
|
127
|
+
shows `deliveryTier: "public"` in its governance, and a refused one shows
|
|
128
|
+
`tierAdmissionVeto`.
|
|
129
|
+
|
|
130
|
+
- **A newer approved version takes over the same link.** Nothing needs
|
|
131
|
+
re-pasting.
|
|
132
|
+
- **To take a link down**, `demote` the version (the link falls back to
|
|
133
|
+
the previous public version, or stops serving if there is none) or
|
|
134
|
+
`archive` the asset. Both use the same lifecycle endpoint.
|
|
135
|
+
- **Governance that would have blocked the approval cannot be added while
|
|
136
|
+
a version is public.** A patch adding a past expiry date, an embargo, a
|
|
137
|
+
usage block, or a license without publication is refused with a
|
|
138
|
+
conflict that tells you to demote first. A future expiry date can be
|
|
139
|
+
set, moved, or cleared on a public version; the link stops serving the
|
|
140
|
+
version when that date arrives.
|
|
141
|
+
- **Changes take up to five minutes to show everywhere.** Responses are
|
|
142
|
+
`Cache-Control: public, max-age=300`, so a new version or a take-down
|
|
143
|
+
can lag by that long in browsers and CDN caches. On AWS CloudFront,
|
|
144
|
+
cached copies can currently outlive that window — the image pipeline
|
|
145
|
+
sets a one-year TTL and the distribution permits it — until the hosting
|
|
146
|
+
lane is corrected; the five minutes holds for Vercel and Cloudflare. Do
|
|
147
|
+
not treat a public link as instantly revocable, and do not re-cache it
|
|
148
|
+
for longer downstream.
|
|
149
|
+
|
|
150
|
+
## Pre-Baked Derivatives or a Public Link?
|
|
151
|
+
|
|
152
|
+
- **Images a page renders from content: keep using the pre-baked
|
|
153
|
+
pipeline.** Declare `imageSlots` in the contract and render with
|
|
154
|
+
`imageAttrs()` or `Picture`. The build produces fixed sizes per slot and
|
|
155
|
+
you never construct a URL. See the authoring skill.
|
|
156
|
+
- **A URL that lives outside the build: use the public link.** A field in
|
|
157
|
+
an external CMS, an email, a social card, a partner page, or a one-off
|
|
158
|
+
size that no slot declares.
|
|
159
|
+
|
|
160
|
+
The difference that matters: a pre-baked image is fixed at publish time
|
|
161
|
+
and changes with the next publish. A public link follows approval and
|
|
162
|
+
take-down on its own, within the five-minute window.
|
|
163
|
+
|
|
164
|
+
Published content may carry `/dam/{assetId}` links. The publish check
|
|
165
|
+
rejects a payload that contains a raw source path (`dam/blobs/…`) or a
|
|
166
|
+
retired `/dam/a/` or `/dam/i/` path.
|
|
167
|
+
|
|
168
|
+
## Email and External CMS Fields
|
|
169
|
+
|
|
170
|
+
1. **Paste the link; never let the tool import the bytes.** Many email
|
|
171
|
+
tools offer to "import" or "copy" images to their own CDN. Refuse. An
|
|
172
|
+
imported copy escapes approval and take-down forever; the link is the
|
|
173
|
+
governed pointer.
|
|
174
|
+
2. **Always set `fm=jpg` or `fm=png` in email.** The default is WebP, and
|
|
175
|
+
Outlook desktop cannot render WebP.
|
|
176
|
+
3. **Use the slug form when a tool wants a file extension:**
|
|
177
|
+
`/dam/{assetId}/spring-sale.jpg?w=640&fm=jpg`.
|
|
178
|
+
4. **`block_new_usage` does not take a public link down.** The link cannot
|
|
179
|
+
tell an old placement from a new one, so an asset under that
|
|
180
|
+
restriction keeps serving where it is already pasted. To stop serving,
|
|
181
|
+
demote or archive.
|
|
182
|
+
|
|
183
|
+
## When a Link Does Not Serve
|
|
184
|
+
|
|
185
|
+
Errors are never cached (`no-store`) on Vercel and Cloudflare. On AWS
|
|
186
|
+
CloudFront, 403 and 5xx responses may be cached by the distribution for up
|
|
187
|
+
to about ten seconds regardless of `no-store`. Exact codes differ slightly
|
|
188
|
+
between hosting providers, so treat any 4xx as "not served".
|
|
189
|
+
|
|
190
|
+
| You see | Why | Do |
|
|
191
|
+
| --- | --- | --- |
|
|
192
|
+
| 301 | a slug was dropped or the query was put in canonical form | follow it; write the canonical link next time |
|
|
193
|
+
| 403 | the asset has no public version (never approved, approval vetoed, demoted, archived, or expired), or the ID is malformed | check `effects` from the approve call and `deliveryTier` on the asset record |
|
|
194
|
+
| 404 | a retired `/dam/a/…` or `/dam/i/…` path, DAM delivery is not enabled for this site, or you are on the local dev server | rewrite the link; ask the operator to enable DAM delivery |
|
|
195
|
+
| 413 | the original is too large to shape | drop the query to get the original, or upload a smaller master |
|
|
196
|
+
| 415 | shaping was asked of a non-image original | drop the query |
|
|
197
|
+
| 503 | delivery could not read its own state and refused rather than guess | retry; if it persists, it is an operator issue |
|
|
198
|
+
| A download instead of an image | the original is not JPEG, PNG, WebP, or AVIF | by design; render SVGs through the site's own image pipeline |
|
|
199
|
+
|
|
200
|
+
## Draft Previews (Management Surfaces Only)
|
|
201
|
+
|
|
202
|
+
The public link never serves a draft. A draft or rejected version is
|
|
203
|
+
reachable only by an authenticated caller with read permission on the
|
|
204
|
+
asset, and only by naming the exact version:
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
GET /v1/dam/assets/{assetId}/versions/{versionId}/preview
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
It answers `302` to a short-lived signed URL: for JPEG, PNG, GIF, and WebP
|
|
211
|
+
up to 20 MiB, a WebP of that version downsampled at upload (longest edge
|
|
212
|
+
1024 px, never upscaled); for SVG, formats the server does not decode
|
|
213
|
+
(HEIC, AVIF, TIFF, BMP), or a version whose preview is not generated yet,
|
|
214
|
+
the original. Follow the redirect without forwarding your bearer token. It
|
|
215
|
+
takes no shaping parameters. Use it for editorial UIs and thumbnails,
|
|
216
|
+
never for site rendering.
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# Public Link Grammar Reference (`/dam/{assetId}`)
|
|
2
|
+
|
|
3
|
+
The one public address for a DAM asset:
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
/dam/{assetId}[/{slug}]?w=640&h=384&fit=crop&fm=jpg&q=80
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Permanent, built from the asset ID alone, and always serving the newest
|
|
10
|
+
approved public version. Everything below is enforced at the hosting edge.
|
|
11
|
+
No API call sits in the path of a view, and no API hands these links out —
|
|
12
|
+
you write them.
|
|
13
|
+
|
|
14
|
+
## Asset ID
|
|
15
|
+
|
|
16
|
+
Exactly 27 characters from `0-9A-Za-z`, no prefix. IDs that start with
|
|
17
|
+
`ast_` are retired and refused; per ADR 0043 the migration to the new IDs
|
|
18
|
+
is breaking, with no compatibility period. Anything else is refused.
|
|
19
|
+
|
|
20
|
+
## Parameters
|
|
21
|
+
|
|
22
|
+
Only these five names mean anything. Every other name is dropped, so
|
|
23
|
+
tracking decorations (`utm_*`, `mkt_tok`) cannot break an image.
|
|
24
|
+
|
|
25
|
+
| Param | Values | Default | Snapping |
|
|
26
|
+
| --- | --- | --- | --- |
|
|
27
|
+
| `w`, `h` | whole numbers | none | below 16 becomes 16, above 3840 becomes 3840, otherwise snapped DOWN to the ladder `16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840` |
|
|
28
|
+
| `fit` | `max` \| `crop` | `max` | any other value becomes `max` |
|
|
29
|
+
| `fm` | `webp` \| `avif` \| `jpg` \| `png` | `webp` | any other value becomes `webp` |
|
|
30
|
+
| `q` | whole numbers | 80 | below 5 becomes 5, above 100 becomes 100, otherwise snapped DOWN to a step of 5 |
|
|
31
|
+
|
|
32
|
+
Nothing in the query is ever answered with an error. A value the address
|
|
33
|
+
cannot read is treated as if that parameter had been left out, so a typo
|
|
34
|
+
never shrinks an image or lowers its quality. The reading rules are the
|
|
35
|
+
same on every hosting provider:
|
|
36
|
+
|
|
37
|
+
- **Any of the five names turns shaping on**, whatever its value, even an
|
|
38
|
+
empty one (`?w=`).
|
|
39
|
+
- **`w`, `h`, and `q` are read only as a whole number in plain digits**,
|
|
40
|
+
with an optional leading minus sign. Zero and negative numbers count as
|
|
41
|
+
below the minimum (`w=-1` serves 16, `q=0` serves 5). Anything else is
|
|
42
|
+
read as left out: an empty value, letters (`w=abc`, `w=640px`), a
|
|
43
|
+
decimal point (`w=640.7`), an exponent (`w=1e3`), a plus sign, spaces,
|
|
44
|
+
or a number larger in size than 9007199254740991. A `w` or `h` read as
|
|
45
|
+
left out sets no size; a `q` read as left out is 80.
|
|
46
|
+
- **An unrecognised or empty `fit` or `fm` takes its default** (`max`,
|
|
47
|
+
`webp`).
|
|
48
|
+
- **Names, and the values of `fit` and `fm`, are lowercase only.** `W=640`
|
|
49
|
+
is an unknown name and is dropped; `fm=JPG` serves WebP.
|
|
50
|
+
- **When a name repeats, the first one decides**, even when it cannot be
|
|
51
|
+
read: `?w=abc&w=640` sets no width.
|
|
52
|
+
|
|
53
|
+
The ladder is the Next.js image `srcset` ladder, so breakpoints written
|
|
54
|
+
for any modern framework land on a rung instead of snapping visibly.
|
|
55
|
+
Snapping is deliberate: it keeps the number of distinct renditions per
|
|
56
|
+
asset small and bounded.
|
|
57
|
+
|
|
58
|
+
How `fit` behaves:
|
|
59
|
+
|
|
60
|
+
- **`max`** scales the image to fit inside `w` × `h`, keeps its
|
|
61
|
+
proportions, and never crops. Give one dimension and the other follows.
|
|
62
|
+
- **`crop`** scales and crops to fill `w` × `h` exactly. With only one
|
|
63
|
+
dimension there is nothing to crop to, so it behaves like `max`.
|
|
64
|
+
- Neither enlarges: asking for more pixels than the original has serves
|
|
65
|
+
the original size.
|
|
66
|
+
|
|
67
|
+
Deliberately **not** in the grammar:
|
|
68
|
+
|
|
69
|
+
- No `dpr`. Pick a larger `w` rung instead, the way `srcset` does.
|
|
70
|
+
- No crop position or focal point.
|
|
71
|
+
- No format negotiation from the browser's `Accept` header. The format is
|
|
72
|
+
always the explicit `fm`.
|
|
73
|
+
- No recipes or named presets, no signatures, no expiry.
|
|
74
|
+
|
|
75
|
+
## Canonical Form
|
|
76
|
+
|
|
77
|
+
One spelling per rendition: `w`, `h`, `fit`, `fm`, `q` in that order,
|
|
78
|
+
after snapping. `w` and `h` appear only when given; `fit`, `fm`, and `q`
|
|
79
|
+
always appear once any of the five is present.
|
|
80
|
+
|
|
81
|
+
| You write | Canonical link |
|
|
82
|
+
| --- | --- |
|
|
83
|
+
| `/dam/{id}?w=640` | `/dam/{id}?w=640&fit=max&fm=webp&q=80` |
|
|
84
|
+
| `/dam/{id}?q=77&w=333&utm_source=mail` | `/dam/{id}?w=256&fit=max&fm=webp&q=75` |
|
|
85
|
+
| `/dam/{id}?fm=jpg` | `/dam/{id}?fit=max&fm=jpg&q=80` (a format change at the original size) |
|
|
86
|
+
| `/dam/{id}?w=640&q=high` | `/dam/{id}?w=640&fit=max&fm=webp&q=80` (the unreadable quality is read as left out) |
|
|
87
|
+
| `/dam/{id}?w=abc` | `/dam/{id}?fit=max&fm=webp&q=80` (no width, but still shaped: WebP at the original size) |
|
|
88
|
+
| `/dam/{id}?utm_source=mail` | `/dam/{id}` (no shaping asked for, so the original) |
|
|
89
|
+
| `/dam/{id}/spring-sale.jpg?w=640` | `/dam/{id}?w=640`, then as the first row |
|
|
90
|
+
|
|
91
|
+
A link that is not canonical is answered with one permanent redirect
|
|
92
|
+
(`301`, cacheable for an hour) to the canonical link, before any image
|
|
93
|
+
work is done. The image itself is cached once, under the canonical link.
|
|
94
|
+
A slug costs its own redirect first, with the query carried over as
|
|
95
|
+
written.
|
|
96
|
+
|
|
97
|
+
Sites hosted on CloudFront put the query in canonical form without a
|
|
98
|
+
visible redirect; a slug still redirects there.
|
|
99
|
+
|
|
100
|
+
## Responses
|
|
101
|
+
|
|
102
|
+
Only `GET` and `HEAD` are served. Error responses are `no-store` on
|
|
103
|
+
Vercel and Cloudflare; on AWS CloudFront, 403 and 5xx responses may be
|
|
104
|
+
cached by the distribution for up to about ten seconds regardless of
|
|
105
|
+
`no-store`. Exact error codes differ slightly between hosting providers;
|
|
106
|
+
treat any 4xx as "not served".
|
|
107
|
+
|
|
108
|
+
| Response | Meaning |
|
|
109
|
+
| --- | --- |
|
|
110
|
+
| 200, `Cache-Control: public, max-age=300` | serving |
|
|
111
|
+
| 301 | a slug was dropped, or the query was put in canonical form |
|
|
112
|
+
| 403, `no-store` | the asset has no public version (never approved, approval vetoed, demoted, archived, or expired), or the ID is malformed |
|
|
113
|
+
| 404, `no-store` | a retired `/dam/a/…` or `/dam/i/…` path, or DAM delivery is not enabled for the site |
|
|
114
|
+
| 413, `no-store` | the original is too large to shape (limits below) |
|
|
115
|
+
| 415, `no-store` | shaping was asked of an original that is not JPEG, PNG, WebP, or AVIF |
|
|
116
|
+
| 503, `no-store` | delivery could not read its own state; it refuses rather than guess |
|
|
117
|
+
|
|
118
|
+
The five-minute `max-age` is the whole revocation story. After a
|
|
119
|
+
take-down, an already-cached copy can keep showing for up to five minutes;
|
|
120
|
+
the next uncached request is checked again and refused. A newly approved
|
|
121
|
+
version takes over the link within the same window. This holds for Vercel
|
|
122
|
+
and Cloudflare; on AWS CloudFront, cached copies can currently outlive the
|
|
123
|
+
window — the image pipeline sets a one-year TTL and the distribution
|
|
124
|
+
permits it — until the hosting lane is corrected.
|
|
125
|
+
|
|
126
|
+
## Originals That Are Not Shaped
|
|
127
|
+
|
|
128
|
+
- **No query:** the approved file is streamed byte for byte, whatever its
|
|
129
|
+
size.
|
|
130
|
+
- **Shapeable originals** are JPEG, PNG, WebP, and AVIF.
|
|
131
|
+
- **Everything else** (SVG, GIF, PDF, video, documents) is served only as
|
|
132
|
+
a file download (`Content-Disposition: attachment`, with
|
|
133
|
+
`X-Content-Type-Options: nosniff`) and never displayed inline. An
|
|
134
|
+
`<img>` pointing at such a link will not render. On AWS CloudFront this
|
|
135
|
+
holds only once the hosting fix (PR #709) has rolled out to the tenant;
|
|
136
|
+
until then that lane may serve SVG or HTML inline.
|
|
137
|
+
- **Size limits for shaping:** the original must be at most 20 MB, at most
|
|
138
|
+
8192 pixels on either side, and at most 40 megapixels. Past any of
|
|
139
|
+
those, a shaped link is refused; the plain link still serves the
|
|
140
|
+
original. Provider gap: the AWS CloudFront lane does not currently
|
|
141
|
+
enforce these bounds, so an over-limit request is not refused there — do
|
|
142
|
+
not rely on enforcement on CloudFront.
|
|
143
|
+
|
|
144
|
+
## Examples
|
|
145
|
+
|
|
146
|
+
```html
|
|
147
|
+
<!-- Fixed-size email hero, JPEG for Outlook, explicit quality.
|
|
148
|
+
640 and 384 are ladder rungs; keep the HTML width/height on the same
|
|
149
|
+
rungs so the served crop and the layout box agree exactly -->
|
|
150
|
+
<img src="https://www.example.com/dam/2E9qL0001aBcDeFgHiJkLmNoPqR?w=640&h=384&fit=crop&fm=jpg&q=80"
|
|
151
|
+
width="640" height="384" alt="Spring sale hero">
|
|
152
|
+
|
|
153
|
+
<!-- Responsive srcset on ladder rungs, canonical form (no dpr — use w) -->
|
|
154
|
+
<img src="https://www.example.com/dam/2E9qL0001aBcDeFgHiJkLmNoPqR?w=828&fit=max&fm=webp&q=80"
|
|
155
|
+
srcset="https://www.example.com/dam/2E9qL0001aBcDeFgHiJkLmNoPqR?w=640&fit=max&fm=webp&q=80 640w,
|
|
156
|
+
https://www.example.com/dam/2E9qL0001aBcDeFgHiJkLmNoPqR?w=828&fit=max&fm=webp&q=80 828w,
|
|
157
|
+
https://www.example.com/dam/2E9qL0001aBcDeFgHiJkLmNoPqR?w=1200&fit=max&fm=webp&q=80 1200w"
|
|
158
|
+
sizes="(max-width: 640px) 100vw, 640px" alt="…">
|
|
159
|
+
|
|
160
|
+
<!-- Slug form for editors that check for a file extension: one cached
|
|
161
|
+
redirect to the link without the slug. The extension is cosmetic;
|
|
162
|
+
fm still picks the format -->
|
|
163
|
+
https://www.example.com/dam/2E9qL0001aBcDeFgHiJkLmNoPqR/spring-sale.jpg?w=640&fit=max&fm=jpg&q=80
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Snapping in practice: `?w=333&q=77` and `?w=256&q=75` serve the identical
|
|
167
|
+
rendition (333 snaps to 256, 77 snaps to 75).
|
|
@@ -92,29 +92,12 @@ export default function Layout({ children }: { children: ReactNode }) {
|
|
|
92
92
|
}
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
-
### 7. Layout Contracts
|
|
95
|
+
### 7. Replace Layout Contracts With Content Templates
|
|
96
96
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
import { defineLayoutContract, slot, fragmentDefault } from '@gradial/aci';
|
|
102
|
-
|
|
103
|
-
export default [
|
|
104
|
-
defineLayoutContract({
|
|
105
|
-
name: 'default',
|
|
106
|
-
slots: [
|
|
107
|
-
slot('header'),
|
|
108
|
-
slot('main', true),
|
|
109
|
-
slot('footer'),
|
|
110
|
-
],
|
|
111
|
-
defaults: {
|
|
112
|
-
header: fragmentDefault('navbar'),
|
|
113
|
-
footer: fragmentDefault('site-footer'),
|
|
114
|
-
},
|
|
115
|
-
}),
|
|
116
|
-
];
|
|
117
|
-
```
|
|
97
|
+
Convert each legacy code layout into `.content/templates/<name>.json`. The
|
|
98
|
+
template owns ordered regions, placement policy, requiredness, and fragment
|
|
99
|
+
defaults. Bind pages with `template` (or a route binding), then delete the
|
|
100
|
+
layout contract and remove `layoutRegistry` from `.aci.yaml`.
|
|
118
101
|
|
|
119
102
|
### 8. Content Compilation: Standardize CLI Command
|
|
120
103
|
|
|
@@ -235,23 +218,15 @@ conformancePreset({
|
|
|
235
218
|
`dam` rewrite from `next.config.ts`. The SDK asset route handles
|
|
236
219
|
both dev-mode file serving and deployed S3 serving.
|
|
237
220
|
|
|
238
|
-
6. **
|
|
221
|
+
6. **Replace All Layout Definitions**
|
|
239
222
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
223
|
+
Convert `src/cms/layouts.ts` and any `src/cms/contracts/layouts` definition
|
|
224
|
+
into `.content/templates`. Move navbar/footer fragment defaults into the
|
|
225
|
+
template regions, bind pages with `template`, and delete the old files.
|
|
243
226
|
|
|
244
|
-
7. **
|
|
227
|
+
7. **Remove Retired Config**
|
|
245
228
|
|
|
246
|
-
|
|
247
|
-
`fragmentDefault()`:
|
|
248
|
-
|
|
249
|
-
```ts
|
|
250
|
-
defaults: {
|
|
251
|
-
header: fragmentDefault('navbar'),
|
|
252
|
-
footer: fragmentDefault('site-footer'),
|
|
253
|
-
}
|
|
254
|
-
```
|
|
229
|
+
Remove `layoutRegistry` from `.aci.yaml`; current config rejects it.
|
|
255
230
|
|
|
256
231
|
8. **Update `.aci.yaml` siteId**
|
|
257
232
|
|
|
@@ -272,29 +247,11 @@ conformancePreset({
|
|
|
272
247
|
|
|
273
248
|
#### Required Changes
|
|
274
249
|
|
|
275
|
-
1. **
|
|
250
|
+
1. **Replace Layout Contracts With Templates**
|
|
276
251
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
// src/cms/contracts/layouts/index.ts
|
|
281
|
-
import { defineLayoutContract, slot, fragmentDefault } from '@gradial/aci';
|
|
282
|
-
|
|
283
|
-
export default [
|
|
284
|
-
defineLayoutContract({
|
|
285
|
-
name: 'default',
|
|
286
|
-
slots: [
|
|
287
|
-
slot('header'),
|
|
288
|
-
slot('main', true),
|
|
289
|
-
slot('footer'),
|
|
290
|
-
],
|
|
291
|
-
defaults: {
|
|
292
|
-
header: fragmentDefault('navbar'),
|
|
293
|
-
footer: fragmentDefault('site-footer'),
|
|
294
|
-
},
|
|
295
|
-
}),
|
|
296
|
-
];
|
|
297
|
-
```
|
|
252
|
+
Convert the layout contract into `.content/templates/default.json`, move
|
|
253
|
+
fragment defaults into template regions, bind pages with `template`, and
|
|
254
|
+
delete the code layout registry.
|
|
298
255
|
|
|
299
256
|
2. **Remove Customer Middleware**
|
|
300
257
|
|
|
@@ -359,16 +316,10 @@ conformancePreset({
|
|
|
359
316
|
already in place and handles DAM asset serving automatically with immutable
|
|
360
317
|
caching (`max-age=31536000`).
|
|
361
318
|
|
|
362
|
-
3. **
|
|
319
|
+
3. **Move Layout Defaults Into Templates**
|
|
363
320
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
```ts
|
|
367
|
-
defaults: {
|
|
368
|
-
header: fragmentDefault('navbar'),
|
|
369
|
-
footer: fragmentDefault('site-footer'),
|
|
370
|
-
}
|
|
371
|
-
```
|
|
321
|
+
Move navbar/footer defaults into `.content/templates` regions and delete
|
|
322
|
+
the code layout definition.
|
|
372
323
|
|
|
373
324
|
4. **General Migration Steps**
|
|
374
325
|
|
|
@@ -13,7 +13,7 @@ Location: `artifacts/source-vs-target/selector-map.json`
|
|
|
13
13
|
"targetUrl": "http://localhost:3000/",
|
|
14
14
|
"breakpoints": [360, 768, 1024, 1280, 1400],
|
|
15
15
|
"entries": {
|
|
16
|
-
"content/pages/
|
|
16
|
+
"content/pages/_index.json blocks[\"home-hero\"]": {
|
|
17
17
|
"source": ".home-hero",
|
|
18
18
|
"target": ".home-hero",
|
|
19
19
|
"viewport": "both",
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$type": "fragment",
|
|
3
|
+
"fragmentId": "navbar",
|
|
4
|
+
"block": {
|
|
5
|
+
"$type": "component",
|
|
6
|
+
"component": "site-navigation",
|
|
7
|
+
"props": {
|
|
8
|
+
"brandHref": "/",
|
|
9
|
+
"brandLabel": "Meridian",
|
|
10
|
+
"navigation": [
|
|
11
|
+
{ "id": "home", "label": "Home", "href": "/" },
|
|
12
|
+
{ "id": "plans", "label": "Plans", "href": "/plans/" },
|
|
13
|
+
{ "id": "devices", "label": "Devices", "href": "/devices/" },
|
|
14
|
+
{ "id": "business", "label": "Business", "href": "/business/" },
|
|
15
|
+
{ "id": "blog", "label": "Blog", "href": "/blog/" },
|
|
16
|
+
{ "id": "about", "label": "About", "href": "/about/" }
|
|
17
|
+
],
|
|
18
|
+
"utilities": [
|
|
19
|
+
{ "id": "sign-in", "label": "Sign in", "href": "/sign-in/", "variant": "ghost" },
|
|
20
|
+
{ "id": "contact-sales", "label": "Contact sales", "href": "/contact-sales/", "variant": "primary" }
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$type": "fragment",
|
|
3
|
+
"fragmentId": "site-footer",
|
|
4
|
+
"block": {
|
|
5
|
+
"$type": "component",
|
|
6
|
+
"component": "site-footer",
|
|
7
|
+
"props": {
|
|
8
|
+
"brandHref": "/",
|
|
9
|
+
"brandLabel": "Meridian",
|
|
10
|
+
"columns": [
|
|
11
|
+
{
|
|
12
|
+
"id": "products",
|
|
13
|
+
"title": "Products",
|
|
14
|
+
"links": [
|
|
15
|
+
{ "id": "plans", "label": "Plans", "href": "/plans/" },
|
|
16
|
+
{ "id": "devices", "label": "Devices", "href": "/devices/" },
|
|
17
|
+
{ "id": "coverage", "label": "Coverage", "href": "/coverage/" }
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"id": "solutions",
|
|
22
|
+
"title": "Solutions",
|
|
23
|
+
"links": [
|
|
24
|
+
{ "id": "business", "label": "Business", "href": "/business/" },
|
|
25
|
+
{ "id": "maritime", "label": "Maritime", "href": "/business/maritime/" },
|
|
26
|
+
{ "id": "aerospace", "label": "Aerospace", "href": "/business/aerospace/" }
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"id": "resources",
|
|
31
|
+
"title": "Resources",
|
|
32
|
+
"links": [
|
|
33
|
+
{ "id": "blog", "label": "Blog", "href": "/blog/" },
|
|
34
|
+
{ "id": "documentation", "label": "Documentation", "href": "/docs/" },
|
|
35
|
+
{ "id": "support", "label": "Support", "href": "/support/" }
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"id": "company",
|
|
40
|
+
"title": "Company",
|
|
41
|
+
"links": [
|
|
42
|
+
{ "id": "about", "label": "About us", "href": "/about/" },
|
|
43
|
+
{ "id": "careers", "label": "Careers", "href": "/careers/" },
|
|
44
|
+
{ "id": "contact", "label": "Contact", "href": "/contact/" }
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"social": [
|
|
49
|
+
{ "id": "x", "label": "X", "href": "https://x.com/meridian", "icon": "X" },
|
|
50
|
+
{ "id": "linkedin", "label": "LinkedIn", "href": "https://www.linkedin.com/company/meridian", "icon": "in" },
|
|
51
|
+
{ "id": "youtube", "label": "YouTube", "href": "https://www.youtube.com/meridian", "icon": "YT" }
|
|
52
|
+
],
|
|
53
|
+
"legalLinks": [
|
|
54
|
+
{ "id": "terms", "label": "Terms of Service", "href": "/terms/" },
|
|
55
|
+
{ "id": "privacy", "label": "Privacy Policy", "href": "/privacy/" },
|
|
56
|
+
{ "id": "security", "label": "Security", "href": "/security/" }
|
|
57
|
+
],
|
|
58
|
+
"copyright": "Copyright (c) 2026 Meridian Satellite Networks, Inc. All rights reserved."
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -2,15 +2,17 @@
|
|
|
2
2
|
"$type": "page",
|
|
3
3
|
"id": "meridian-not-found",
|
|
4
4
|
"status": "published",
|
|
5
|
-
"layout": "default",
|
|
6
5
|
"metadata": {
|
|
7
6
|
"title": "Page not found — Meridian",
|
|
8
7
|
"description": "The page you are looking for does not exist.",
|
|
9
|
-
"sitemap": {
|
|
8
|
+
"sitemap": {
|
|
9
|
+
"visible": false
|
|
10
|
+
}
|
|
10
11
|
},
|
|
11
12
|
"regions": {
|
|
12
13
|
"main": [
|
|
13
14
|
{
|
|
15
|
+
"$type": "component",
|
|
14
16
|
"id": "not-found-hero",
|
|
15
17
|
"component": "home_hero",
|
|
16
18
|
"props": {
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
"$type": "page",
|
|
3
3
|
"id": "meridian-home",
|
|
4
4
|
"status": "published",
|
|
5
|
-
"layout": "default",
|
|
6
5
|
"metadata": {
|
|
7
6
|
"title": "Meridian — Global Satellite Internet",
|
|
8
7
|
"description": "Connect from anywhere on Earth. Low-latency satellite internet for homes, businesses, and beyond.",
|
|
@@ -2,15 +2,17 @@
|
|
|
2
2
|
"$type": "page",
|
|
3
3
|
"id": "meridian-error",
|
|
4
4
|
"status": "published",
|
|
5
|
-
"layout": "default",
|
|
6
5
|
"metadata": {
|
|
7
6
|
"title": "Something went wrong — Meridian",
|
|
8
7
|
"description": "An unexpected error occurred while serving this page.",
|
|
9
|
-
"sitemap": {
|
|
8
|
+
"sitemap": {
|
|
9
|
+
"visible": false
|
|
10
|
+
}
|
|
10
11
|
},
|
|
11
12
|
"regions": {
|
|
12
13
|
"main": [
|
|
13
14
|
{
|
|
15
|
+
"$type": "component",
|
|
14
16
|
"id": "error-hero",
|
|
15
17
|
"component": "home_hero",
|
|
16
18
|
"props": {
|