@getvitops/generator 8.2.0-alpha.0 → 8.3.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +550 -25
- package/assets/css/index.css +7 -0
- package/assets/css/patterns/banner.css +20 -0
- package/assets/css/patterns/callout.css +39 -0
- package/assets/css/patterns/copy.css +5 -0
- package/assets/css/patterns/embed.css +39 -0
- package/assets/css/patterns/forms.css +19 -0
- package/assets/css/patterns/logos.css +45 -0
- package/assets/css/patterns/marquee.css +16 -0
- package/assets/css/patterns/section.css +53 -0
- package/assets/css/patterns/sitenav.css +262 -0
- package/assets/css/patterns/splitter.css +11 -0
- package/assets/css/patterns/stats.css +61 -0
- package/assets/css/patterns/steps.css +98 -0
- package/assets/css/patterns/table.css +10 -0
- package/assets/css/patterns/tone.css +38 -0
- package/assets/js/consent.js +1 -1
- package/assets/js/elements.js +5 -5
- package/assets/js/polyfills/adoptedStyleSheets.js +1 -1
- package/assets/js/polyfills/css-anchor-positioning-fn.js +2 -2
- package/assets/js/polyfills/popover.js +2 -2
- package/config.schema.json +257 -120
- package/dist/config-BfcWKH-5.mjs +1743 -0
- package/dist/config-BfcWKH-5.mjs.map +1 -0
- package/dist/{config-DvbYx3Gi.mjs → config-Bhg3Xv3D.mjs} +10 -207
- package/dist/config-Bhg3Xv3D.mjs.map +1 -0
- package/dist/config-D5xuz8--.mjs +1807 -0
- package/dist/config-D5xuz8--.mjs.map +1 -0
- package/dist/config.d.mts +157 -211
- package/dist/config.d.mts.map +1 -1
- package/dist/config.mjs +1 -1
- package/dist/{icons-sprite-Bf_KmKeX.d.mts → icons-sprite-CQ5Zj4go.d.mts} +4 -6
- package/dist/icons-sprite-CQ5Zj4go.d.mts.map +1 -0
- package/dist/icons-sprite.d.mts +1 -1
- package/dist/icons-sprite.mjs +1 -2
- package/dist/index.d.mts +49 -35
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +607 -75
- package/dist/index.mjs.map +1 -1
- package/dist/{schema-Dmq1J7S3.d.mts → schema-BV2n2phj.d.mts} +2 -3
- package/dist/{schema-Dmq1J7S3.d.mts.map → schema-BV2n2phj.d.mts.map} +1 -1
- package/dist/schema-C-P9dF9F.d.mts +337 -0
- package/dist/schema-C-P9dF9F.d.mts.map +1 -0
- package/dist/{tokens-8SXMDAd1.d.mts → tokens-BzBbTeTi.d.mts} +2 -6
- package/dist/tokens-BzBbTeTi.d.mts.map +1 -0
- package/dist/{tokens-zi594IZ3.mjs → tokens-C1RJwFeG.mjs} +3 -5
- package/dist/{tokens-zi594IZ3.mjs.map → tokens-C1RJwFeG.mjs.map} +1 -1
- package/dist/tokens-CaIGQQLk.mjs +740 -0
- package/dist/tokens-CaIGQQLk.mjs.map +1 -0
- package/dist/tokens-DH5cpvKd.d.mts +242 -0
- package/dist/tokens-DH5cpvKd.d.mts.map +1 -0
- package/dist/tokens.d.mts +1 -1
- package/dist/tokens.mjs +1 -1
- package/package.json +6 -5
- package/schema.json +95 -5
- package/dist/config-DvbYx3Gi.mjs.map +0 -1
- package/dist/icons-sprite-Bf_KmKeX.d.mts.map +0 -1
- package/dist/tokens-8SXMDAd1.d.mts.map +0 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { a as expandPalette, b as roleHue, d as tokenVar, g as ROLE_TOKEN_KEYS, h as REQUIRED_ROLES, o as functionalRole, x as roleKind } from "./tokens-
|
|
1
|
+
import { a as expandPalette, b as roleHue, d as tokenVar, g as ROLE_TOKEN_KEYS, h as REQUIRED_ROLES, o as functionalRole, x as roleKind } from "./tokens-C1RJwFeG.mjs";
|
|
2
|
+
import { AD_PROVIDERS, AdPropertySchema, AdProviderSchema, BIGIN_DATA_CENTERS, CRM_PROVIDERS, CrmSchema, DeploymentSchema, IndexNowSchema, IndexingSchema, NotificationsSchema, ReviewLocationSchema, ReviewsSchema, SearchConsoleSchema, SearchConsoleSetupSchema, SecuritySchema, TrackingSchema, desc } from "@getvitops/config";
|
|
2
3
|
import * as z from "@zod/mini";
|
|
3
4
|
import { AD_PLATFORMS } from "@getvitops/utils/ads";
|
|
4
5
|
import { TRACKED_PARAMS } from "@getvitops/utils/tracking";
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
// src/token-refs.ts
|
|
7
8
|
/**
|
|
8
9
|
* Cross-layer check: does every `var(--…)` a config authors resolve to a token
|
|
9
10
|
* the generator actually emits?
|
|
@@ -294,8 +295,7 @@ function tokenRefIssues(ds) {
|
|
|
294
295
|
};
|
|
295
296
|
}
|
|
296
297
|
|
|
297
|
-
|
|
298
|
-
//#region src/schema.ts
|
|
298
|
+
// src/schema.ts
|
|
299
299
|
/**
|
|
300
300
|
* Canonical `design-system.json` schema — the single source of truth.
|
|
301
301
|
*
|
|
@@ -308,13 +308,6 @@ function tokenRefIssues(ds) {
|
|
|
308
308
|
* • runtime validation (`validate`) for the CLI and to gate `generate`,
|
|
309
309
|
* • the generated `authoring.md` reference doc (walks `jsonSchema`'s descriptions).
|
|
310
310
|
*/
|
|
311
|
-
/**
|
|
312
|
-
* Attach a JSON-Schema `description`. zod/mini has no `.describe()` method; the
|
|
313
|
-
* mini-API equivalent is `.check(z.describe(…))`, and `.check()` clones — so a
|
|
314
|
-
* shared sub-schema (`Scale`, `CssDecls`, …) can carry a different description
|
|
315
|
-
* per use-site without mutating the original.
|
|
316
|
-
*/
|
|
317
|
-
const desc = (schema, text) => schema.check(z.describe(text));
|
|
318
311
|
const CssDecls = desc(z.record(z.string(), z.string()), "A CSS declaration block: property → value. Values stay strings (they can be hex, var(), clamp(), keywords, …); the generator, not the schema, interprets them.");
|
|
319
312
|
const Scalar = z.union([z.string(), z.number()]);
|
|
320
313
|
const VarMap = z.record(z.string(), Scalar);
|
|
@@ -572,8 +565,7 @@ function validate(input) {
|
|
|
572
565
|
};
|
|
573
566
|
}
|
|
574
567
|
|
|
575
|
-
|
|
576
|
-
//#region src/config.ts
|
|
568
|
+
// src/config.ts
|
|
577
569
|
/**
|
|
578
570
|
* The top-level configuration schema — the umbrella around a
|
|
579
571
|
* `design-system.json`-compliant `designSystem`.
|
|
@@ -792,17 +784,6 @@ const DnsDomainSchema = z.strictObject({
|
|
|
792
784
|
nameservers: z.optional(z.array(z.string())),
|
|
793
785
|
records: z.optional(z.array(DnsRecordSchema))
|
|
794
786
|
});
|
|
795
|
-
/**
|
|
796
|
-
* One domain to onboard into Google Search Console via `vitops search setup`.
|
|
797
|
-
*
|
|
798
|
-
* The verification token is fetched live from the Site Verification API at run
|
|
799
|
-
* time and written to DNS — it is never stored here. What the config records is
|
|
800
|
-
* the *intent*: which domains to onboard, and who should co-own them.
|
|
801
|
-
*/
|
|
802
|
-
const SearchConsoleSetupSchema = z.strictObject({
|
|
803
|
-
delegatedOwners: desc(z.optional(z.array(z.email())), "Emails added as verification owners on the Site Verification web resource. Automated via the API — additive and idempotent, never removes an existing owner."),
|
|
804
|
-
fullUserGroup: desc(z.optional(z.email()), "A Google Group to grant Full-User access in Search Console. SURFACED AS A REMINDER only: Search Console exposes no user/permission API, so this step stays manual by design.")
|
|
805
|
-
});
|
|
806
787
|
const RobotsSchema = z.string();
|
|
807
788
|
const EnvironmentSchema = z.strictObject({
|
|
808
789
|
url: desc(z.url(), "Public origin of this environment."),
|
|
@@ -1010,101 +991,6 @@ const TwitterSchema = z.strictObject({
|
|
|
1010
991
|
image: z.optional(ImageRefSchema)
|
|
1011
992
|
});
|
|
1012
993
|
/**
|
|
1013
|
-
* What `vitops search notify` needs to tell search engines a deploy happened.
|
|
1014
|
-
*
|
|
1015
|
-
* Scoped by what search engines actually accept, which is narrower than it looks:
|
|
1016
|
-
* Google exposes **no** "request indexing" API (the Search Console button is not in
|
|
1017
|
-
* its API, and URL Inspection is read-only), and it removed the sitemap ping
|
|
1018
|
-
* endpoint in 2023. So the sanctioned set is: an accurate sitemap, a Search Console
|
|
1019
|
-
* sitemap resubmit, an IndexNow ping — which Google does *not* honour but Bing,
|
|
1020
|
-
* Yandex, Naver, Seznam and Yep do — and a read-only inspection pass to find out
|
|
1021
|
-
* what Google actually did.
|
|
1022
|
-
*
|
|
1023
|
-
* Facts only, the same rule the legal block follows: this records what the site has
|
|
1024
|
-
* (a key, a property, which pages matter), never what to say about it.
|
|
1025
|
-
*/
|
|
1026
|
-
const IndexNowSchema = z.strictObject({
|
|
1027
|
-
key: desc(z.string().check(z.regex(/^[a-zA-Z0-9-]{8,128}$/)), "IndexNow key (8–128 chars, hex is conventional). NOT a secret — it is served publicly at `keyLocation` so the engine can verify you own the host. Generate one with `vitops search notify --new-key`."),
|
|
1028
|
-
keyLocation: desc(z.optional(z.url()), "Absolute URL of the key file. Defaults to `<canonical>/<key>.txt`; set it only when the file lives elsewhere."),
|
|
1029
|
-
endpoint: desc(z.optional(z.url()), "IndexNow endpoint (default `https://api.indexnow.org/indexnow`). Any participating engine shares submissions with the rest, so one is normally enough.")
|
|
1030
|
-
});
|
|
1031
|
-
const SearchConsoleSchema = z.strictObject({
|
|
1032
|
-
siteUrl: desc(z.string(), "The property exactly as Search Console identifies it — `sc-domain:acme.ca` for a domain property, or the URL-prefix form `https://acme.ca/`. A mismatch here is a 403, not a \"not found\"."),
|
|
1033
|
-
resubmitSitemap: desc(z.optional(z.boolean()), "Re-submit the sitemap through the Search Console API on each notify (default true when `searchConsole` is set). This is the automated equivalent of the manual resubmit in the UI.")
|
|
1034
|
-
});
|
|
1035
|
-
const IndexingSchema = z.strictObject({
|
|
1036
|
-
sitemapUrl: desc(z.optional(z.url()), "The sitemap to submit and to diff for changed URLs. Defaults to `<canonical>/sitemap-index.xml`."),
|
|
1037
|
-
indexNow: desc(z.optional(IndexNowSchema), "IndexNow submission (Bing, Yandex, Naver, Seznam, Yep — not Google). Omit to skip the channel."),
|
|
1038
|
-
searchConsole: desc(z.optional(SearchConsoleSchema), "Google Search Console property. Needs a credential at run time — either a service account in `VITOPS_GSC_SERVICE_ACCOUNT` / `GOOGLE_APPLICATION_CREDENTIALS`, or the user OAuth credential `vitops search setup` uses (`VITOPS_GOOGLE_CLIENT_ID` / `_CLIENT_SECRET` / `_REFRESH_TOKEN`). The service account wins when both are set. Never put a key in this file."),
|
|
1039
|
-
priorityUrls: desc(z.optional(z.array(z.url())), "The pages whose indexing actually matters. `vitops search notify --check` inspects these and exits non-zero if Google has not indexed one. Kept explicit because URL Inspection is quota-bound (2000/day), so checking every page is neither affordable nor informative.")
|
|
1040
|
-
});
|
|
1041
|
-
/**
|
|
1042
|
-
* The ad platforms `vitops ads` can link a site to.
|
|
1043
|
-
*
|
|
1044
|
-
* A closed enum, mirroring `AD_PROVIDER_KEYS` in `@getvitops/utils/ads` — that
|
|
1045
|
-
* module owns what each platform *can do* (whether it verifies a domain, what its
|
|
1046
|
-
* tag is, which click ID it stamps), this owns what a config may *say*. Mirrored
|
|
1047
|
-
* rather than derived because a `z.enum` needs literals to reach the published JSON
|
|
1048
|
-
* Schema; `config.test.ts` asserts the two lists are the same set, so a provider
|
|
1049
|
-
* added to one and not the other fails the build rather than silently getting no
|
|
1050
|
-
* verification step and no tag.
|
|
1051
|
-
*/
|
|
1052
|
-
const AD_PROVIDERS = [
|
|
1053
|
-
"google",
|
|
1054
|
-
"meta",
|
|
1055
|
-
"linkedin",
|
|
1056
|
-
"reddit",
|
|
1057
|
-
"tiktok",
|
|
1058
|
-
"microsoft",
|
|
1059
|
-
"pinterest",
|
|
1060
|
-
"snapchat"
|
|
1061
|
-
];
|
|
1062
|
-
const AdProviderSchema = z.enum(AD_PROVIDERS);
|
|
1063
|
-
/**
|
|
1064
|
-
* One ad property this site is linked to.
|
|
1065
|
-
*
|
|
1066
|
-
* Facts, not prose — the same rule the legal block follows. This records *which*
|
|
1067
|
-
* account and *which* tag id, and the platform capability table decides what can be
|
|
1068
|
-
* done about them. It is also what finally lets the rest of the toolchain see an ad
|
|
1069
|
-
* pixel: the generated cookie notice discloses its cookies, `vitops ads lint`
|
|
1070
|
-
* checks its click ID is captured, and the consent gate is handed the cookie names
|
|
1071
|
-
* to clear on revoke. A pixel pasted into a template is invisible to all three.
|
|
1072
|
-
*/
|
|
1073
|
-
const AdPropertySchema = z.strictObject({
|
|
1074
|
-
accountId: desc(z.optional(z.string()), "The advertising account as the platform shows it — Google Ads customer ID, Meta ad account, LinkedIn partner ID, Reddit advertiser ID. For LinkedIn this is also the Insight Tag id; everywhere else the tag id is `pixelId`."),
|
|
1075
|
-
pixelId: desc(z.optional(z.string()), "The tag/pixel ID the browser snippet initialises — Meta pixel, TikTok pixel, Reddit pixel, Microsoft UET tag ID, Pinterest tag ID, Snap pixel, or the Google Ads conversion ID (`AW-…`, which is NOT the customer ID)."),
|
|
1076
|
-
conversionLabel: desc(z.optional(z.union([z.string(), z.strictObject({
|
|
1077
|
-
call: desc(z.optional(z.string()), "Fired on a tel: link click."),
|
|
1078
|
-
email: desc(z.optional(z.string()), "Fired on a mailto: link click."),
|
|
1079
|
-
form: desc(z.optional(z.string()), "Fired client-side by `vitopsFormConversion()` — the consumer's own submit handler calls it once a form POST succeeds.")
|
|
1080
|
-
})])), "Google Ads only: the conversion action label(s) paired with the `AW-…` conversion ID — either one bare label (back-compat, treated as the `call` action) or a map of action → label, so a call, an email click and a form submission each fire their own Google Ads conversion action instead of all three reporting as the same one."),
|
|
1081
|
-
domain: desc(z.optional(z.string()), "Bare hostname to verify with this platform. Defaults to the host of `domains.canonical` — set it only when the ad account is verified against a different domain."),
|
|
1082
|
-
domainVerification: desc(z.optional(z.string()), "The verification token from the platform UI, for the platforms that verify by DNS TXT (Meta, TikTok, Pinterest, Snapchat). `vitops ads setup` prompts for it and writes it here on first run. NOT a secret — it is published in DNS, and the platform fetching it back is the ownership proof, exactly like the IndexNow key. A value containing `=` is used as the whole record, which is the escape hatch if a platform changes its prefix."),
|
|
1083
|
-
category: desc(z.optional(z.enum(["marketing", "analytics"])), "Consent category the tag waits on (default `marketing`). An ad pixel is advertising by default; `analytics` is for a site using one purely for its own measurement."),
|
|
1084
|
-
enabled: desc(z.optional(z.boolean()), "Set false to keep the property on record without emitting its tag.")
|
|
1085
|
-
});
|
|
1086
|
-
/**
|
|
1087
|
-
* How one location's Google reviews are selected and ordered for display.
|
|
1088
|
-
*
|
|
1089
|
-
* Keyed by `organization.locations` key, mirroring `site.ads`/`site.searchConsole`
|
|
1090
|
-
* — `vitops reviews` needs to know which physical location a fetched review set
|
|
1091
|
-
* belongs to, and that record already exists.
|
|
1092
|
-
*/
|
|
1093
|
-
const ReviewLocationSchema = z.strictObject({
|
|
1094
|
-
accountId: desc(z.optional(z.string()), "GBP account resource id (`accounts/…`), overriding `site.reviews.accountId` for this location."),
|
|
1095
|
-
locationId: desc(z.string(), "GBP location resource id (`locations/…`) to fetch reviews for."),
|
|
1096
|
-
featured: desc(z.optional(z.array(z.string())), "Review ids to always include, in this order, ahead of everything else automatically selected."),
|
|
1097
|
-
minRating: desc(z.optional(z.number()), "Drop reviews below this star rating (default 4) from the automatic (non-featured) selection."),
|
|
1098
|
-
limit: desc(z.optional(z.number()), "Keep at most this many reviews after filtering."),
|
|
1099
|
-
sort: desc(z.optional(z.enum(["recent", "rating"])), "Ordering for the non-featured remainder (default `recent`).")
|
|
1100
|
-
});
|
|
1101
|
-
const ReviewsSchema = z.strictObject({
|
|
1102
|
-
accountId: desc(z.optional(z.string()), "Default GBP account resource id (`accounts/…`) for locations that do not override it."),
|
|
1103
|
-
locations: desc(z.record(z.string(), ReviewLocationSchema), "Which `organization.locations` to fetch Google reviews for, and how each one’s reviews are filtered/ordered. `vitops reviews` writes the result to `.vitops/reviews.json`."),
|
|
1104
|
-
schema: desc(z.optional(z.boolean()), "Emit `Review` JSON-LD for these reviews (default false). Off by default: Google’s structured-data policy treats a business marking up reviews of itself as ineligible for review rich results, and risks a manual action."),
|
|
1105
|
-
avatars: desc(z.optional(z.boolean()), "Render the reviewer’s Google-hosted avatar photo (default false). Off by default: every visitor would otherwise issue a third-party request to googleusercontent.com, and the URLs are not guaranteed to stay live.")
|
|
1106
|
-
});
|
|
1107
|
-
/**
|
|
1108
994
|
* The commercial plan/add-on a site is entitled to — distinct from a `Config`
|
|
1109
995
|
* section's own `enabled` flag. `enabled` answers "does this site do X at
|
|
1110
996
|
* all" (a capability switch); `plan` answers "is this client entitled to turn
|
|
@@ -1120,65 +1006,6 @@ const PlanSchema = z.strictObject({
|
|
|
1120
1006
|
addons: desc(z.optional(z.array(z.string())), "Add-on keys this site is entitled to (e.g. \"ab_testing\", \"server_side_tracking\") — checked against PLAN_CAPABILITIES.")
|
|
1121
1007
|
});
|
|
1122
1008
|
/**
|
|
1123
|
-
* The CRMs this toolchain can push a form submission into.
|
|
1124
|
-
*
|
|
1125
|
-
* A closed enum, mirroring `CrmProvider` in `@getvitops/utils/crm` — that module
|
|
1126
|
-
* owns what each provider's API needs, this owns what a config may say.
|
|
1127
|
-
* Mirrored rather than derived for the same reason `AD_PROVIDERS` is: a
|
|
1128
|
-
* `z.enum` needs literals to reach the published JSON Schema.
|
|
1129
|
-
*/
|
|
1130
|
-
const CRM_PROVIDERS = [
|
|
1131
|
-
"hubspot",
|
|
1132
|
-
"bigin",
|
|
1133
|
-
"jobber"
|
|
1134
|
-
];
|
|
1135
|
-
const CrmProviderSchema = z.enum(CRM_PROVIDERS);
|
|
1136
|
-
const BIGIN_DATA_CENTERS = [
|
|
1137
|
-
"com",
|
|
1138
|
-
"ca",
|
|
1139
|
-
"eu",
|
|
1140
|
-
"in",
|
|
1141
|
-
"com.au",
|
|
1142
|
-
"jp"
|
|
1143
|
-
];
|
|
1144
|
-
const HubSpotConfigSchema = z.strictObject({
|
|
1145
|
-
portalId: desc(z.string(), "The HubSpot portal (hub) ID the form belongs to."),
|
|
1146
|
-
formGuid: desc(z.string(), "The HubSpot form GUID to submit against."),
|
|
1147
|
-
dataCenter: desc(z.optional(z.enum(["na", "eu"])), "Which regional submissions API to post to (default `na`).")
|
|
1148
|
-
});
|
|
1149
|
-
const BiginPipelineConfigSchema = z.strictObject({
|
|
1150
|
-
enabled: desc(z.boolean(), "Also open a Pipelines record for the new/updated contact."),
|
|
1151
|
-
subPipeline: desc(z.optional(z.string()), "Sub-pipeline to file the record under."),
|
|
1152
|
-
stage: desc(z.optional(z.string()), "Starting stage for the pipeline record.")
|
|
1153
|
-
});
|
|
1154
|
-
const BiginConfigSchema = z.strictObject({
|
|
1155
|
-
dataCenter: desc(z.enum(BIGIN_DATA_CENTERS), "The self-client's data centre — determines both the OAuth accounts host and the API host (`www.zohoapis.<dc>`)."),
|
|
1156
|
-
duplicateCheckField: desc(z.optional(z.string()), "Bigin field the upsert dedupes on (default `Email`, Bigin's own unique field)."),
|
|
1157
|
-
pipeline: desc(z.optional(BiginPipelineConfigSchema), "Also open a Pipelines record alongside the Contact.")
|
|
1158
|
-
});
|
|
1159
|
-
const JobberNoteConfigSchema = z.strictObject({ enabled: desc(z.optional(z.boolean()), "Attach a best-effort note carrying the message and unmapped attribution (default true). A failure here never loses the client record itself.") });
|
|
1160
|
-
const JobberConfigSchema = z.strictObject({
|
|
1161
|
-
apiVersion: desc(z.optional(z.string()), "Override the pinned `X-JOBBER-GRAPHQL-VERSION` date this integration is tested against. An escape hatch for an app pinned to a different version — Jobber's schema can change field names between versions."),
|
|
1162
|
-
dedupe: desc(z.optional(z.boolean()), "Look up an existing client by email before creating one (default false pending verification of Jobber's search API against a live schema — see AGENTS.md). Jobber's `clientCreate` has no upsert, so without this a resubmitting visitor creates a second client."),
|
|
1163
|
-
note: desc(z.optional(JobberNoteConfigSchema), "Attach a best-effort note carrying the submitted message and any attribution/extra fields with no dedicated Jobber field.")
|
|
1164
|
-
});
|
|
1165
|
-
/**
|
|
1166
|
-
* A client's CRM, wired to the same conversion route `site.notifications`
|
|
1167
|
-
* already reaches — see AGENTS.md's "CRM submissions" section for why this is
|
|
1168
|
-
* server-side-only and hung off `createConversionRoute()` rather than a
|
|
1169
|
-
* client-side embed. Credentials never live here — the toolchain has no
|
|
1170
|
-
* secret store, matching every other integration.
|
|
1171
|
-
*/
|
|
1172
|
-
const CrmSchema = z.strictObject({
|
|
1173
|
-
provider: desc(CrmProviderSchema, "Which CRM this site pushes form submissions into."),
|
|
1174
|
-
enabled: desc(z.optional(z.boolean()), "Set false to keep the block on record without writing to the CRM."),
|
|
1175
|
-
hubspot: desc(z.optional(HubSpotConfigSchema), "Required when `provider` is `hubspot`."),
|
|
1176
|
-
bigin: desc(z.optional(BiginConfigSchema), "Required when `provider` is `bigin`."),
|
|
1177
|
-
jobber: desc(z.optional(JobberConfigSchema), "Required when `provider` is `jobber`."),
|
|
1178
|
-
fieldMap: desc(z.optional(z.record(z.string(), z.string())), "Submitted form field name → CRM property name. A field with no entry here is dropped, not guessed — an unmapped field never reaches the CRM."),
|
|
1179
|
-
trackingFields: desc(z.optional(z.record(z.string(), z.string())), "`_ac` attribution key (a click-ID param, a UTM param, `landingPage`, `referrer`, or `ab_variant`) → CRM property name. Same drop-if-unmapped rule as `fieldMap`; a visitor with no `_ac` cookie maps to no attribution fields at all, never an error.")
|
|
1180
|
-
});
|
|
1181
|
-
/**
|
|
1182
1009
|
* Which template set the generated legal documents are written against. This is
|
|
1183
1010
|
* a closed enum rather than a free string because an unrecognised value would
|
|
1184
1011
|
* otherwise silently fall back to the wrong body of law; `validateConfig` rejects
|
|
@@ -1274,27 +1101,12 @@ const SiteSectionSchema = z.strictObject({
|
|
|
1274
1101
|
abVariantDimensions: desc(z.optional(z.record(z.string(), z.number())), "Pre-created Matomo custom-dimension index per `site.experiments` key — Matomo requires the dimension to exist in the instance before a value can be pushed for it.")
|
|
1275
1102
|
})), "Matomo instance.")
|
|
1276
1103
|
})), "Analytics provider IDs (gated per environment via `environments.<env>.analytics`). Which provider is set is also what the generated privacy policy and cookie notice disclose — see `legal`."),
|
|
1277
|
-
notifications: desc(
|
|
1278
|
-
|
|
1279
|
-
provider: desc(z.literal("cloudflare"), "Delivery provider. Only Cloudflare Email Sending is implemented; the field is stated so adding another is additive."),
|
|
1280
|
-
to: desc(z.optional(z.email()), "Recipient. Defaults to the primary location’s `email`, then the first location that has one."),
|
|
1281
|
-
from: desc(z.optional(z.email()), "Sender. Defaults to `noreply@<domains.canonical>`. Its domain must be onboarded (`wrangler email sending enable <domain>`) or every send fails."),
|
|
1282
|
-
fromName: desc(z.optional(z.string()), "Display name on the From header. Defaults to `organization.name`."),
|
|
1283
|
-
replyTo: desc(z.optional(z.email()), "Reply-To header."),
|
|
1284
|
-
binding: desc(z.optional(z.string()), "Workers `send_email` binding name (default `EMAIL`). Set it when using a restricted binding."),
|
|
1285
|
-
verifySender: desc(z.optional(z.boolean()), "Set false to skip `vitops email check`'s deploy-time onboarding warning for this site — for a `from` domain the scan cannot see is correct (e.g. built dynamically), which would otherwise be a false positive.")
|
|
1286
|
-
})])), "Where conversion notifications are e-mailed. A bare address is shorthand for `{ provider: \"cloudflare\", to }`."),
|
|
1287
|
-
actionUrl: desc(z.optional(z.string()), "Optional action-link template added to the conversion email (e.g. a link into your ad platform or your own CRM/portal). `{clickId}` is replaced with the ad click ID captured on `_ac` (gclid, fbclid, …). Omitted from the email when the event carries no click ID to interpolate, rather than rendering a broken link.")
|
|
1288
|
-
})), "Where site notifications (form submissions, tracked calls) are sent. TODO: `sms` and `persist` channels — only `email` is implemented."),
|
|
1289
|
-
tracking: desc(z.optional(z.strictObject({
|
|
1290
|
-
enabled: desc(z.optional(z.boolean()), "Capture ad click IDs and UTMs from the landing URL into the `_ac` cookie, for attributing conversions."),
|
|
1291
|
-
category: desc(z.optional(z.enum(["marketing", "analytics"])), "Consent category the `_ac` cookie waits on (default `marketing`). It is a 90-day identifier tying a visitor to the ad that brought them, so it is only written once this category is granted — and asking for it is what raises the banner."),
|
|
1292
|
-
platforms: desc(z.optional(z.array(z.string())), "Informational list of ad platforms in use. Capture recognises every known click-ID parameter regardless.")
|
|
1293
|
-
})), "Ad-click attribution for conversion tracking."),
|
|
1104
|
+
notifications: desc(NotificationsSchema, "Where site notifications (form submissions, tracked calls) are sent. TODO: `sms` and `persist` channels — only `email` is implemented."),
|
|
1105
|
+
tracking: desc(TrackingSchema, "Ad-click attribution for conversion tracking."),
|
|
1294
1106
|
ads: desc(z.optional(z.partialRecord(AdProviderSchema, AdPropertySchema)), "Ad properties this site is linked to, keyed by platform. Read by `vitops ads setup` (ensure the DNS verification record), `vitops ads tags` (emit the consent-gated pixel), and the generated cookie notice (disclose what each pixel stores). Credentials never live here — the DNS write uses CLOUDFLARE_API_TOKEN from the environment."),
|
|
1295
1107
|
reviews: desc(z.optional(ReviewsSchema), "Google Business Profile reviews to cache and display, keyed by `organization.locations`. Read by `vitops reviews`. Credentials never live here — a Google OAuth credential comes from the environment, same as `site.searchConsole`."),
|
|
1296
1108
|
crm: desc(z.optional(CrmSchema), "Push form submissions into a client CRM (HubSpot, Zoho Bigin, or Jobber) alongside the notification email. Read by `createConversionRoute()`'s `crm` option and `vitops crm check`/`vitops crm setup`. Credentials never live here."),
|
|
1297
|
-
security: desc(
|
|
1109
|
+
security: desc(SecuritySchema, "Security integrations (bot protection)."),
|
|
1298
1110
|
legal: desc(z.optional(z.strictObject({
|
|
1299
1111
|
jurisdiction: desc(z.optional(JurisdictionSchema), "Which legal template set the generated documents use. Default `ca`."),
|
|
1300
1112
|
privacyPolicy: z.optional(z.strictObject({
|
|
@@ -1345,15 +1157,7 @@ const SiteSectionSchema = z.strictObject({
|
|
|
1345
1157
|
themeColor: desc(z.optional(z.string()), "Browser UI colour, emitted as `<meta name=\"theme-color\">` on every page — so it applies with or without a manifest. Note it is also half the manifest switch: see `name`."),
|
|
1346
1158
|
backgroundColor: desc(z.optional(z.string()), "Background composited under the OPAQUE generated icons — `apple-touch-icon.png` and the maskable `icon-mask.png` — which are produced whether or not there is a manifest. Defaults to white, so a dark logo on a transparent source needs this set. It is also the manifest `background_color` when one is emitted, but it is not manifest-only.")
|
|
1347
1159
|
})), "Favicon/PWA asset generation (consumed by `@getvitops/utils` favicon tooling)."),
|
|
1348
|
-
deployment: desc(
|
|
1349
|
-
platform: z.optional(z.string()),
|
|
1350
|
-
buildCommand: z.optional(z.string()),
|
|
1351
|
-
deployCommand: z.optional(z.string()),
|
|
1352
|
-
outputDirectory: z.optional(z.string()),
|
|
1353
|
-
type: z.optional(z.string()),
|
|
1354
|
-
repo: desc(z.optional(z.string()), "`owner/name` of this site's GitHub repository. Read by the EmDash design-system-editor plugin route to auto-commit a client's admin edit back to `branch` — see AGENTS.md's \"EmDash plugin as the design-system editing surface\" section. Absent means that sync is skipped (the live override still applies); nothing else in this toolchain reads it today."),
|
|
1355
|
-
branch: desc(z.optional(z.string()), "Branch the design-system-editor sync commits to. Default `\"dev\"` — never `main`/production directly; a commit here still needs this repo's own `promote` PR + admin approval to reach production, the same gate every other change goes through.")
|
|
1356
|
-
})), "How the site is built and deployed (platform, commands, output directory) — informational for tooling.")
|
|
1160
|
+
deployment: desc(DeploymentSchema, "How the site is built and deployed (platform, commands, output directory) — informational for tooling.")
|
|
1357
1161
|
});
|
|
1358
1162
|
const OrganizationSectionSchema = z.extend(OrganizationSchema, {
|
|
1359
1163
|
contact: desc(z.optional(ContactConfigSchema), "Primary contact: either a `locations` key (string reference) or an inline name/email/phone/address object."),
|
|
@@ -1966,6 +1770,5 @@ function formatConfig(value, col = 0, indent = 0) {
|
|
|
1966
1770
|
return JSON.stringify(value) ?? "null";
|
|
1967
1771
|
}
|
|
1968
1772
|
|
|
1969
|
-
//#endregion
|
|
1970
1773
|
export { jsonSchema as A, resolveTheme as C, DesignSystemSchema as D, validateConfig as E, movedTokens as M, SCHEMA_LOCAL_PATH as O, resolvePrivacyContact as S, stripNulls as T, getAt as _, CONFIG_VERSION as a, resolveConfig as b, JURISDICTIONS as c, SiteFontSchema as d, configJsonSchema as f, formatConfig as g, experimentDimensionWarnings as h, CONFIG_SCHEMA_URL as i, validate as j, SCHEMA_URL as k, JURISDICTION_COUNTRIES as l, designSystemPath as m, BIGIN_DATA_CENTERS as n, CRM_PROVIDERS as o, deepMerge as p, CONFIG_SCHEMA_LOCAL_PATH as r, ConfigSchema as s, AD_PROVIDERS as t, PLAN_CAPABILITIES as u, isConfig as v, setAt as w, resolveInput as x, mergePatch as y };
|
|
1971
|
-
//# sourceMappingURL=config-
|
|
1774
|
+
//# sourceMappingURL=config-Bhg3Xv3D.mjs.map
|