Authoritative field-level guide to every block type shipped in WECO v1.0.0.
Effective: 2026-05-11 · Applies to release ≥ v1.0.0 · Canonical source: shared/blocks.ts in the release tarball. For high-level feature catalog see features.html.
What is a block?
A block is a reusable content module that renders as one section of a published SPV landing page. A site is an ordered sequence of blocks arranged in the admin drag-and-drop editor. Every block supports per-block styling (background colour, padding), visibility toggling, and optional investor gating. Schema v2 added per-language text variants: every text field is a LocalizedText (plain string for single-language sites, or a LocalizedString map keyed by BCP-47 language code). The renderer resolves the right value via pickLocale(), preserving byte-for-byte equivalence for configs that stay monolingual.
Index
Block catalog
1. Navigation block.type === 'navigation'Shipped
Purpose
Sticky top navigation bar with logo, site title, anchor-based menu links, and optional phone number.
Fields
title: LocalizedText — site/brand title (required).
menu: Array<{label, anchor, url?}> — clickable items; url wins over anchor and accepts absolute URLs, mailto:/tel:, or same-host slug paths like /site/other-slug/ (required; ≥1 item).
logo_ref?: string — asset reference for the logo image.
phone?: string — phone number displayed in the nav.
Editor flow
Operator pastes a title, uploads a logo (or leaves empty for text-only), adds menu items with labels and anchor targets or external URLs. Per-language title support is automatic when the site has multiple languages.
Rendered output
Fixed-position top bar with logo + title on the left, menu links in the centre, phone number on the right. Menu links scroll to in-page anchors or navigate to external URLs. On mobile, the menu collapses to a hamburger.
Typical use
Every SPV page needs a navigation bar; place this block first (order 0) to lock it at the top.
i18n
The title and each menu item's label are localisable. Multi-language sites add a language switcher pill to the nav automatically.
2. Hero block.type === 'hero'Shipped
Purpose
Full-width banner section with headline, optional subtitle, background image, and optional call-to-action button.
Fields
title: LocalizedText — headline (required).
legal_subtitle?: LocalizedText — secondary text (disclaimer, tagline).
bg_image_ref?: string — asset reference for the banner background image.
bg_color?: string — fallback CSS colour if no image (inherits from style.bg_color).
cta_slot?: CtaSlot — optional button with label + URL.
Editor flow
Operator enters the headline, optionally adds a subtitle and background image, and can attach a CTA button with custom label and link target.
Rendered output
Full-width coloured or image-backed banner with headline centred. If a background image is set, it scales to cover the entire banner. The CTA button appears below the headline if configured.
Typical use
Place at the top of the page (after navigation) to introduce the fund or deal with a striking visual.
i18n
title, legal_subtitle, and the CTA button label are localisable.
3. Text + Image block.type === 'text_image'Shipped (legacy)
Purpose
Deprecated — use Activity block with layout: 'image-left' or 'image-right' instead. Kept for back-compat; identical to a plain-variant Activity block.
rows: DocumentRow[] — array of {id, title, file_ref, date?, size?, mime: 'application/pdf', allow_download?} (required; ≥1 row). allow_download: true overrides the watermark gate and lets the visitor download the raw unstamped PDF.
Editor flow
Operator uploads PDF files, enters titles and optional dates, and toggles allow_download per document. Watermark mode (corner, compliance, off) is configured at the site level in the Document Security tab, not per-block.
Rendered output
List of PDF titles with dates and View/Download buttons. View opens an in-page PDF.js viewer; Download (if allowed) saves the raw PDF. When watermarking is on, the viewer renders a stamped version (email + timestamp + masked IP) on every page; direct download is refused unless allow_download: true.
Typical use
Fund prospectuses, pitch decks, term sheets, cap tables — anything requiring watermarking or access control.
i18n
Each row's title is localisable.
5. Footer block.type === 'footer'Shipped
Purpose
Three-column footer with rich-text content in each column (company info, contact links, legal disclaimers).
Fields
col1, col2, col3: {heading: LocalizedText, rich_text: LocalizedText} — three independent columns (all required). Rich text supports bold, italic, colour.
Editor flow
Operator fills in three column headings and body text. Columns are typically "About", "Contact", "Legal".
Rendered output
Three-column layout (responsive stack on mobile) with headings and body text. Rendered at the bottom of the page.
Typical use
Place last on every page to provide contact info, copyright, and legal links.
i18n
All headings and body text are localisable.
6. Activity block.type === 'activity'Shipped
Purpose
Flexible text section with optional variant styling (normal, quote, disclaimer, callout), optional image, bullet list, and optional CTA button.
Operator enters heading, body text, and optional bullets. Picks a variant (quotes are indented + italicised, disclaimers use a border, callouts use a highlight colour). If layout is not 'prose', uploads an image. A CTA slot can be added below the body.
Rendered output
Styled text section with optional image and bullet list. Variant controls visual treatment; layout arranges text and image. Mobile always stacks vertically.
Typical use
Fund strategy, team background, investment process, risk disclosures, any prose-heavy section.
i18n
Heading, body text, each bullet, and CTA label are localisable.
7. News block.type === 'news'Shipped
Purpose
Time-ordered list of news items, filings, or announcements with optional date grouping.
Fields
title: LocalizedText (required).
rows: NewsRow[] — {date, summary, external_link} (required; ≥1 row). date is ISO-8601.
Operator enters a title, adds news items with date, summary text, and external link. When grouping is set, the renderer buckets items by period and renders a muted header.
Rendered output
Chronological list (newest first). If grouping is enabled, items are bucketed with headers. Each item shows date + summary; clicking opens the external link.
Typical use
Fund announcements, regulatory filings, quarterly updates, investor letters.
i18n
Title and each row's summary are localisable.
8. Contacts block.type === 'contacts'Shipped
Purpose
Contact information card with address, phone, email, business hours, and optional embedded map.
Fields
address?: LocalizedText · phone?: string · email?: string · hours?: LocalizedText · map_embed?: string (iframe HTML from Google Maps / Yandex / OpenStreetMap).
Editor flow
Operator fills in address, phone, email, and hours. Can paste an <iframe> embed code to show a map.
Rendered output
Card with address, phone, email, and hours formatted nicely. Map embed (if present) renders below the text in a sandboxed iframe.
Typical use
Fund office address, GP contact details, investor relations office hours.
i18n
Address and hours are localisable; phone and email are not.
9. Accordion block.type === 'accordion'Shipped
Purpose
Collapsible question-and-answer pairs, optionally arranged in a responsive grid.
rows: Record<string, LocalizedText>[] — row objects mapping column keys to cell values (required; can be empty).
Editor flow
Operator enters a title, adds columns, populates rows. CSV paste is supported: header becomes column labels, rows are parsed.
Rendered output
Responsive HTML table. Mobile may horizontal-scroll or switch to card layout.
Typical use
Fee schedules, cap table, timeline milestones, performance data.
i18n
Title, column labels, and all cell values are localisable.
11. Divider block.type === 'divider'Shipped
Purpose
Visual spacer or horizontal rule between sections.
Fields
height: 'sm' | 'md' | 'lg' — vertical space (required).
hairline: boolean — when true, renders a thin horizontal rule.
Editor flow
Operator chooses space height and toggles the hairline option.
Rendered output
Blank vertical space (optionally with a thin horizontal rule at the top).
Typical use
Break between major sections; use instead of relying on padding for explicit spacing control.
i18n
None — purely structural.
12. Stats block.type === 'stats'Shipped
Purpose
Key performance indicators as metric tiles with value, label, optional delta direction, and optional CTA.
Fields
heading?: LocalizedText.
items: {value, label, delta_pct?, delta_direction?}[] (required; ≥1). value is a plain string ("$1.2B", "+8.3%") because the operator decides whether it translates.
columns?: 2 | 3 | 4 (default 3).
cta_slot?: CtaSlot.
Editor flow
Operator enters optional heading, adds tiles with value/label/delta, chooses column count, optionally adds a CTA.
Rendered output
Grid of metric tiles. Each tile shows the value (large), label (small), and optionally a coloured up/down delta pill. Grid stacks on tablet/mobile.
Typical use
Fund size, AUM, return rate, number of investors, deployment speed.
i18n
Heading and each tile's label are localisable. The value stays a plain string.
13. Team block.type === 'team'Shipped
Purpose
Grid of team members or advisors with photo, name, title, bio, and optional social links.
Operator enters optional heading, uploads images, fills in alt text and captions (alt is for accessibility).
Rendered output
Single image or grid of images. Each image is clickable to open a lightbox viewer (no JS required — native CSS technique). Alt text on hover; captions appear below each image.
Typical use
Property photos, fund strategy visualisations, team event photos, deal documentation.
i18n
Heading, alt text, and caption are localisable.
15. Logos block.type === 'logos'Shipped
Purpose
Trust bar or partner logos (auditors, co-investors, partners) in a single responsive row with optional captions and links.
Fields
heading?: LocalizedText.
items: {ref, alt, link_url?, caption?}[] (required; ≥1). alt is required for accessibility.
Editor flow
Operator enters optional heading, uploads logos, fills in alt text (required), and optionally adds a caption + URL. Captions are typically used for accreditation statements ("Audited by", "Member of").
Rendered output
Single row of logos (greyscale by default, full colour on hover). Clickable if a URL is set. Captions render in a muted tone below each logo.
Typical use
Auditor/bank logos, co-investor partners, industry memberships, regulatory approvals.
i18n
Heading, alt text, and caption are localisable. The link_url is a plain string.
16. Call-to-Action block.type === 'cta'Shipped
Purpose
Standalone full-width button block with optional heading and subheading.
Operator enters optional heading/subheading, required button label and URL, chooses visual style and size.
Rendered output
Centred section with optional heading, optional subheading, and a large button. Visual treatment depends on button_style.
Typical use
"Request prospectus", "Schedule a call", "Sign up", "Download whitepaper" — placed between sections to interrupt scroll and prompt action.
i18n
Heading, subheading, and label are localisable.
17. Schedule block.type === 'schedule'Shipped
Purpose
Event schedule with countdown timer, calendar grid, or list display. Supports recurring events with date arithmetic.
Fields
heading?: LocalizedText.
items: {name, datetime, recurrence?, offset_days?, description?, link_url?}[] (required; ≥1). datetime is ISO-8601 UTC; recurrence is one of 'none' | 'daily' | 'weekly' | 'monthly' | 'monthly_first_day' | 'monthly_last_day' | 'monthly_last_business_day' | 'quarterly' | 'yearly'. The renderer computes the next upcoming instance and uses it for countdown display.
Operator enters optional heading, adds events with name, date/time (local timezone converted to UTC by the editor), recurrence rule, optional day offset, description, and link. Chooses display mode.
Rendered output
Countdown shows a timer to the next instance; calendar shows a grid with highlighted dates; list shows rows of events. Recurring events are rolled forward deterministically so the next upcoming instance is always shown.
Typical use
Bond fix dates, quarterly distribution dates, investor update calls, annual meetings, syndication close dates.
i18n
Heading, name, and description are localisable. datetime and link_url are plain strings.
18. Embed block.type === 'embed'Shipped
Purpose
Custom embed for external content (HTML snippets or iframe URLs) rendered in a sandboxed iframe.
Fields
mode: 'html' | 'url' (required).
content: string — HTML string or URL depending on mode (required).
height?: number (default 500) · width?: string (default '100%').
heading?: LocalizedText.
Editor flow
Operator chooses mode, pastes HTML or URL, optionally adjusts height/width and heading.
Rendered output
Sandboxed iframe (sandbox="allow-scripts"). The iframe cannot access cookies, localStorage, or the rest of the page — prevents malicious scripts from stealing session data. If the remote domain sends framing headers, the iframe will not load (renderer warns in the editor).
Heading is localisable. Content is not translated.
19. Q&A block.type === 'qa'Shipped v0.0.79+
Purpose
Investor question inbox. Visitors submit questions; the GP triages and answers in the admin Inbox tab. Display mode controls whether threads are public or hidden from other visitors.
mode?: 'request_form' | 'public_thread' (default 'request_form'). Request-form shows a form but does NOT list questions publicly. Public-thread lists all approved Q&A pairs for all visitors.
anonymous_to_other_investors?: boolean — when public-thread + true, other visitors see "Anonymous"; the GP still sees the real email in the inbox.
Editor flow
Operator enters heading and optional intro, chooses visibility and mode, toggles anonymity if using public-thread.
Rendered output
Request-form mode shows email + question fields; submissions appear in the admin Inbox (not on the public site). Public-thread mode shows the list of approved Q&A pairs.
Typical use
Fund investor relations Q&A, deal investor engagement, private equity information request management.
i18n
Heading and intro are localisable.
20. Capital tracker block.type === 'capital'Shipped v0.0.82+
Purpose
LP capital tracker showing committed, called, distributed, and NAV per investor. Each row is gated to the matching investor session (never exposed to other investors).
Fields
heading?: LocalizedText.
currency?: string — ISO 4217 (default 'USD').
rows: {investor_email, committed, called, distributed, nav, last_updated?, nav_history?}[] (required; ≥1). Row is keyed by investor_email (case-insensitive). The renderer does NOT emit row HTML directly; it renders a placeholder, then a client-side hydration script calls GET /sites/<slug>/capital/me with the investor session cookie and receives ONLY the row for the logged-in investor's email.
show_nav_history?: boolean — when true, draws a sparkline using nav_history points (default false).
Editor flow
Operator enters optional heading, picks currency, adds investor rows with email, committed, called, distributed, NAV, optional last-update timestamp, optional NAV time series.
Rendered output
Placeholder at render time. On page load in an investor's browser, a script calls the host API with the investor cookie, receives that investor's row, and fills the table. Other visitors see nothing or only their own row.
Typical use
SPV cap table, LP dashboard, fund commitment tracking.
i18n
Heading is localisable. Email, numbers, and timestamps are plain strings.
Standalone investor magic-link login surface. Visible only when the investor portal is enabled; renders nothing when disabled (safe to place and toggle later).
Operator enters optional heading, optional intro, optional button label. Everything else (email field, NDA checkbox, accreditation checkbox if configured) is auto-generated from site-level Investor Portal settings.
Rendered output
Email input, required NDA checkbox, optional accreditation checkbox (if configured in Investors → Settings). Submit button sends a magic-link mint request. When the investor IS authenticated (cookie ff_inv_<slug> valid), the block shows "Signed in as <email>" + a Sign out button. When the portal is disabled, the block renders nothing.
Typical use
Multi-language sites that need a dedicated login page, or sites with gated content but no traditional "investor portal".
i18n
Heading, intro, and button label are all localisable.
Theme presets
Every site has a theme object (schema v2+; v1 configs are back-filled with Classic Corporate). The renderer reads the theme and emits CSS custom properties for headings, body fonts, colours, border radius, and container width. The following 11 curated presets are available via one-click apply in the Design tab:
Classic Corporate — Deep navy + warm gold, serif headings + sans body (Source Serif 4 + Inter). Reads JPMorgan-adjacent. Default for v1 back-fill.
Modern Minimal — Monochrome + electric blue accent, sans-serif (Inter). Stripe / Linear aesthetic.
Financial Gold — Emerald + refined gold on cream, serif + sans (Playfair + Lato). Old-money private-equity vibe.
Dark Professional — Deep charcoal background + teal accent, sans-serif (Space Grotesk + Inter). Hedge-fund / quant aesthetic.
Sunset Bronze — Bronze + teal on cream, serif + sans (Playfair + Lato). Boutique merchant-bank feel.
Ocean Slate — Slate blue + soft cyan on linen, sans-serif (Inter). Coastal / maritime; pairs with infrastructure funds.
Forest Sage — Sage green + walnut on cream, mixed (Source Serif + Inter). ESG / sustainable fund aesthetic.
Pastel Calm — Soft mauve + lavender on cream, serif (Playfair + Lato). Wealth managers, art funds.
High Contrast — Pure black/white + amber accent. WCAG AAA contrast on all text-on-background pairs.
Brutalist Yellow — Black + yellow on neutral, sans-serif (Space Grotesk + Inter). Editorial, attention-grabbing.
Custom themes can be built by editing colours, fonts, radius, heading style, and container width directly in the Design tab. Operators can also create custom font pairs from the Google Fonts library.