A modern, interactive learning platform built with Next.js, MDX, and TypeScript. Create beautiful, engaging courses with syntax-highlighted code examples, quizzes, and custom components.
# Install dependencies
yarn
# Start development server with auto-registry updates
yarn dev
# Build for production
yarn buildChapters are defined in lib/chapter-metadata.ts. This is the single source of truth for chapter information.
File: lib/chapter-metadata.ts
export const chapterMetadata: Record<string, ChapterMetadata> = {
'your-chapter-slug': {
number: 7, // Chapter order
title: 'Your Chapter Title', // Display name
description: 'Brief description', // Chapter description
icon: 'rocket_launch' // Material Icon name (see below)
}
}Chapters use Google Material Icons. You can use any icon from Google Material Icons.
Popular Chapter Icons:
menu_book- Documentation/readingrocket_launch- Getting started/launchpalette- Design/visualedit- Editing/CMScloud- Cloud/serverlessbolt- Performance/speedemoji_events- Foundation/achievementschool- Learning/educationconstruction- Building/setupapi- APIs/integrationsecurity- Security/permissionsstorage- Database/storage
More icons: Browse the full collection at Google Material Icons
Lessons are automatically discovered from the file system. Just create a .mdx file in the appropriate chapter folder!
# Create a new lesson file
mkdir -p content/lessons/your-chapter-slug
touch content/lessons/your-chapter-slug/your-lesson.mdxEvery lesson needs frontmatter at the top:
---
title: "Your Lesson Title"
description: "Brief description of what this lesson covers"
order: 1 # Optional: Controls lesson order in sidebar (lower = first)
author: "Your Name" # Optional
date: "2024-01-15" # Optional
estimatedTime: "15 min" # Optional
difficulty: "beginner | intermediate | advanced" # Optional
---
# Your Lesson Content Here
This is your lesson content...Lesson Ordering:
- Add an
orderfield to control the sequence of lessons within a chapter - Lessons with lower order numbers appear first (e.g.,
order: 1,order: 2,order: 3) - Lessons without an
orderfield are sorted alphabetically and appear after ordered lessons - The order only affects lessons within the same chapter
Example:
# First lesson in the chapter
---
title: "Introduction"
order: 1
---
# Second lesson in the chapter
---
title: "Getting Started"
order: 2
---
# Third lesson in the chapter
---
title: "Advanced Topics"
order: 3
---Use Markdown and custom MDX components (see below).
If you're running npm run dev:auto, the lesson will automatically appear in the sidebar!
content/
lessons/
chapter-slug/
lesson-1.mdx
lesson-2.mdx
another-lesson.mdx
Slug Format:
- If filename matches chapter:
chapter-slug→/course/chapter-slug - Otherwise:
chapter-slug/lesson-name→/course/chapter-slug/lesson-name
Your lessons have access to powerful custom components. Here's how to use them:
Display syntax-highlighted code with copy functionality.
Basic Usage:
<CodeBlock language="typescript" filename="example.ts" code={`
function hello(name: string) {
return \`Hello, \${name}!\`;
}
`} />With Pre-defined Variable:
export const myCode = `
const greeting = "Hello World";
console.log(greeting);
`;
<CodeBlock language="javascript" filename="app.js" code={myCode} />Props:
language(required):typescript,javascript,jsx,tsx,python,bash,json, etc.filename(optional): Shows filename in headercode(required): The code string to display
Features:
- ✅ Syntax highlighting with Shiki
- ✅ Theme-aware (light/dark mode)
- ✅ Copy to clipboard button
- ✅ File type icons
- ✅ Line numbers
Display images with click-to-fullscreen functionality.
Basic Usage:
<Image src="/images/screenshot.png" title="Dashboard screenshot" />Alt text usage:
<Image src="/images/screenshot.png" alt="Dashboard screenshot" />A title prop is displayed as a caption below the image. An alt prop provides accessibility text and is not visible.
An image requires either a title or alt prop for accessibility. If both are not provided, an error will be shown.
Custom Dimensions:
<Image
src="/images/photo.jpg"
title="Photo"
width={1200}
height={800}
/>Props:
src(required): Path to image (place images inpublic/images/)title(optional): Caption shown below imagealt(optional): Alt text for accessibilitywidth(optional): Width in pixels (default: 800)height(optional): Height in pixels (default: 600)
Features:
- ✅ Click to view fullscreen
- ✅ ESC or click outside to close
- ✅ Next.js Image optimization
- ✅ Responsive
- ✅ Zoom indicator on hover
Create external links that open in a new tab with proper security.
Basic Usage:
<ExternalLink href="https://www.webiny.com">Visit Webiny</ExternalLink>Without Icon:
<ExternalLink href="https://docs.webiny.com" showIcon={false}>
Documentation
</ExternalLink>In Lists:
Resources:
- <ExternalLink href="https://docs.webiny.com">Documentation</ExternalLink>
- <ExternalLink href="https://github.com/webiny/webiny-js">GitHub</ExternalLink>
- <ExternalLink href="https://www.webiny.com/blog">Blog</ExternalLink>Props:
href(required): URL to link tochildren(required): Link textshowIcon(optional): Show external link icon (default: true)
Features:
- ✅ Opens in new tab
- ✅ Security attributes (
rel="noopener noreferrer") - ✅ External link icon
- ✅ Theme-aware styling
Add interactive quizzes to test knowledge.
Basic Usage:
<Quiz
question="What is Webiny built with?"
options={[
"PHP and MySQL",
"Node.js and React",
"Ruby on Rails",
"Python and Django"
]}
correctAnswer={1}
explanation="Webiny is built with Node.js on the backend and React on the frontend."
/>Props:
question(required): The question textoptions(required): Array of answer optionscorrectAnswer(required): Index of correct answer (0-based)explanation(optional): Explanation shown after answering correctlyhintHint shown after answering incorrectly
Features:
- ✅ Interactive selection
- ✅ Instant feedback
- ✅ Explanation on answer
- ✅ Visual indicators (correct/incorrect)
Highlight important information with styled callouts.
Types:
Info:
<Callout type="info">
This is an informational callout with useful tips.
</Callout>Warning:
<Callout type="warning">
⚠️ **Warning:** This action cannot be undone!
</Callout>Hint:
<Callout type="hint">
💡 **Tip:** Use keyboard shortcuts to speed up your workflow.
</Callout>Success:
<Callout type="success">
✅ **Success:** Your project is now deployed!
</Callout>Question:
<Callout type="question">
🤔 **Think about it:** How would you structure this for scalability?
</Callout>Props:
type(optional):info,warning,hint,success,question(default:info)title(optional): Custom title to displaychildren(required): Content to display
Features:
- ✅ Color-coded by type
- ✅ Icon indicators
- ✅ Markdown support in content
- ✅ Theme-aware
- ✅ Custom titles
Highlight features that are only available in paid Webiny tiers.
Business Tier (includes Enterprise):
<PaidFeature tier="business">
Advanced multi-tenancy features including custom tenant hierarchies and granular access control are available in Webiny Business and Enterprise tiers.
</PaidFeature>Enterprise Tier Only:
<PaidFeature tier="enterprise">
SSO integration and advanced security features are exclusively available in Webiny Enterprise tier.
</PaidFeature>With Custom Message:
<PaidFeature tier="business" message="Custom branding options require a Business or Enterprise license.">
Learn how to customize your Webiny instance branding.
</PaidFeature>Props:
tier(required):"business"or"enterprise"business: Feature available in Business AND Enterprise tiersenterprise: Feature available ONLY in Enterprise tier
message(optional): Custom message to displaychildren(optional): Custom content (alternative to message)
Features:
- ✅ Visual tier badge (💎 Business or 💎 Enterprise)
- ✅ Color-coded by tier (blue for business, purple for enterprise)
- ✅ Clear availability indication
- ✅ Theme-aware styling
- ✅ Icon indicators
Default Messages:
- Business: "This feature is available in Webiny Business and Enterprise tiers."
- Enterprise: "This feature is available exclusively in Webiny Enterprise tier."
Mark sections that need completion or review. Only visible in development - automatically hidden in production builds.
Basic Usage:
<TodoPointer
title="Add Production Deployment Examples"
message="Need to add concrete examples of production deployment configurations and best practices. Include screenshots of the deployment process and common pitfalls to avoid."
/>Another Example:
<TodoPointer
title="Review Technical Accuracy"
message="This section needs to be reviewed by a technical expert to ensure all code examples are correct and follow current best practices."
/>Props:
title(required): Short title describing what needs to be donemessage(required): Detailed description of the task or issue
Features:
- ✅ Development only - Hidden in production builds
- ✅ Highly visible - Red border and warning styling
- ✅ Automatic detection - Build process scans and warns about TodoPointers
- ✅ Watch mode - Real-time detection during development
- ✅ CI/CD friendly - Shows warnings but doesn't block builds
Checking for TODOs:
During development:
npm run check-todosThis will scan all MDX files and list any TodoPointer components found.
Automatic Checks:
- Development:
npm run devwatches for TodoPointers and alerts you in real-time - Build:
npm run builddisplays warnings but allows the build to complete - Production: TodoPointers are hidden from users but warnings are shown in build logs
Best Practices:
- Use for incomplete sections during content creation
- Include specific details about what needs to be done
- Review and remove before marking lesson as complete
- Great for collaborative content development
Display a list of chapter topics at the beginning of a lesson.
Usage:
<ChapterOverview
items={[
{ icon: "description", text: "Setting up your environment" },
{ icon: "edit", text: "Creating your first project" },
{ icon: "code", text: "Building with components" },
{ icon: "check_circle", text: "Testing and deployment" }
]}
/>Icon Options:
You can use any icon from Google Material Icons. Just use the icon name in lowercase with underscores.
Popular Icons:
description- Files/documentsedit- Editing/writingcode- Coding/developmentcheck_circle- Completion/successwarning- Warnings/alertsinfo- Informationsettings- Configurationfolder- Folders/organizationterminal- Command lineapi- APIs/endpointssecurity- Security/permissionsdatabase- Databasescloud- Cloud/hostingbolt- Performance/speedlock- Security/privacyshield- Protection/safety
More Icons: Browse the full collection at Google Material Icons
Props:
items(required): Array of{ icon: string, text: string }objectstopics(alternative): Same asitems(supports both prop names)
Features:
- ✅ Clean, organized layout
- ✅ Access to 2000+ Material Icons
- ✅ Theme-aware styling
- ✅ Responsive design
Create visually appealing headings with Material Icons.
Basic Usage (default h2):
<IconTitle icon="rocket_launch" title="Getting Started" />With Different Heading Levels:
<IconTitle icon="settings" title="Configuration" heading="h3" />
<IconTitle icon="code" title="Implementation Details" heading="h4" />
<IconTitle icon="info" title="Important Note" heading="h5" />Examples with Different Icons:
<IconTitle icon="lightbulb" title="Key Concepts" heading="h2" />
<IconTitle icon="terminal" title="Command Line Usage" heading="h3" />
<IconTitle icon="shield" title="Security Best Practices" heading="h2" />
<IconTitle icon="database" title="Database Schema" heading="h3" />Props:
icon(required): Material Icon name (e.g.,"rocket_launch","code","settings")title(required): The heading text to displayheading(optional): Heading level -"h1","h2","h3","h4","h5","h6"(default:"h2")
Icon Options:
Use any icon from Google Material Icons. Popular choices:
rocket_launch- Launch/getting startedlightbulb- Ideas/tipsterminal- Command linecode- Code/developmentsettings- Configurationshield- Securitydatabase- Data/storageapi- APIsbuild- Building/constructionspeed- Performance
Features:
- ✅ Automatic icon sizing per heading level
- ✅ Theme-aware icon colors (primary)
- ✅ 2000+ Material Icons available
- ✅ Semantic HTML headings
Create an interactive accordion-style FAQ section.
Basic Usage:
<FAQ
items={[
{
question: "What is Webiny?",
answer: "Webiny is a serverless CMS platform built with Node.js and React."
},
{
question: "How do I deploy my project?",
answer: "You can deploy using the Webiny CLI with the command: webiny deploy"
},
{
question: "Is Webiny open source?",
answer: "Yes! Webiny is open source and available on GitHub under the MIT license."
}
]}
/>With Default Open Item:
<FAQ
items={[
{ question: "First question?", answer: "First answer" },
{ question: "Second question?", answer: "Second answer" },
{ question: "Third question?", answer: "Third answer" }
]}
defaultOpen={0}
/>Complex FAQ:
<FAQ
items={[
{
question: "What are the system requirements?",
answer: "Webiny requires Node.js 18+ and AWS account credentials for deployment. You'll also need at least 8GB of RAM for local development."
},
{
question: "Can I use Webiny with existing infrastructure?",
answer: "Yes! Webiny can be deployed to your existing AWS account and can integrate with your current infrastructure."
},
{
question: "What databases does Webiny support?",
answer: "Webiny uses DynamoDB for data storage by default, which is fully managed and scales automatically."
}
]}
/>Props:
items(required): Array of{ question: string, answer: string }objectsdefaultOpen(optional): Index of item to open by default (0-based), ornullfor all closed (default:null)
Features:
- ✅ Accordion-style interaction (one item open at a time)
- ✅ Smooth animations
- ✅ Theme-aware styling
- ✅ Click to expand/collapse
- ✅ Chevron icon indicates state
- ✅ Keyboard accessible
- ✅ Mobile-friendly
Best Practices:
- Keep answers concise but informative
- Use consistent question format (e.g., all ending with "?")
- Order questions from most common to least common
- Group related questions together
Here's a full example showing multiple components:
---
title: "Building Your First Component"
description: "Learn how to create reusable React components"
author: "Your Name"
date: "2024-01-15"
estimatedTime: "20 min"
difficulty: "beginner"
---
# Building Your First Component
In this lesson, you'll learn how to create reusable React components.
<ChapterOverview
items={[
{ icon: "file", text: "Understanding component structure" },
{ icon: "code", text: "Writing your first component" },
{ icon: "check", text: "Testing your component" }
]}
/>
## What You'll Build
<Image
src="/images/component-example.png"
title="The component we'll build in this lesson"
/>
## Getting Started
First, create a new file for your component:
export const componentCode = \`
import React from 'react';
export function HelloWorld() {
return <h1>Hello, World!</h1>;
}
\`;
<CodeBlock language="tsx" filename="HelloWorld.tsx" code={componentCode} />
<Callout type="tip">
💡 **Pro Tip:** Always use PascalCase for component names!
</Callout>
## Learn More
Check out the official <ExternalLink href="https://react.dev">React documentation</ExternalLink> for more details.
<Quiz
question="What naming convention should you use for React components?"
options={[
"camelCase",
"PascalCase",
"snake_case",
"kebab-case"
]}
correctAnswer={1}
explanation="React components should use PascalCase (e.g., HelloWorld, UserProfile)."
/>- Start with frontmatter - Always include title, description, and metadata
- Use ChapterOverview - Give learners a roadmap at the start
- Break up content - Use headings to organize sections
- Add visuals - Include images and diagrams
- Use Callouts - Highlight important information
- Include examples - Show code with CodeBlock
- Test knowledge - Add quizzes at the end
- Link to resources - Use ExternalLink for additional reading
- Use descriptive filenames
- Keep code snippets focused and concise
- Explain what the code does
- Use comments in complex examples
- Place images in
public/images/ - Use descriptive filenames
- Always provide alt text
- Keep file sizes under 2MB
- Use appropriate formats (PNG for screenshots, JPG for photos, SVG for diagrams)
- Framework: Next.js 16 (App Router)
- Language: TypeScript
- Styling: Tailwind CSS 4
- MDX: @next/mdx
- Code Highlighting: Shiki
- Icons: Lucide React
- UI Components: Radix UI
learn-webiny/
├── app/ # Next.js app directory
│ ├── course/ # Course pages
│ └── layout.tsx # Root layout
├── components/ # React components
│ ├── ui/ # UI primitives
│ └── ... # Custom components
├── content/
│ └── lessons/ # Lesson MDX files
│ ├── chapter-1/
│ ├── chapter-2/
│ └── ...
├── lib/
│ ├── chapter-metadata.ts # Chapter definitions
│ ├── mdx-registry.ts # Auto-generated registry
│ └── mdx-loader.ts # MDX loading logic
├── scripts/
│ ├── generate-mdx-registry.mjs # Registry generator
│ └── watch-mdx-lessons.mjs # File watcher
├── mdx-components.tsx # MDX component mappings
└── next.config.mjs # Next.js configuration
The lesson registry is automatically managed:
-
Development (
npm run dev:auto):- Generates registry on start
- Watches for file changes
- Auto-regenerates when lessons added/removed
-
Production (
npm run build):- Regenerates registry before build
- Ensures all lessons included
- No manual intervention needed
# Connect your GitHub repo to Vercel
# Vercel will automatically:
# 1. Run npm run build (which includes registry generation)
# 2. Deploy your siteThe platform includes comprehensive SEO features for optimal discoverability:
Every page includes optimized metadata:
- Homepage: Default metadata with Open Graph and Twitter Card tags
- Course Page: Overview metadata with course information
- Lesson Pages: Dynamic metadata generated from lesson frontmatter
- Includes chapter context
- Uses lesson title and description
- Proper meta tags for social sharing
Automatically generated sitemap includes:
- Homepage
- Course overview page
- All lesson pages (dynamically discovered)
Location: /sitemap.xml
Updates: Automatically regenerates based on MDX registry
Configures search engine crawling behavior:
- Allows all crawlers
- References sitemap location
- Ready for future private route exclusions
Locations:
- Dynamic:
app/robots.ts(Next.js App Router) - Static:
public/robots.txt(fallback)
Support for AI/LLM training and context:
Comprehensive documentation for AI models including:
- Platform overview and purpose
- Content structure and organization
- Topics covered in the course
- Technical stack information
- Available MDX components
- Learning features
- Best use cases for AI training
- Attribution and contact information
Locations:
public/llm.txtpublic/llms.txt(both files have identical content for compatibility)
These files help AI models understand the platform structure and provide better assistance to users learning Webiny.
When creating content:
-
Frontmatter is Critical
--- title: "Clear, Descriptive Title" description: "Compelling 150-160 character description" ---
-
Use Semantic Heading Structure
- One
<h1>per lesson (automatically from title) - Use
##for main sections - Use
###for subsections
- One
-
Add Title Text to Images
<Image src="/path/to/image.png" title="Descriptive alt text" />
-
Link to External Resources
<ExternalLink href="https://docs.webiny.com">Official Documentation</ExternalLink>
Make sure your build command runs:
npm run buildThis automatically:
- Generates the MDX registry
- Builds the Next.js application
- Next.js Documentation: https://nextjs.org/docs
- MDX Documentation: https://mdxjs.com
- Tailwind CSS: https://tailwindcss.com
- Webiny: https://www.webiny.com
- Create a new chapter in
lib/chapter-metadata.ts - Add lesson files to
content/lessons/your-chapter/ - Use MDX components to enhance content
- Test locally with
yarn dev - Submit a pull request
MIT
Built with ❤️ for the Webiny community