DeployCode Deployment
Deploy as Sites
Create static and dynamic websites with MDX
Deploy MDX as Sites
Documentation Status: This documentation describes the planned API design for the .do platform. Code examples represent the intended interface and may not reflect the current implementation state. See roadmap for implementation status.
Create beautiful, performant websites with MDX - from static marketing sites to dynamic content platforms.
Overview
Deploy MDX as sites to create:
- Marketing Sites - Landing pages, product pages, company websites
- Documentation - Technical docs, API references, guides
- Blogs - Personal blogs, company blogs, publications
- Portfolios - Showcase work, projects, case studies
flowchart LR
A[MDX Content] --> B{Rendering Strategy}
B -->|Static| C[SSG]
B -->|Dynamic| D[SSR]
B -->|Hybrid| E[ISR]
C --> F[Pre-rendered HTML]
D --> G[On-demand HTML]
E --> H[Cached + Revalidated HTML]
F --> I[CDN]
G --> I
H --> I
I --> J[User]
Static Site Generation
Simple Marketing Site
---
title: Welcome to Our Product
description: The best solution for your needs
---
# Transform Your Business with AI
Our platform helps you automate, optimize, and scale your operations.
## Features
<FeatureGrid>
<Feature icon="⚡" title="Lightning Fast" description="Built for performance from the ground up" />
<Feature icon="🔒" title="Secure by Default" description="Enterprise-grade security and compliance" />
<Feature icon="📈" title="Scales Automatically" description="From zero to millions of users" />
</FeatureGrid>
## Get Started Today
<CTASection>
<Button href="/signup">Start Free Trial</Button>
<Button href="/demo" variant="secondary">
Watch Demo
</Button>
</CTASection>Blog Site
---
title: My Blog
description: Thoughts on technology and development
---
export async function getAllPosts() {
return await $.db.posts.find({
where: { status: 'published' },
orderBy: { publishedAt: 'desc' },
})
}
export async function getPost(slug: string) {
return await $.db.posts.findOne({
where: { slug }
})
}
// Blog index page
export default async function BlogIndex() {
const posts = await getAllPosts()
return (
<div className="blog-index">
<h1>Latest Posts</h1>
<div className="post-grid">
{posts.map((post) => (
<PostCard key={post.id} post={post} />
))}
</div>
</div>
) }
// Individual post page
export async function BlogPost({ params }) {
const post = await getPost(params.slug)
if (!post) {
return <NotFound />
}
return (
<article className="blog-post">
<header>
<h1>{post.title}</h1>
<time>{post.publishedAt.toLocaleDateString()}</time>
</header>
<MDXContent source={post.content} />
<footer>
<ShareButtons post={post} />
<Comments postId={post.id} />
</footer>
</article>
) }Server-Side Rendering
Dynamic Content Site
---
title: Product Catalog
description: Browse our products
---
export async function getProducts(params: { category?: string; page: number }) {
return await $.db.products.find({
where: params.category ? { category: params.category } : {},
limit: 20,
offset: (params.page - 1) * 20
})
}
export default async function ProductCatalog({ searchParams }) {
// Server-side data fetching
const products = await getProducts({
category: searchParams.category,
page: parseInt(searchParams.page || '1')
})
return (
<div className="catalog">
<CategoryFilter />
<div className="product-grid">
{products.map((product) => (
<ProductCard key={product.id} product={product} />
))}
</div>
<Pagination total={products.total} page={searchParams.page} />
</div>
) }Incremental Static Regeneration
Content That Updates
export async function getStaticProps() {
const posts = await $.db.posts.find({ limit: 10 })
return {
props: { posts },
revalidate: 3600 // Regenerate every hour
}
}
export default function RecentPosts({ posts }) {
return (
<div>
<h2>Recent Posts</h2>
{posts.map(post => (
<PostPreview key={post.id} post={post} />
))}
</div>
)
}Interactive Components
Newsletter Signup
export async function subscribeToNewsletter(email: string) {
return await $.db.subscribers.create({
email,
subscribedAt: new Date()
})
}
export function NewsletterSignup() {
const [email, setEmail] = useState('')
const [status, setStatus] = useState('idle')
async function handleSubmit(e) {
e.preventDefault()
setStatus('loading')
try {
await subscribeToNewsletter(email)
setStatus('success')
setEmail('')
} catch (error) {
setStatus('error')
}
}
return (
<form onSubmit={handleSubmit}>
<h3>Subscribe to our newsletter</h3>
<input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="[email protected]" required />
<button type="submit" disabled={status === 'loading'}>
{status === 'loading' ? 'Subscribing...' : 'Subscribe'}
</button>
{status === 'success' && <p>Thanks for subscribing!</p>}
{status === 'error' && <p>Error. Please try again.</p>}
</form>
) }SEO Optimization
Metadata
---
title: Product Name | Company Name
description: Detailed product description for search engines
keywords: [product, solution, industry]
og:
image: /images/product-og.jpg
type: website
twitter:
card: summary_large_image
creator: '@company'
---
export function generateMetadata({ params }) {
return {
title: `${params.title} | Our Company`,
description: params.description,
openGraph: {
title: params.title,
description: params.description,
images: [params.image]
}
}
}Structured Data
export function BlogPostSchema({ post }) {
return (
<script type="application/ld+json">
{JSON.stringify({
'@context': 'https://schema.org',
'@type': 'BlogPosting',
headline: post.title,
datePublished: post.publishedAt,
author: {
'@type': 'Person',
name: post.author.name
}
})}
</script>
)
}Performance Optimization
Image Optimization
export function OptimizedImage({ src, alt }) {
return (
<$.Image
src={src}
alt={alt}
width={800}
height={600}
loading="lazy"
formats={['webp', 'avif']}
/>
)
}Code Splitting
import { lazy, Suspense } from 'react'
const HeavyComponent = lazy(() => import('./HeavyComponent'))
export function Page() {
return (
<div>
<Header />
<Suspense fallback={<Loading />}>
<HeavyComponent />
</Suspense>
</div>
)
}Internationalization
export async function getStaticPaths() {
const locales = ['en', 'es', 'fr', 'de']
const paths = locales.map((locale) => ({ params: { locale } }))
return { paths }
}
export default function Page({ params }) {
const t = $.i18n.use(params.locale)
return (
<div>
<h1>{t('welcome')}</h1>
<p>{t('description')}</p>
</div>
) }Analytics
Built-in Analytics
export default function Page() {
useEffect(() => {
$.analytics.pageView({
page: '/products',
title: 'Product Catalog'
})
}, [])
return <ProductCatalog />
}Deployment Configuration
// do.config.ts
export default {
sites: [
{
name: 'marketing-site',
source: './site',
deployment: {
type: 'static', // or 'ssr', 'isr'
domain: 'example.do',
build: {
output: 'static',
prerender: ['/', '/about', '/pricing', '/blog'],
},
cdn: {
enabled: true,
cache: {
static: '1y',
html: '1h',
api: '5m',
},
},
},
},
],
}