.do

Executable Code

Embed TypeScript/JavaScript directly in your MDX files for dynamic content generation

Executable Code

Embed TypeScript/JavaScript directly in your MDX files:

export const greeting = 'Hello, World!'

export function greet(name: string) {
  return `Hello, ${name}!`
}

export const timestamp = new Date().toISOString()

<div>{greet('MDX')} - Generated at {timestamp}</div>

The code is executed at build time or runtime, allowing you to:

  • Generate content dynamically
  • Validate data against schemas
  • Transform and process information
  • Create interactive experiences
  • Compute values from structured data
  • Implement business logic

Why Executable Code?

Embedding code in MDX enables powerful capabilities:

  • Dynamic content: Generate content based on data or context
  • Data transformation: Process and transform structured data
  • Business logic: Implement calculations and rules
  • Integration: Fetch data from APIs or databases
  • Validation: Ensure data meets requirements
  • Automation: Reduce manual work through code

Export Variables

Define and export constants:

export const siteTitle = 'My Documentation'
export const version = '1.0.0'
export const lastUpdated = new Date().toLocaleDateString()

# {siteTitle}

Version: {version} | Last updated: {lastUpdated}

Export Functions

Define reusable functions:

export function formatCurrency(amount: number) {
  return new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency: 'USD'
  }).format(amount)
}

export function calculateDiscount(price: number, discount: number) {
  return price * (1 - discount / 100)
}

Price: {formatCurrency(99.99)}
Discounted: {formatCurrency(calculateDiscount(99.99, 20))}

Import External Modules

Import and use external libraries:

import { format } from 'date-fns'
import { z } from 'zod'

export const formattedDate = format(new Date(), 'PPP')
export const schema = z.object({
  name: z.string(),
  age: z.number()
})

Today's date: {formattedDate}

Access Frontmatter

Use frontmatter data in code:

---
title: Product Page
price: 99.99
discount: 20
---

export function calculateSavings(price: number, discount: number) {
  return price * (discount / 100)
}

# {frontmatter.title}

Regular price: ${frontmatter.price}
You save: ${calculateSavings(frontmatter.price, frontmatter.discount)}
Final price: ${frontmatter.price - calculateSavings(frontmatter.price, frontmatter.discount)}

Data Processing

Transform and process data:

export const products = [
  { id: 1, name: 'Widget A', price: 29.99 },
  { id: 2, name: 'Widget B', price: 49.99 },
  { id: 3, name: 'Widget C', price: 79.99 },
]

export const totalValue = products.reduce((sum, p) => sum + p.price, 0)
export const averagePrice = totalValue / products.length

Total catalog value: ${totalValue.toFixed(2)}
Average price: ${averagePrice.toFixed(2)}

API Integration

Fetch data from external APIs:

export async function fetchUserData() {
  const response = await fetch('https://api.example.com/user')
  return response.json()
}

export const userData = await fetchUserData()

Welcome back, {userData.name}!

Schema Validation

Validate data at build time:

import { z } from 'zod'

export const ProductSchema = z.object({
  sku: z.string(),
  name: z.string(),
  price: z.number().positive(),
  inStock: z.boolean(),
})

export function validateProduct(product: unknown) {
  return ProductSchema.parse(product)
}

// This will throw if frontmatter is invalid
export const validatedProduct = validateProduct(frontmatter)

Conditional Rendering

Show/hide content based on conditions:

export const isDevelopment = process.env.NODE_ENV === 'development'
export const isProduction = process.env.NODE_ENV === 'production'

{isDevelopment && (
  <Callout type="warning">
    You are viewing the development version
  </Callout>
)}

{isProduction && (
  <Callout type="info">
    Production version
  </Callout>
)}

Build-Time vs Runtime

Build-Time Execution

Code runs during the build process:

export const buildTime = new Date().toISOString()

Built at: {buildTime}

This value is computed once during build and remains static.

Runtime Execution

For interactive code, use client components:

'use client'

import { useState } from 'react'

export function Counter() {
  const [count, setCount] = useState(0)

  return (
    <button onClick={() => setCount(count + 1)}>
      Count: {count}
    </button>
  )
}

<Counter />

Type Safety

Leverage TypeScript for type-safe code:

interface Product {
  sku: string
  name: string
  price: number
  category: 'electronics' | 'clothing' | 'home'
}

export function formatProduct(product: Product): string {
  return `${product.name} (${product.sku}): $${product.price}`
}

export const product: Product = {
  sku: 'WIDGET-001',
  name: 'Premium Widget',
  price: 99.99,
  category: 'electronics'
}

{formatProduct(product)}

Error Handling

Handle errors gracefully:

export async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data')
    if (!response.ok) throw new Error('Failed to fetch')
    return response.json()
  } catch (error) {
    console.error('Error fetching data:', error)
    return { error: 'Failed to load data' }
  }
}

export const data = await fetchData()

{data.error ? (
  <Callout type="error">{data.error}</Callout>
) : (
  <div>Data loaded successfully</div>
)}

Use Cases

Dynamic Documentation

Generate API documentation from code:

import { routes } from '../api/routes'

export const apiEndpoints = routes.map(r => ({
  method: r.method,
  path: r.path,
  description: r.description
}))

## API Endpoints

{apiEndpoints.map(endpoint => (
  <div key={endpoint.path}>
    **{endpoint.method}** `{endpoint.path}` - {endpoint.description}
  </div>
))}

Computed Values

Calculate values from structured data:

---
items:
  - name: Widget A
    price: 29.99
    quantity: 5
  - name: Widget B
    price: 49.99
    quantity: 3
---

export function calculateTotal(items) {
  return items.reduce((sum, item) =>
    sum + (item.price * item.quantity), 0
  )
}

Total: ${calculateTotal(frontmatter.items).toFixed(2)}

Configuration Files

Define configuration with validation:

---
$type: WorkerConfig
name: api-worker
main: src/index.ts
compatibility_date: 2025-10-27
---

import { z } from 'zod'

export const ConfigSchema = z.object({
  $type: z.literal('WorkerConfig'),
  name: z.string(),
  main: z.string(),
  compatibility_date: z.string(),
})

export const validatedConfig = ConfigSchema.parse(frontmatter)

Next Steps