Custom Landing Pages
Lito gives you complete control over your landing page design. Whether you want a simple config-driven page or a fully custom HTML/CSS/JS experience, Lito supports it.
Landing Page Types
| Type | Best For | Complexity |
|---|---|---|
default | Quick start, no customization needed | None |
config | Simple hero + features from JSON | Low |
sections | Mix of custom and default sections | Medium |
custom | Full creative control with HTML/CSS/JS | High |
none | No landing, go straight to docs | None |
Quick Start
Option 1: Config-Based (Simplest)
Just add a landing object to your docs-config.json:
{ "landing": { "enabled": true, "hero": { "title": "Build Amazing Docs", "subtitle": "The easiest way to create beautiful documentation", "cta": [ { "label": "Get Started", "href": "/introduction", "variant": "primary" }, { "label": "View on GitHub", "href": "https://github.com", "variant": "secondary" } ] }, "features": [ { "title": "Fast", "description": "Built on Astro for speed", "icon": "bolt" }, { "title": "Flexible", "description": "Customize everything", "icon": "settings" }, { "title": "Modern", "description": "Beautiful out of the box", "icon": "sparkles" } ] }}Option 2: Full Custom Landing
For complete control, create a _landing/ folder:
docs/├── _landing/│ ├── index.html # Your landing page HTML│ ├── styles.css # Your custom styles│ ├── script.js # Interactive features│ └── assets/ # Images, icons, fonts├── introduction.mdx└── docs-config.jsonThen configure:
{ "landing": { "type": "custom", "source": "_landing", "injectNav": true, "injectFooter": true }}Creating a Custom Landing Page
Step 1: Create the _landing/ Folder
mkdir docs/_landingStep 2: Create index.html
<section class="hero"> <div class="hero-content"> <h1>Welcome to <span class="highlight">MyProduct</span></h1> <p class="subtitle">The best way to build amazing things</p> <div class="cta-buttons"> <a href="/introduction" class="btn btn-primary">Get Started</a> <a href="https://github.com" class="btn btn-secondary">GitHub</a> </div> </div></section>
<section class="features"> <h2>Why Choose Us?</h2> <div class="feature-grid"> <div class="feature-card"> <div class="icon">⚡</div> <h3>Lightning Fast</h3> <p>Built for performance from the ground up.</p> </div> <div class="feature-card"> <div class="icon">🎨</div> <h3>Beautiful Design</h3> <p>Looks great without any configuration.</p> </div> <div class="feature-card"> <div class="icon">🔧</div> <h3>Fully Customizable</h3> <p>Tailor every aspect to your brand.</p> </div> </div></section>Step 3: Add Styles (styles.css)
.hero { min-height: 80vh; display: flex; align-items: center; justify-content: center; text-align: center; background: linear-gradient(135deg, var(--primary-50) 0%, var(--primary-100) 100%); padding: 4rem 2rem;}
.hero-content h1 { font-size: 3.5rem; font-weight: 800; margin-bottom: 1rem;}
.hero-content .highlight { color: var(--primary-600);}
.subtitle { font-size: 1.5rem; color: var(--gray-600); margin-bottom: 2rem;}
.cta-buttons { display: flex; gap: 1rem; justify-content: center;}
.btn { padding: 0.875rem 2rem; border-radius: 0.5rem; font-weight: 600; text-decoration: none; transition: all 0.2s;}
.btn-primary { background: var(--primary-600); color: white;}
.btn-primary:hover { background: var(--primary-700);}
.btn-secondary { background: white; color: var(--gray-900); border: 1px solid var(--gray-200);}
.btn-secondary:hover { background: var(--gray-50);}
.features { padding: 6rem 2rem; max-width: 1200px; margin: 0 auto;}
.features h2 { text-align: center; font-size: 2.5rem; margin-bottom: 3rem;}
.feature-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 2rem;}
.feature-card { background: white; padding: 2rem; border-radius: 1rem; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); text-align: center;}
.feature-card .icon { font-size: 3rem; margin-bottom: 1rem;}
.feature-card h3 { margin-bottom: 0.5rem;}Step 4: Add Interactivity (script.js)
// Animate elements on scrolldocument.addEventListener('DOMContentLoaded', () => { const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('animate-in'); } }); }, { threshold: 0.1 });
document.querySelectorAll('.feature-card').forEach(card => { observer.observe(card); });});Section-Based Landing
For a mix of custom and default components, use the section-based approach:
{ "landing": { "type": "sections", "sections": [ { "type": "hero", "source": "default", "props": { "title": "Build Something Amazing", "subtitle": "Start your documentation journey" } }, { "type": "custom", "html": "_landing/features.html" }, { "type": "cta", "source": "default" }, { "type": "custom", "html": "_landing/pricing.html" } ] }}Create individual section files:
<section class="custom-features"> <!-- Your custom features HTML --></section><section class="pricing-table"> <!-- Your custom pricing HTML --></section>Using Theme Variables
Your custom landing page has access to Lito’s theme CSS variables:
/* Primary colors */var(--primary-50) through var(--primary-950)
/* Gray scale */var(--gray-50) through var(--gray-950)
/* Semantic colors */var(--success), var(--warning), var(--danger), var(--info)
/* Typography */var(--font-sans)var(--font-mono)This ensures your landing page matches the rest of your documentation site.
Custom Navbar and Footer
By default, Lito renders the site’s Header and Footer components on landing pages. You can replace them with custom HTML or hide them entirely.
Custom HTML Navbar/Footer
Place files in your _landing/ folder:
docs/├── _landing/│ ├── index.html # Main landing content│ ├── navbar.html # Custom navbar (replaces default Header)│ ├── footer.html # Custom footer (replaces default Footer)│ ├── styles.css│ └── script.jsOr specify paths in config:
{ "landing": { "type": "custom", "navbar": { "html": "_landing/navbar.html" }, "footer": { "html": "_landing/footer.html" } }}Accepted navbar file names: navbar.html, nav.html, header.html.
Hiding Navbar and Footer
Set navbar or footer to false to completely remove them from the landing page. This is useful when your custom landing has its own navigation built in.
{ "landing": { "type": "custom", "navbar": false, "footer": false }}You can mix and match — hide one while keeping the other:
{ "landing": { "type": "custom", "navbar": false, "footer": { "html": "_landing/footer.html" } }}| Value | Behavior |
|---|---|
| Omitted | Default Header/Footer component renders |
{ "html": "..." } | Custom HTML replaces the default component |
false | No navbar/footer rendered at all |
This works with both custom and sections landing types.
Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
type | string | config | custom, sections, config, default, none |
source | string | _landing | Folder containing custom landing files |
navbar | object | false | — | Custom navbar HTML or false to hide |
footer | object | false | — | Custom footer HTML or false to hide |
Disabling the Landing Page
To skip the landing page entirely:
{ "landing": { "enabled": false }}Or:
{ "landing": { "type": "none" }}This redirects visitors directly to your documentation.
Best Practices
Keep It Fast
Optimize images, minimize JavaScript, and leverage CSS for animations.
Stay Accessible
Use semantic HTML, proper heading structure, and sufficient color contrast.
Mobile First
Design for mobile screens first, then enhance for larger displays.
Match Your Brand
Use your brand colors via the --primary-* CSS variables.
Framework Support
Custom landing pages work across all supported frameworks:
| Framework | How It Works |
|---|---|
| Astro | Generates index.astro with scoped styles |
| React | Creates LandingPage.jsx component |
| Next.js | Generates app/page.jsx |
| Vue | Creates LandingPage.vue SFC |
Your HTML/CSS/JS source files remain the same regardless of the target framework.