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

TypeBest ForComplexity
defaultQuick start, no customization neededNone
configSimple hero + features from JSONLow
sectionsMix of custom and default sectionsMedium
customFull creative control with HTML/CSS/JSHigh
noneNo landing, go straight to docsNone

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.json

Then configure:

{
"landing": {
"type": "custom",
"source": "_landing",
"injectNav": true,
"injectFooter": true
}
}

Creating a Custom Landing Page

Step 1: Create the _landing/ Folder

Terminal window
mkdir docs/_landing

Step 2: Create index.html

docs/_landing/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)

docs/_landing/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)

docs/_landing/script.js
// Animate elements on scroll
document.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:

docs/_landing/features.html
<section class="custom-features">
<!-- Your custom features HTML -->
</section>
docs/_landing/pricing.html
<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.

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.js

Or 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.

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" }
}
}
ValueBehavior
OmittedDefault Header/Footer component renders
{ "html": "..." }Custom HTML replaces the default component
falseNo navbar/footer rendered at all

Configuration Options

OptionTypeDefaultDescription
typestringconfigcustom, sections, config, default, none
sourcestring_landingFolder containing custom landing files
navbarobject | falseCustom navbar HTML or false to hide
footerobject | falseCustom 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

bolt

Keep It Fast

Optimize images, minimize JavaScript, and leverage CSS for animations.

universal-access

Stay Accessible

Use semantic HTML, proper heading structure, and sufficient color contrast.

mobile

Mobile First

Design for mobile screens first, then enhance for larger displays.

palette

Match Your Brand

Use your brand colors via the --primary-* CSS variables.

Framework Support

Custom landing pages work across all supported frameworks:

FrameworkHow It Works
AstroGenerates index.astro with scoped styles
ReactCreates LandingPage.jsx component
Next.jsGenerates app/page.jsx
VueCreates LandingPage.vue SFC

Your HTML/CSS/JS source files remain the same regardless of the target framework.