Components
Overview
The layer ships 50+ components organized by function across the core layer and opt-in modules. All components follow the complexity budget: max 50 lines, max 5 props, max 2 abstraction layers.
Convert Components
Signal capture components. All include data-testid for testing.
Form
Email/field capture form with anti-spam protection.
No credit card required
::convert-form
---
location: hero
submitLabel: Get Early Access
note: No credit card required
fields:
- name: email
type: email
required: true
- name: company
type: text
placeholder: Company name
---
::
'Get Access'.'stacked'.data-testid: convert-form
External
Link to external payment/booking (Stripe, LemonSqueezy, Cal.com).
::convert-external
---
to: https://buy.stripe.com/...
type: presale
location: pricing
label: Buy Now
variant: button
buttonSize: xl
buttonColor: primary
---
::
| Prop | Type | Default | Description |
|---|---|---|---|
to | string | — (required) | External destination URL |
type | OfferId | — (required) | Offer type identifier |
location | string | — (required) | Tracking location |
label | string | — | Button/card label |
icon | string | — | Icon name |
title | string | — | Card title (card variant) |
description | string | — | Card description |
price | string | — | Price display |
originalPrice | string | — | Strikethrough price |
priceNote | string | — | Price footnote |
badge | string | — | Corner badge text |
variant | 'button' | 'card' | 'button' | Display variant |
highlighted | boolean | false | Visual emphasis |
buttonSize | ButtonProps['size'] | 'xl' | Button size |
buttonVariant | ButtonProps['variant'] | 'solid' | Button variant |
buttonColor | ButtonProps['color'] | 'primary' | Button color |
block | boolean | false | Full-width button |
- data-testid:
convert-external
Internal
Link to internal pages (offers, success pages).
| Prop | Type | Default | Description |
|---|---|---|---|
offerSlug | OfferId | — | Offer tracking identifier |
to | string | — | Internal destination path |
label | string | — | Button/card label |
icon | string | — | Icon name |
variant | 'button' | 'card' | 'button' | Display variant |
size | ButtonProps['size'] | 'md' | Button size |
block | boolean | — | Full-width button |
color | ButtonProps['color'] | 'primary' | Button color |
buttonVariant | ButtonProps['variant'] | 'solid' | Button variant |
description | string | — | Card description |
cardVariant | PageCardProps['variant'] | — | Card variant |
spotlight | PageCardProps['spotlight'] | — | Card spotlight effect |
location | string | — (required) | Tracking location |
- data-testid:
convert-internal
Pricing
Pricing cards with booking links.
| Prop | Type | Default | Description |
|---|---|---|---|
options | BookingOption[] | — (required) | Pricing tier definitions |
Each BookingOption has: url, title, price, originalPrice?, priceNote?, priceInterval?, description, badge?, location, buttonLabel?, buttonVariant?, buttonColor?, highlighted?, features?.
- data-testid:
convert-pricing
Social
Social media icon links.
::convert-social
---
location: footer
size: lg
variant: subtle
color: secondary
rounded: true
gap: normal
---
::
| Prop | Type | Default | Description |
|---|---|---|---|
location | string | — (required) | Tracking location |
size | ButtonProps['size'] | 'xl' | Icon button size |
variant | ButtonProps['variant'] | 'subtle' | Button variant |
color | ButtonProps['color'] | 'secondary' | Button color |
rounded | boolean | true | Rounded buttons |
gap | 'tight' | 'normal' | 'relaxed' | 'normal' | Spacing between icons |
showEmail | boolean | false | Include email link |
- data-testid:
convert-social
SocialShare
Page sharing menu (Twitter, LinkedIn, Facebook, Email, clipboard).
::convert-social-share
---
title: Check out this article
description: A comprehensive guide to product validation
label: Share
size: md
variant: subtle
color: primary
---
::
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | 'Share Page' | Button label |
size | ButtonProps['size'] | 'xl' | Button size |
color | ButtonProps['color'] | 'primary' | Button color |
variant | ButtonProps['variant'] | 'subtle' | Button variant |
trailingIcon | string | 'i-lucide-share' | Trailing icon |
title | string | — (required) | Share title |
description | string | — (required) | Share description |
url | string | — | Override share URL |
- data-testid:
convert-social-share
Rss
RSS feed subscription with reader links (Feedly, Inoreader, NewsBlur, The Old Reader).
| Prop | Type | Default | Description |
|---|---|---|---|
feedPath | string | 'decisions' | Feed collection path |
feedUrl | string | — | Override feed URL |
location | string | — (required) | Tracking location |
size | SelectMenuProps['size'] | 'lg' | Menu size |
variant | SelectMenuProps['variant'] | 'ghost' | Menu variant |
color | SelectMenuProps['color'] | 'neutral' | Menu color |
showLabel | boolean | true | Show RSS label |
label | string | 'RSS' | Button label text |
- Slots:
#item(scoped:{ item }) - data-testid:
convert-rss
Section Components
SectionWrapper
Wraps landing page sections with consistent layout, anchors, and data-testid.
| Prop | Type | Default | Description |
|---|---|---|---|
sectionId | string | — | Section identifier (used for data-testid and anchor) |
| ...PageSectionProps | — | — | All Nuxt UI PageSection props pass through |
- Slots:
#titleplus allPageSectionslots - data-testid:
section-{sectionId}(auto-generated)
Content Components
VideoHtml
HTML5 video player with aspect ratio control.
| Prop | Type | Default | Description |
|---|---|---|---|
src | string | — (required) | Video source URL |
alt | string | 'video' | Video description |
poster | string | — | Poster image |
aspectRatio | 'square' | 'video' | 'portrait' | 'wide' | 'auto' | 'video' | Aspect ratio |
autoplay | boolean | false | Autoplay on load |
loop | boolean | false | Loop playback |
muted | boolean | true | Muted audio |
loading | 'eager' | 'lazy' | 'lazy' | Loading strategy |
VideoIframe
Iframe video embed (YouTube, Vimeo).
| Prop | Type | Default | Description |
|---|---|---|---|
src | string | — (required) | Embed URL |
title | string | 'video' | Iframe title |
aspectRatio | 'square' | 'video' | 'portrait' | 'wide' | 'video' | Aspect ratio |
loading | 'eager' | 'lazy' | 'lazy' | Loading strategy |
CaseStudy
Client testimonial card with optional partner logos.
| Prop | Type | Default | Description |
|---|---|---|---|
client | Client | — (required) | Client info (name, role, company, avatar?, website?, action?) |
quote | string | — (required) | Testimonial text |
partner | { label?, logos? } | — | Partner logo bar |
Changelog
Changelog timeline with author lookup. Provided by the changelog module.
| Prop | Type | Default | Description |
|---|---|---|---|
labelField | keyof ChangelogCollectionItem | 'label' | Grouping label field |
sortField | keyof ChangelogCollectionItem | 'date' | Sort field |
sortOrder | 'ASC' | 'DESC' | 'DESC' | Sort direction |
showAuthor | boolean | true | Show author info |
showImage | boolean | true | Show entry images |
showScrollTop | boolean | true | Show scroll-to-top button |
scrollTopThreshold | number | 500 | Scroll threshold for button |
emptyTitle | string | 'No items yet' | Empty state title |
emptyDescription | string | 'Check back soon for updates.' | Empty state text |
emptyIcon | string | 'i-lucide-inbox' | Empty state icon |
ComparisonList
Two-column comparison (e.g., "Without Foundry" vs "With Foundry").
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | — | Section title |
left | Column | — (required) | Left column (title, icon?, color?, description?, items?) |
right | Column | — (required) | Right column |
- Slots:
default(optional alert slot)
FeatureGrid
Grid of feature cards.
| Prop | Type | Default | Description |
|---|---|---|---|
features | Feature[] | — (required) | Feature items (title?, description?, icon?, to?, target?) |
columns | 2 | 3 | 4 | 3 | Grid columns |
orientation | 'horizontal' | 'vertical' | 'vertical' | Card layout |
FaqAccordion
FAQ accordion with content-driven items.
| Prop | Type | Default | Description |
|---|---|---|---|
items | AccordionItemData[] | — | FAQ items (label, content, icon?, color?, slot?) |
types | string[] | — | Filter by FAQ type |
FounderBio
Founder profile card.
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | — (required) | Founder name |
intro | string | — (required) | Introduction text |
avatar | string | — | Avatar image path |
Cited / Defn
Inline citation and definition markers for academic content. Provided by the docs module (Cited requires citations: true, Defn requires glossary: true).
| Component | Prop | Type | Description |
|---|---|---|---|
Cited | id | string (required) | Citation reference ID |
Defn | id | string (required) | Glossary term ID |
Both provide default slot for wrapping content.
Confetti
Celebration animation trigger.
| Prop | Type | Default | Description |
|---|---|---|---|
particleCount | number | 100 | Number of particles |
spread | number | 70 | Spread angle |
originY | number | 0.6 | Y origin position |
App Components
AppBanner
Site-wide banner bar. Configured via navigation.yml banner field. No props — reads from injected banner_config.
AppLogo
Site logo with light/dark variants from app config.
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | — | Override logo title |
AppHeader / AppFooter
Structural wrapper components that compose header and footer from sub-components. No direct props — sub-components read from injected navigation data.
Header slots: #title, #body, #right, #toggle (scoped: { open, toggle })
Footer slots: #top, #left, #right, #bottom
Navigation Components
Anchor
In-page anchor point for scroll navigation.
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | — (required) | Anchor identifier |
Cta
Call-to-action card with configurable layout.
| Prop | Type | Default | Description |
|---|---|---|---|
cta | CtaConfig | — | CTA config (headline?, message?, primary?, button) |
title | string | — | Override title |
description | string | — | Override description |
variant | 'outline' | 'solid' | 'soft' | 'subtle' | 'naked' | 'outline' | Card variant |
orientation | 'vertical' | 'horizontal' | 'vertical' | Layout direction |
- Slots:
#links
Page Components
PageSplit
Two-column page layout.
| Prop | Type | Default | Description |
|---|---|---|---|
maxWidth | 'xl' | '2xl' | ... | 'full' | '7xl' | Container max width |
gap | number | 8 | Column gap |
- Slots:
#left,#right
OG Image Components
OgImageDocs / OgImageLanding
Open Graph image generation templates for docs and landing pages.
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | 'title' | OG image title |
description | string | 'description' | OG image description |
headline | string | — | Optional headline |
Docs Components
Provided by the docs module. These are registered when docs.enabled is true in your layer config.
DocsAsideLeftBody, DocsAsideLeftTop, DocsAsideRightBottom, DocsPageHeaderLinks — Structural docs layout components with no props. They read from injected navigation data and useContentConfig().
Bibliography, GlossaryTable, SourcesTable — Content feature components for citations and glossary. Registered when their respective sub-features are enabled (citations: true, glossary: true).
ProseA
Custom prose anchor override with external link detection.
| Prop | Type | Default | Description |
|---|---|---|---|
href | string | '' | Link URL |
target | string | — | Link target |
- Slots:
default