Content Recipes

Copy-paste solutions for common content patterns. Each recipe shows the markdown you write and notes on key points.

For deeper explanations, see the Writing Content guide.

Note: These recipes use generic type names (Hero, Features, FAQ, etc.). Your site's template may use different names — check the existing .md files in your site to see what types are available, and your template's documentation for details.


Sections

Hero with Image and CTA Buttons

A bold landing section with headline, description, buttons, and a hero image.

---
type: Hero
theme: gradient
---

#> Welcome to
# Acme Corp
## Build something great

We help teams ship products faster with modern tools and beautiful design.

[Get Started](/signup)
[Watch Demo](/demo)

![Hero illustration](./hero.jpg)
  • The #> label line creates a pretitle ("Welcome to") above the title. A smaller heading directly above the title (### → #) does the same.
  • Standalone links become CTA buttons. The section type decides how they look.
  • The image, links, and paragraphs are ingredients — the section type arranges them.

Multi-Line Hero with Accented Text

A bold hero with a two-line headline and the second line styled differently.

---
type: Hero
theme: dark
---

#> Our Mission
# Build the future
# [with confidence]{accent}

We help teams ship products faster with modern tools and beautiful design.

[Get Started](/signup)
[Learn More](/about)
  • Two consecutive # headings merge into a multi-line title — one <h1> with visual line breaks.
  • [with confidence]{accent} highlights the second line with accent styling (color + bold).
  • The #> label line creates a pretitle ("Our Mission") above the title. A smaller heading directly above the title (### → #) does the same.

Feature Grid with Icons

A grid of feature cards, each with an icon, title, and description.

---
type: Features
---

# Why Choose Us

We've built the tools you need.

### Lightning Fast

![](lu-zap)

Sub-second load times across all devices.

### Bank-Grade Security

![](lu-shield)

Enterprise security with end-to-end encryption.

### Easy Integration

![](lu-plug)

Connect with your existing tools in minutes.

### 24/7 Support

![](lu-headphones)

Real humans ready to help around the clock.

### Analytics Built In

![](lu-bar-chart-3)

Track everything that matters, nothing that doesn't.

### Open Source

![](lu-github)

Transparent, auditable, community-driven.

FAQ Section

Expandable questions and answers.

---
type: FAQ
---

# Frequently Asked Questions

### How do I get started?

Sign up for a free account and follow our quickstart guide. You'll have your first project running in under five minutes.

### Is there a free plan?

Yes! Our free tier includes unlimited projects and up to 3 team members. No credit card required.

### Can I use my own domain?

Absolutely. Connect any custom domain in your project settings. We handle SSL certificates automatically.

### How do I cancel?

You can cancel anytime from your account settings. No questions asked, no hidden fees.
  • Each ### heading becomes a question. The paragraphs below it are the answer.

Pricing Table

Pricing tiers with feature lists.

---
type: Pricing
---

# Simple, Transparent Pricing

Choose the plan that's right for you.

### Starter

$9/month

Perfect for individuals and small projects.

- 5 projects
- 1 team member
- Community support
- Basic analytics

[Get Started](/signup?plan=starter)

### Pro

$29/month

For growing teams that need more.

- Unlimited projects
- 10 team members
- Priority support
- Advanced analytics
- Custom domains

[Get Started](/signup?plan=pro)

### Enterprise

Custom

For organizations with advanced needs.

- Everything in Pro
- Unlimited team members
- Dedicated support
- SLA guarantee
- SSO / SAML

[Contact Sales](/contact)

```yaml:pricing
billingToggle: true
annual:
  starter: 7
  pro: 24
  enterprise: null
```
  • Each ### heading is a pricing tier with its own paragraphs, lists, and links.
  • The YAML data block passes structured data (like billing toggle config) to the section.

Testimonials

Quote cards from customers.

---
type: Testimonials
---

# What Our Customers Say

### Jane Smith

> "Absolutely transformed how we build websites. We shipped our redesign in half the time."

CEO at TechCo

![Jane](./jane.jpg)

### Mike Johnson

> "The best developer experience I've found. My team loves working with it."

CTO at StartupX

![Mike](./mike.jpg)

### Sarah Chen

> "Finally, a tool where our content team and engineering team don't step on each other."

VP Engineering at ScaleUp

![Sarah](./sarah.jpg)
  • Each ### is a person. Their quote uses blockquote syntax (>).
  • The paragraph after the quote is their role/company.
  • Images become avatars. The order of quote, role, and image within each item doesn't matter.

Team Page

Photo + name + role cards.

---
type: Team
---

# Our Team

The people behind the product.

### Sarah Chen

![Sarah](./sarah.jpg)

Lead Engineer

Building systems that scale. Previously at Google and Stripe.

[LinkedIn](https://linkedin.com/in/sarah){target=_blank}

### Alex Rivera

![Alex](./alex.jpg)

Head of Design

Crafting experiences users love. Award-winning designer.

[Portfolio](https://alex.design){target=_blank}

### Jordan Park

![Jordan](./jordan.jpg)

Product Manager

Turning ideas into shipped features. 10 years in SaaS.

[Twitter](https://twitter.com/jordan){target=_blank}
  • Each ### is a team member. Provide their image, role, bio, and links — the section type arranges them.

A set of images displayed in a grid.

---
type: Gallery
---

# Project Gallery

![Mountain landscape](./mountain.jpg)
![City skyline](./city.jpg)
![Ocean sunset](./ocean.jpg)
![Forest trail](./forest.jpg)
![Desert dunes](./desert.jpg)
![Lake reflection](./lake.jpg)
  • Just list your images. The section type handles the gallery layout.
  • Alt text is important for accessibility and may be used as captions.

Logo Cloud

A row of partner or client logos.

---
type: LogoCloud
---

# Trusted By

![Acme Corp](./logos/acme.svg)
![TechCo](./logos/techco.svg)
![StartupX](./logos/startupx.svg)
![ScaleUp](./logos/scaleup.svg)
![BigCorp](./logos/bigcorp.svg)
  • Just list your logo images. Use SVG for best quality at any size.

Contact Form

A form section using structured data for field configuration.

---
type: Contact
---

# Get in Touch

We'd love to hear from you. Fill out the form below and we'll get back to you within 24 hours.

![](lu-mail)

```yaml:form
fields:
  - name: name
    label: Full Name
    type: text
    required: true
  - name: email
    label: Email Address
    type: email
    required: true
  - name: subject
    label: Subject
    type: select
    options:
      - General Inquiry
      - Technical Support
      - Partnership
  - name: message
    label: Message
    type: textarea
    required: true
submitLabel: Send Message
successMessage: Thanks! We'll be in touch soon.
```
  • The YAML data block configures the form. The tag name (form) and field structure depend on what your template's Contact type expects — check your template's documentation.

Header with Navigation

Site-wide header. This lives in layout/header.md.

---
type: Header
---

![Logo](./logo.svg){role=icon}

[Home](/)
[Products](/products)
[Docs](/docs)
[Pricing](/pricing)
[Contact](/contact)
  • A file in layout/ makes this appear on every page.
  • The icon with role=icon becomes the site logo.
  • Standalone links become navigation items.

Auto-navigation alternative: Some Header types automatically build navigation from your page structure, so you may not need to list links manually. Check the header file that came with your template.


Site-wide footer. This lives in layout/footer.md.

---
type: Footer
---

### Product

[Features](/features)
[Pricing](/pricing)
[Changelog](/changelog)
[Roadmap](/roadmap)

### Company

[About](/about)
[Careers](/careers)
[Blog](/blog)
[Press](/press)

### Legal

[Privacy Policy](/privacy)
[Terms of Service](/terms)

---

![](lu-twitter){href="https://twitter.com/example" target=_blank}
![](lu-github){href="https://github.com/example" target=_blank}
![](lu-linkedin){href="https://linkedin.com/company/example" target=_blank}

© 2025 Acme Corp. All rights reserved.
  • Each ### heading creates a link column.
  • Clickable icons (with href) become social media links.
  • The final paragraph is the copyright notice.

Pages & Routes

Adding a New Page

Create a folder under pages/ and add a .md file:

pages/
├── home/
├── about/
└── pricing/          ← new page
    └── content.md
---
type: Pricing
---

# Our Plans

Choose the right plan for you.

The page automatically appears at /pricing and shows up in navigation. The title defaults to the folder name.

To set a custom title, description, or ordering, add a page.yml:

title: Pricing
description: Our plans and pricing
order: 3

Tip: Use index: in site.yml (not pages:) to set your homepage. This way new pages are auto-discovered in navigation without manually updating a list.


Linking Between Pages

Use the page: protocol for internal links that won't break if you reorganize:

[See our pricing](page:pricing)
[Read the docs](page:docs)
[Contact us](page:about#contact)

For simple cases, plain paths work too:

[Pricing](/pricing)

But page: links survive if you move pages to different folders. For pages you link to often, add an id in their page.yml:

# pages/docs/getting-started/installation/page.yml
id: installation
title: Installation Guide

Now [Install guide](page:installation) works no matter where the page lives.


Blog with an Article List and a Page per Article

Set up a blog: a list of articles, a page for each one, and a few more articles at the bottom of each.

1. Declare a query in site.yml (or in queries.yml):

queries:
  articles:
    schema: '@/article'
    sort: date desc

2. Add article files in records/article/ — every file there is a record:

records/article/
├── hello-world.md
├── new-feature.md
└── tips-and-tricks.md

Each article has frontmatter:

---
title: Hello World
date: 2025-01-15
description: Our first blog post
---

Welcome to our blog! Here's what we've been building...

3. Create the blog page, which names the query:

pages/blog/
├── page.yml
└── list.md
# pages/blog/page.yml
title: Blog
query: articles
<!-- pages/blog/list.md -->
---
type: ArticleList
---

# Blog

The latest from our team.

4. Give each article a page, with a [slug] folder inside the blog:

pages/blog/
├── page.yml
├── list.md
└── [slug]/
    ├── article.md
    └── more.md
<!-- pages/blog/[slug]/article.md -->
---
type: Article
---
<!-- pages/blog/[slug]/more.md -->
---
type: ArticleList
fetch:
  query: articles
  current: exclude   # every article except the one this page shows
  limit: 3
---

# More from the blog
  • The [slug] folder is a parametric page: one page per article (/blog/hello-world). It takes the blog page's query: articles, and its Article section shows the article the URL names.
  • The more.md section names the same query, leaves out this page's article, and keeps three.
  • These pages don't appear in navigation — they're reached from the list, and from every list of the query: each article carries $route, the URL of its page, which list components use for the card's link. See Linking to a record.
  • To show the latest three on the home page, add a section there with fetch: { query: articles, limit: 3 }.

Adding Search to Your Site

1. Enable search in site.yml:

services:
  search:
    enabled: true

2. Check your template — most templates include search UI that works automatically once search is enabled.

That's it. The build generates a search index, and the search UI loads it on demand.

Optional configuration:

services:
  search:
    enabled: true
    exclude:
      routes:
        - /admin
        - /draft

See the Search guide for full configuration options.


Content Patterns

Hero with Background Image

Any section can have a background image — just add background: to the frontmatter. The simplest form is a URL:

---
type: Hero
theme: dark
background: /images/hero-bg.jpg
---

# Transform Your Business

Start building with modern tools today.

[Get Started](/signup)

For busy images, add an overlay to keep text readable:

---
type: Hero
theme: dark
background:
  image:
    src: /images/hero-bg.jpg
    position: center
  overlay:
    enabled: true
    type: dark
    opacity: 0.6
---

# Transform Your Business

Start building with modern tools today.

[Get Started](/signup)
  • Background images appear behind the content, covering the full section.
  • Overlays add a semi-transparent layer so text stays readable. Use type: dark or type: light.
  • Adjust opacity (0 to 1) — higher values make the overlay stronger.

Section with Background Color

Any section can use a solid color as its background:

---
type: CTA
theme: dark
background: "#1e1e2e"
---

# Ready to Get Started?

Join thousands of teams already using our platform.

[Sign Up Free](/signup)
  • You can use hex colors (#1e1e2e), CSS color names (navy), or theme variables (var(--primary-900)).
  • When using a dark background color, set theme: dark so the text colors adapt.

Section with Gradient Background

---
type: Hero
theme: dark
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%)
---

# Build Something Beautiful

Modern tools for modern teams.

[Get Started](/signup)
  • Any CSS gradient works: linear-gradient(...), radial-gradient(...), conic-gradient(...).
  • Combine with theme: dark for light text on dark gradients.

Hero with Background Video

---
type: Hero
theme: dark
background:
  video:
    src: /videos/hero.mp4
    poster: /images/hero-poster.jpg
  overlay:
    enabled: true
    type: dark
    opacity: 0.5
---

# See It in Action

Watch how easy it is to get started.

[Try Free](/signup)
  • Video backgrounds automatically show a still image for users who prefer reduced motion.
  • The poster image shows while the video loads.
  • You can also use the simple form: background: /videos/hero.mp4 (video detected by extension).

Multi-Section Page

A complete page with several sections, each using a different type:

pages/home/
├── page.yml
├── 1-hero.md
├── 2-logos.md
├── 3-features.md
├── 4-testimonials.md
├── 5-pricing.md
└── 6-cta.md

Each file has its own type: in the frontmatter. The number prefix controls the order. You can freely add, remove, or reorder sections by changing the filenames.


Quick Reference

Content cheat sheet

What you writeWhat it becomes
# Heading (first)Main title
## Heading (after title)Subtitle
#> Heading (a label line)Pretitle / eyebrow text
ParagraphsBody text
[text](url) on its own lineButton / CTA
![alt](url)Image
![](lu-name)Icon
> quoteBlockquote
- itemList
### After contentNew item (card, entry)
```yaml:tagStructured data

Icon family codes

Browse all icons visually at react-icons.github.io/react-icons.

CodeLibrary
luLucide
hi / hi2Heroicons v1 / v2
fiFeather
piPhosphor
tbTabler
bsBootstrap Icons
mdMaterial Design
aiAnt Design Icons
riRemix Icon
siSimple Icons
io5Ionicons 5
biBoxicons
vscVS Code Codicons
wiWeather Icons
giGame Icons
fa / fa6Font Awesome 5 / 6

Analytics & Third-Party Scripts

To add Google Analytics, tracking pixels, or any other service that asks you to "paste this code into your site's <head>":

  1. Create a file called head.html in your site folder (next to site.yml)
  2. Paste the code the service gives you

That's it. The build injects it into every page automatically.

⚠️ This works where your site's pages are built from your files — uniweb export, or uniweb deploy --host=<adapter>. If you publish to Uniweb Cloud (uniweb publish), the host builds your pages from your synced content and head.html is not applied — your file is kept and synced, but a script in it will not run there.

⭐ For a tracking script, there is a shorter way that works everywhere

If the service gave you a single <script src="…"> line and nothing else — most analytics tools and tag managers do — you can skip head.html and name the URL instead:

# site.yml
services:
  tracking:
    scripts:
      - https://www.example-analytics.com/tag.js?id=YOUR-ID

Same script, same service, same data. The difference is who loads it: the site's runtime does, so it works on every host — including Uniweb Cloud, where head.html does not apply.

It also gets you two things a pasted snippet does not: it is loaded once per page even as visitors move around your site, and if you add consent: required the script is never fetched at all until a visitor agrees, rather than loaded and then asked to behave.

Use head.html instead when the service's snippet has more than a <script src> in it — some add a few inline configuration lines, and those have nowhere to go in a URL. See Tracking for the full reference.

Google Analytics

<!-- site/head.html -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'G-XXXXXXXXXX');
</script>

Replace G-XXXXXXXXXX with your Measurement ID (found in Google Analytics → Admin → Data Streams).

Multiple scripts

You can put as many scripts as you need in head.html. Just paste them one after another:

<!-- Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>/* ... */</script>

<!-- Cookie consent -->
<script src="https://cdn.example.com/consent.js"></script>

See Also

  • Writing Content — Full guide to writing content
  • Layout Areas — Header, footer, and sidebar details
  • Linking — Stable page: links
  • Records — How records work, the records/ folder and its folder.yml, and a page per record
  • Search — Search configuration