.do
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',
          },
        },
      },
    },
  ],
}
  • Apps - Interactive applications
    • MDX - MDX capabilities
    • Components - UI components
  • APIs - API integration