@verisure-italy/lp-types
v2.0.0
Published
Types for Landing Page service
Readme
@verisure-italy/lp-types
Domain contracts for landing pages, widgets, presets, SEO metadata, and build manifests.
Installation
pnpm add @verisure-italy/lp-typesMain Exports
- raw catalogs such as
themeNames,layoutVariants,pageStatuses,buildStatuses,deploymentProviders,widgetTypes, andtextFormats - enums for themes, layout variants, page status, build status, deployment provider, widget type, and text format
- shared widget primitives such as
imagePropsSchema widgetSchemaand the individual widget-property schemaspageSchema,pageWidgetConfigSchema,landingPageDataSchemabuildSchema,buildManifestSchema, andglobalManifestSchema
What This Package Gives You
- an authoring model for landing pages and widget presets
- a runtime-safe discriminated union for widget rendering
- build and deployment metadata for page publishing flows
- reusable text, image, and navigation primitives for page composition
Schema Inventory
| Schema | Type alias | Kind | Purpose |
| --- | --- | --- | --- |
| imagePropsSchema | ImageProps | object schema | Shared image primitive |
| themeNameSchema | ThemeName | enum | Page theme |
| layoutVariantSchema | LayoutVariant | enum | Layout variant |
| pageStatusSchema | PageStatus | enum | Publication status |
| buildStatusSchema | BuildStatus | enum | Build status |
| seoMetadataSchema | SeoMetadata | object schema | SEO metadata |
| deploymentProviderSchema | DeploymentProvider | enum | Deployment provider |
| widgetAlignmentSchema | WidgetAlignment | enum | Widget alignment values |
| widgetIconTokenSchema | WidgetIconToken | string schema | Namespaced icon token (provider:name) |
| widgetIconSchema | n/a | nullable string schema | Nullable namespaced icon token |
| widgetTypeSchema | WidgetType | enum | Widget discriminator |
| widgetContentBoxSubTypeSchema | WidgetContentBoxSubType | enum | Content-box variants |
| widgetContentListSubTypeSchema | WidgetContentListSubType | enum | Content-list variants |
| widgetCostsItemVisibilitySchema | WidgetCostsItemVisibility | enum | Costs-item visibility |
| textFormatSchema | TextFormat | enum | Text formatting mode |
| textContentSchema | TextContent | union | Rich text primitive |
| widgetAnchorIdSchema | WidgetAnchorId | string schema | DOM anchor id without # |
| widgetHeroSchema | WidgetHero | object schema | Hero widget |
| widgetProductSliderSchema | WidgetProductSlider | object schema | Product-slider widget |
| widgetCostsSchema | WidgetCosts | object schema | Costs widget |
| widgetContentBoxSchema | WidgetContentBox | object schema | Content-box widget |
| widgetTrustpilotSchema | WidgetTrustpilot | object schema | Trustpilot widget |
| widgetFAQSchema | WidgetFAQ | object schema | FAQ widget |
| widgetStatsSchema | WidgetStats | object schema | Stats widget |
| widgetContentListSchema | WidgetContentList | object schema | Content-list widget |
| widgetPropertyTypeSchema | WidgetPropertyType | object schema | Property-type widget |
| widgetAlarmTypeComparisonSchema | WidgetAlarmTypeComparison | object schema | Alarm-comparison widget |
| widgetHeaderMenuLinkSchema | WidgetHeaderMenuLink | discriminated union | Header menu links |
| widgetHeaderSchema | WidgetHeader | object schema | Header widget |
| widgetFooterMenuItemSchema | WidgetFooterMenuItem | object schema | Footer menu item |
| widgetFooterMenuSectionSchema | WidgetFooterMenuSection | object schema | Footer menu section |
| widgetFooterSchema | WidgetFooter | object schema | Footer widget |
| widgetSchema | Widget | discriminated union | Full widget union |
| widgetPresetSchema | WidgetPreset | object schema | Stored widget preset |
| pageWidgetConfigSchema | PageWidgetConfig | discriminated union | Stored page widget config |
| pageSchema | Page | object schema | Persisted page |
| buildManifestPageSchema | BuildManifestPage | object schema | Compact page in build artifacts |
| buildManifestSchema | BuildManifest | object schema | Build manifest |
| globalManifestSchema | GlobalManifest | object schema | Current, previous, and pending manifests |
| resolvedLandingPageWidgetConfigSchema | ResolvedLandingPageWidgetConfig | discriminated union | Widget config with resolved widget payload |
| landingPageDataSchema | LandingPageData | object schema | Frontend-ready page payload |
| buildSchema | Build | object schema | Build execution record |
Enum Reference
| Schema | Values |
| --- | --- |
| themeNameSchema | light, dark, modern, minimal, vibrant, professional |
| layoutVariantSchema | default, marketing |
| pageStatusSchema | draft, published, needs_republish |
| buildStatusSchema | pending, building, completed, failed |
| deploymentProviderSchema | amplify, apprunner |
| widgetAlignmentSchema | left, center, right |
| widgetIconTokenSchema | string matching ^[a-z0-9][a-z0-9-]*:[a-z0-9][a-z0-9-]*$ |
| widgetTypeSchema | hero, productSlider, costs, contentBox, trustpilot, faq, stats, contentList, propertyType, alarmTypeComparison, header, footer |
| widgetContentBoxSubTypeSchema | zerovision, videoSurveillance |
| widgetContentListSubTypeSchema | keyStrengths, howItWorks |
| widgetCostsItemVisibilitySchema | desktop, mobile |
| textFormatSchema | plain, markdown |
Primitive Schema Reference
imagePropsSchema
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| src | string | Yes | Valid URL |
| alt | string | Yes | Non-empty alt text |
| width | number | No | Positive |
| height | number | No | Positive |
| lazy | boolean | No | Lazy-load flag |
widgetIconTokenSchema and widgetIconSchema
| Rule | Value |
| --- | --- |
| Token format | provider:name |
| Regex | ^[a-z0-9][a-z0-9-]*:[a-z0-9][a-z0-9-]*$ |
| widgetIconTokenSchema | Required namespaced token |
| widgetIconSchema | Same token, but nullable |
Valid examples:
mui:homemui:shield-outlinedfa:housecustom:my-icon
Invalid examples:
homekeymui:homemui:MUI:home
widgetAnchorIdSchema
| Rule | Value |
| --- | --- |
| Type | string |
| Required | Yes |
| Validation | Must match ^[a-z0-9-]+$ and does not include the leading # |
textContentSchema
| Variant | Shape | Notes |
| --- | --- | --- |
| Plain string | string | Must be non-empty |
| Structured content | { value: string; format: TextFormat } | value must be non-empty |
seoMetadataSchema
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| title | string | Yes | Min 1, max 60 |
| description | string | Yes | Min 1, max 160 |
| keywords | string[] | Yes | Keyword list |
| canonicalUrl | string | No | Valid URL |
| ogImage | string | No | Valid URL |
| ogTitle | string | No | Optional override |
| ogDescription | string | No | Optional override |
| robots | string | No | Robots directive |
| languageAlternates | array | No | { lang, url }[] |
Page and Build Schemas
widgetPresetSchema
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| id | string | Yes | Preset id |
| name | string | Yes | Preset name |
| tags | string[] | Yes | Tag list |
| widget | Widget | Yes | Widget payload |
| createdAt | number | Yes | Shared timestamp |
| updatedAt | number | Yes | Shared timestamp |
pageWidgetConfigSchema
Common fields:
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| id | string | Yes | Config id |
| pageId | string | Yes | Page id |
| configType | 'preset' \| 'custom' | Yes | Variant discriminator |
| order | number | Yes | Non-negative integer |
| anchorId | string \| null | No | Optional widget anchor id |
| createdAt | number | Yes | Shared timestamp |
| updatedAt | number | Yes | Shared timestamp |
Variant-specific fields:
| Variant | Additional fields |
| --- | --- |
| preset | presetId: string |
| custom | widget: Widget |
pageSchema
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| id | string | Yes | Page id |
| slug | string | Yes | Must match ^[a-z0-9-]+$ |
| name | string | Yes | Non-empty |
| description | string | No | Optional |
| widgets | PageWidgetConfig[] | Yes | Widget config list |
| theme | ThemeName | Yes | Theme enum |
| layoutVariant | LayoutVariant | No (default) | Defaults to default |
| seo | SeoMetadata | Yes | SEO metadata |
| status | PageStatus | Yes | Publication state |
| requiresRebuild | boolean | Yes | Build flag |
| version | number | Yes | Positive integer |
| publishedAt | number | No | Optional publish timestamp |
| createdAt | number | Yes | Shared timestamp |
| updatedAt | number | Yes | Shared timestamp |
buildManifestPageSchema
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| id | string | Yes | Page id |
| slug | string | Yes | Page slug |
| name | string | Yes | Page name |
| theme | ThemeName | Yes | Page theme |
| layoutVariant | LayoutVariant | No (default) | Defaults to default |
buildManifestSchema
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| buildId | string | Yes | Build id |
| createdAt | string | Yes | ISO timestamp |
| pagesCount | number | Yes | Non-negative integer |
| pages | BuildManifestPage[] | Yes | Included pages |
globalManifestSchema
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| current | BuildManifest \| null | Yes (nullable) | Current deployment |
| previous | BuildManifest \| null | Yes (nullable) | Previous deployment |
| new | BuildManifest \| null | Yes (nullable) | Pending or new deployment |
resolvedLandingPageWidgetConfigSchema
Same base fields as pageWidgetConfigSchema, but both variants include a widget payload:
| Variant | Additional fields |
| --- | --- |
| preset | presetId, widget |
| custom | widget |
landingPageDataSchema
landingPageDataSchema is pageSchema with widgets replaced by ResolvedLandingPageWidgetConfig[].
buildSchema
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| id | string | Yes | Build id |
| status | BuildStatus | Yes | Build state |
| deploymentProvider | DeploymentProvider \| null | No | Deployment backend |
| deploymentId | string \| null | No | Provider-specific id |
| deploymentRef | string \| null | No | Provider-specific ref |
| deploymentTarget | string \| null | No | Deployment target |
| deploymentStatus | string \| null | No | Provider status |
| amplifyBuildId | string \| null | No | Deprecated field |
| amplifyJobUrl | string \| null | No | Deprecated field |
| startedAt | number \| null | Yes (nullable) | Start timestamp |
| completedAt | number \| null | No | Completion timestamp |
| duration | number \| null | No | Duration |
| pagesCount | number \| null | Yes (nullable) | Number of pages |
| pageIds | string[] | Yes | Included page ids |
| error | string \| null | No | Error message |
| s3BucketPath | string \| null | Yes (nullable) | Artifact path |
| createdAt | number | Yes | Shared timestamp |
| updatedAt | number | Yes | Shared timestamp |
Widget Schemas
widgetSchema
Each widget is exported through widgetSchema with a type discriminator and a properties object.
| type value | properties schema |
| --- | --- |
| hero | widgetHeroSchema |
| productSlider | widgetProductSliderSchema |
| costs | widgetCostsSchema |
| contentBox | widgetContentBoxSchema |
| trustpilot | widgetTrustpilotSchema |
| faq | widgetFAQSchema |
| stats | widgetStatsSchema |
| contentList | widgetContentListSchema |
| propertyType | widgetPropertyTypeSchema |
| alarmTypeComparison | widgetAlarmTypeComparisonSchema |
| header | widgetHeaderSchema |
| footer | widgetFooterSchema |
widgetHeroSchema
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| title | TextContent | Yes | String or { value, format } |
| subtitle | TextContent \| null | No | Optional |
| body | TextContent \| null | No | Optional |
| primaryOffer | TextContent \| null | No | Optional |
| secondaryOffer | TextContent \| null | No | Optional |
| cta | object or null | No | Contains label, funnelPath, and funnelSlug |
| media.desktop | ImageProps[] | Yes | At least one image |
| media.mobile | ImageProps[] \| null | No | Optional |
widgetProductSliderSchema
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| title | TextContent | Yes | Title |
| description | TextContent \| null | Yes (nullable) | Description block |
| items | array | Yes | Each item contains image, title, description, featured |
widgetCostsSchema
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| title | TextContent | Yes | Title |
| subtitle | TextContent \| null | Yes (nullable) | Subtitle |
| description | TextContent \| null | Yes (nullable) | Description |
| items | array | Yes | Each item contains title, description, icon (provider:name or null), visibility[] |
widgetContentBoxSchema
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| subType | enum | Yes | zerovision or videoSurveillance |
| title | TextContent | Yes | Title |
| description | TextContent \| null | Yes (nullable) | Description |
| box | object | Yes | Contains title, description, image, alignment |
widgetTrustpilotSchema
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| title | TextContent | Yes | Title |
| description | TextContent \| null | Yes (nullable) | Description |
| config.businessUnitId | string | Yes | Non-empty |
| config.templateId | string | Yes | Non-empty |
| config.styleHeight | string | Yes | Non-empty |
| config.styleWidth | string | Yes | Non-empty |
| config.locale | string | Yes | Non-empty |
widgetFAQSchema
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| title | TextContent | Yes | Title |
| description | TextContent \| null | Yes (nullable) | Description |
| items | array | Yes | Each item contains question and answer |
widgetStatsSchema
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| items | array | Yes | Each item contains label, value, and optional icon (provider:name or null) |
widgetContentListSchema
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| subType | enum | Yes | keyStrengths or howItWorks |
| title | TextContent | Yes | Title |
| description | TextContent \| null | Yes (nullable) | Description |
| items | array | Yes | Each item contains title, description, and optional image |
widgetPropertyTypeSchema
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| title | TextContent | Yes | Title |
| description | TextContent \| null | Yes (nullable) | Description |
| tabs | array | Yes | Each tab contains title, description, image, cta |
widgetAlarmTypeComparisonSchema
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| title | TextContent | Yes | Title |
| description | TextContent \| null | Yes (nullable) | Description |
| tabs | array | Yes | Each tab contains title, description, image, icon (provider:name or null) |
| box | object | Yes | Contains title, description, icon (provider:name or null) |
Icon Migration Notes (Breaking)
Legacy non-namespaced icon values are no longer valid.
| Old value | New value |
| --- | --- |
| home | mui:home |
| key | mui:key |
| operator | custom:operator |
If an icon is not provided, keep using null where the field is nullable.
Example payload update:
// before (invalid from v2)
{ icon: 'home' }
// after
{ icon: 'mui:home' }widgetHeaderMenuLinkSchema
| Variant | Fields |
| --- | --- |
| anchor | label, anchor where anchor must match ^#[a-z0-9-]+$ |
| external | label, url |
| widgetAnchor | label, targetWidgetConfigId |
widgetHeaderSchema
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| logo | ImageProps | Yes | Logo image |
| logoLink | string \| null | No | Optional URL |
| menu | object or null | No | Contains enabled and optional items[] |
widgetFooterMenuItemSchema
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| label | TextContent | Yes | Menu item label |
| url | string | Yes | Valid URL |
widgetFooterMenuSectionSchema
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| title | TextContent | Yes | Section title |
| items | WidgetFooterMenuItem[] | Yes | At least one link |
widgetFooterSchema
| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| paragraphs | TextContent[] \| null | No | Optional |
| menuSections | array or null | No | Each section contains title and items[] |
| phone | TextContent \| null | No | Optional |
| address | TextContent \| null | No | Optional |
| copyright | TextContent \| null | No | Optional |
| customerServiceLink | object or null | No | Contains label and url |
Example
import { widgetSchema } from '@verisure-italy/lp-types'
const hero = widgetSchema.parse({
type: 'hero',
properties: {
title: 'Protect your home',
media: {
desktop: [
{
src: 'https://example.com/hero.jpg',
alt: 'Alarm system',
},
],
},
},
})