From 8548bb6c7ce44159b75d86c4b001a91b7817ca24 Mon Sep 17 00:00:00 2001 From: RedStar Date: Sun, 18 Oct 2026 22:38:31 +0200 Subject: [PATCH] feat(marketing): lead with evidence and drop unsupported claims The hero now says what Code Zero does and starts from observe mode, and its terminal is labelled as an illustrative excerpt using a command the CLI accepts (`zero review --proactive`). The social image dropped the removed `--mode` flag as well. The testimonials named people and companies the project cannot back up, so the section, its copy and its schema are gone. The feature grid uses typed layout slots instead of ids and icons, the logo strip reads as a sentence plus a row, and page controls follow the 44 px marketing density. A header test that clicked an external link now prevents the navigation instead of opening a real URL. --- apps/marketing/README.md | 2 +- apps/marketing/app/pages/index.vue | 1 - apps/marketing/config/content.ts | 32 +++------- apps/marketing/content.config.ts | 2 +- .../modules/home/components/CallToAction.vue | 16 +++-- .../modules/home/components/FeatureGrid.vue | 37 +++++++---- .../modules/home/components/Hero.vue | 64 +++++++++++-------- .../modules/home/components/LogoCloud.vue | 14 ++-- .../modules/home/components/Testimonials.vue | 40 ------------ .../modules/shared/components/site/Header.vue | 17 ++--- apps/marketing/nuxt.config.ts | 4 +- apps/marketing/public/og-image.svg | 10 +-- .../test/nuxt/components/Header.spec.ts | 13 ++++ apps/marketing/test/unit/content.test.ts | 16 +---- apps/marketing/uno.config.ts | 7 +- packages/i18n/locales/en/marketing.json | 31 ++------- packages/i18n/locales/it/marketing.json | 31 ++------- packages/i18n/schemas/marketing.schema.json | 63 ------------------ packages/ui/DESIGN.md | 5 +- 19 files changed, 138 insertions(+), 267 deletions(-) delete mode 100644 apps/marketing/modules/home/components/Testimonials.vue diff --git a/apps/marketing/README.md b/apps/marketing/README.md index 6452b2a3..01d63e33 100644 --- a/apps/marketing/README.md +++ b/apps/marketing/README.md @@ -126,7 +126,7 @@ Two deliberate exclusions: Icons reached through a `:name` binding cannot be found by the icon scanner. When a new icon comes from `config/content.ts`, add its list to `icon.clientBundle.icons` in `nuxt.config.ts` the way -`featureCards` and `logoCloud` already are, or it will silently render as an empty box. +`logoCloud` already is, or it will silently render as an empty box. ## Adding or editing a legal document diff --git a/apps/marketing/app/pages/index.vue b/apps/marketing/app/pages/index.vue index fba5ded0..0c24d4a2 100644 --- a/apps/marketing/app/pages/index.vue +++ b/apps/marketing/app/pages/index.vue @@ -3,7 +3,6 @@ - diff --git a/apps/marketing/config/content.ts b/apps/marketing/config/content.ts index 5e98da2c..b51960d4 100644 --- a/apps/marketing/config/content.ts +++ b/apps/marketing/config/content.ts @@ -1,6 +1,6 @@ /** - * Structure of the landing page: which cards exist, in which order, and which translation key and - * icon each one carries. + * Structure of the landing page: which cards exist, in which order, and which translation key + * each one carries. * * Copy itself lives in `@code-zero/i18n` (`locales//marketing.json`) so translators work * from one place and Lunaria can report staleness. This file only holds what is not language — @@ -11,15 +11,7 @@ export interface FeatureCard { /** Key under `marketing.features.items`; also the Vue list key. */ readonly id: string; - /** Lucide icon name resolved by `@nuxt/icon` from the locally installed collection. */ - readonly icon: string; -} - -export interface Testimonial { - /** Key under `marketing.testimonials.items`. */ - readonly id: string; - /** Initials rendered in the avatar tile; no remote images on a page that must stay fast. */ - readonly initials: string; + readonly layout: 'lead' | 'standard' | 'wide'; } export interface FaqEntry { @@ -48,20 +40,14 @@ export interface PricingPlan { export const pricingCurrency = 'USD'; export const featureCards = [ - { id: 'observe', icon: 'lucide:eye' }, - { id: 'runner', icon: 'lucide:shield-check' }, - { id: 'verify', icon: 'lucide:circle-check-big' }, - { id: 'models', icon: 'lucide:cpu' }, - { id: 'sandbox', icon: 'lucide:box' }, - { id: 'policy', icon: 'lucide:scale' }, + { id: 'observe', layout: 'lead' }, + { id: 'runner', layout: 'standard' }, + { id: 'verify', layout: 'standard' }, + { id: 'models', layout: 'standard' }, + { id: 'sandbox', layout: 'standard' }, + { id: 'policy', layout: 'wide' }, ] as const satisfies readonly FeatureCard[]; -export const testimonials = [ - { id: 'one', initials: 'MC' }, - { id: 'two', initials: 'JW' }, - { id: 'three', initials: 'AO' }, -] as const satisfies readonly Testimonial[]; - export const faqEntries = [ { id: 'write' }, { id: 'models' }, diff --git a/apps/marketing/content.config.ts b/apps/marketing/content.config.ts index 74c9b88a..0f6db56a 100644 --- a/apps/marketing/content.config.ts +++ b/apps/marketing/content.config.ts @@ -14,7 +14,7 @@ const legalSchema = z.object({ /** * Frontmatter every blog post declares. `date` is the publication date (ISO 8601) the listing * sorts by; `tag` is a single lowercase category the listing can filter on; `authorInitials` - * feeds the same initials-tile avatar the testimonials use — this site ships no portrait images. + * feeds the initials-tile avatar — this site ships no portrait images. */ const blogSchema = z.object({ title: z.string(), diff --git a/apps/marketing/modules/home/components/CallToAction.vue b/apps/marketing/modules/home/components/CallToAction.vue index 886ddc44..6eb321cc 100644 --- a/apps/marketing/modules/home/components/CallToAction.vue +++ b/apps/marketing/modules/home/components/CallToAction.vue @@ -1,15 +1,19 @@