Skip to content

Commit cdc7379

Browse files
committed
docs: write articles
1 parent 9a70145 commit cdc7379

File tree

4 files changed

+744
-0
lines changed

4 files changed

+744
-0
lines changed
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
---
2+
title: "Deploying Explainer to production: a complete guide"
3+
description: From local development to production deployment — learn how to ship your Explainer documentation to Cloudflare Pages, Vercel, or any static hosting provider with CI/CD automation.
4+
short_description: "Ship your docs to production with Cloudflare, Vercel, or Docker."
5+
date: 2026-03-16
6+
tags: [guide, deployment, ci-cd, cloudflare]
7+
status: published
8+
author: leadcode_dev
9+
---
10+
11+
You've written your documentation, customized the theme, and everything looks great locally. Now it's time to share it with the world. In this guide, we'll cover the full deployment story — from build configuration to CI/CD pipelines.
12+
13+
## Understanding the build output
14+
15+
Explainer apps are standard **Astro static sites**. Running `pnpm build` produces a `dist/` directory with plain HTML, CSS, and JavaScript files. No server runtime required — you can host the output anywhere that serves static files.
16+
17+
```bash
18+
# Build all three apps
19+
pnpm build
20+
21+
# Or build individually
22+
pnpm --filter @explainer/docs build
23+
pnpm --filter @explainer/blog build
24+
pnpm --filter @explainer/website build
25+
```
26+
27+
:::callout{variant="info" title="Independent apps"}
28+
Each app builds independently with its own `dist/` output. You can deploy them to different providers or subdomains — they don't need to live on the same server.
29+
:::
30+
31+
## Environment variables
32+
33+
Before building for production, configure your cross-app URLs. These ensure navbar links point to the correct domains:
34+
35+
```bash title=".env"
36+
PUBLIC_WEBSITE_URL=https://explainer.dev
37+
PUBLIC_DOCS_URL=https://docs.explainer.dev
38+
PUBLIC_BLOG_URL=https://blog.explainer.dev
39+
```
40+
41+
For the contributors section, you can optionally provide a GitHub token for higher API rate limits:
42+
43+
```bash title=".env"
44+
GITHUB_TOKEN=ghp_xxxxxxxxxxxx
45+
```
46+
47+
:::callout{variant="success"}
48+
Without a token, the GitHub API allows 60 requests per hour — more than enough for a single build. The token is mainly useful during active development when you're rebuilding frequently.
49+
:::
50+
51+
## Deploying to Cloudflare Pages
52+
53+
Cloudflare Pages is our recommended deployment target. It offers a generous free tier, global CDN, and automatic preview deployments.
54+
55+
::::step-group
56+
:::step{title="Create Cloudflare Pages projects"}
57+
Create three projects in your Cloudflare dashboard — one for each app:
58+
- `explainer-docs`
59+
- `explainer-blog`
60+
- `explainer-website`
61+
62+
No build configuration needed in Cloudflare — we handle builds in GitHub Actions.
63+
:::
64+
65+
:::step{title="Configure secrets"}
66+
In your GitHub repository settings, add these secrets:
67+
- `CLOUDFLARE_API_TOKEN` — your Cloudflare API token with Pages edit permission
68+
- `CLOUDFLARE_ACCOUNT_ID` — your Cloudflare account ID
69+
70+
And these variables:
71+
- `PUBLIC_DOCS_URL`, `PUBLIC_BLOG_URL`, `PUBLIC_WEBSITE_URL` — your production URLs
72+
- `DEPLOY_TARGET` — set to `cloudflare`
73+
:::
74+
75+
:::step{title="Push to main"}
76+
The included GitHub Actions workflow handles everything automatically. On each push to `main`, it:
77+
1. Detects which apps have changed (path filtering)
78+
2. Builds only the affected apps
79+
3. Deploys to Cloudflare Pages
80+
81+
```yaml title=".github/workflows/deploy.yml"
82+
- run: pnpm --filter @explainer/docs build
83+
env:
84+
PUBLIC_DOCS_URL: ${{ vars.PUBLIC_DOCS_URL }}
85+
PUBLIC_BLOG_URL: ${{ vars.PUBLIC_BLOG_URL }}
86+
PUBLIC_WEBSITE_URL: ${{ vars.PUBLIC_WEBSITE_URL }}
87+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
88+
```
89+
:::
90+
::::
91+
92+
## Deploying to Vercel
93+
94+
Vercel's zero-config approach works well with Explainer. Each app can be imported as a separate Vercel project.
95+
96+
::::step-group
97+
:::step{title="Import the repository"}
98+
In the Vercel dashboard, import your repository three times — once per app. For each project, configure:
99+
100+
- **Root directory**: `apps/docs`, `apps/blog`, or `apps/website`
101+
- **Build command**: `cd ../.. && pnpm build --filter @explainer/docs`
102+
- **Output directory**: `dist`
103+
:::
104+
105+
:::step{title="Set environment variables"}
106+
Add `PUBLIC_DOCS_URL`, `PUBLIC_BLOG_URL`, `PUBLIC_WEBSITE_URL`, and optionally `GITHUB_TOKEN` in each project's environment settings.
107+
:::
108+
109+
:::step{title="Configure custom domains"}
110+
Assign your subdomains to each Vercel project: `docs.explainer.dev`, `blog.explainer.dev`, and `explainer.dev`.
111+
:::
112+
::::
113+
114+
## Smart CI/CD with path filtering
115+
116+
The monorepo workflow includes intelligent path filtering — only apps with actual changes get rebuilt and deployed:
117+
118+
```yaml
119+
- uses: dorny/paths-filter@v4
120+
with:
121+
filters: |
122+
docs:
123+
- 'apps/docs/**'
124+
- 'packages/**'
125+
- 'pnpm-lock.yaml'
126+
blog:
127+
- 'apps/blog/**'
128+
- 'packages/**'
129+
- 'pnpm-lock.yaml'
130+
```
131+
132+
:::callout{variant="warning" title="Shared packages trigger all builds"}
133+
Changes to `packages/**` trigger rebuilds for all apps, since shared UI or MDX changes can affect any app. This is intentional — it ensures consistency across your documentation ecosystem.
134+
:::
135+
136+
## Custom domains and DNS
137+
138+
A typical setup uses subdomains:
139+
140+
| App | Domain | DNS Record |
141+
|-----|--------|------------|
142+
| Website | `explainer.dev` | `CNAME` to provider |
143+
| Docs | `docs.explainer.dev` | `CNAME` to provider |
144+
| Blog | `blog.explainer.dev` | `CNAME` to provider |
145+
146+
Both Cloudflare Pages and Vercel handle SSL certificates automatically.
147+
148+
## Docker deployment
149+
150+
For self-hosted environments, Explainer supports Docker deployment with a multi-stage build:
151+
152+
```dockerfile title="Dockerfile"
153+
FROM node:22-alpine AS build
154+
RUN corepack enable
155+
WORKDIR /app
156+
COPY . .
157+
RUN pnpm install --frozen-lockfile
158+
RUN pnpm --filter @explainer/docs build
159+
160+
FROM nginx:alpine
161+
COPY --from=build /app/apps/docs/dist /usr/share/nginx/html
162+
```
163+
164+
You can serve all three apps behind a reverse proxy (nginx, Caddy, Traefik) with path-based or subdomain routing.
165+
166+
## Performance checklist
167+
168+
Before going live, verify these optimizations are in place:
169+
170+
::::card-group{cols=2}
171+
:::card{label="Pagefind search" icon="lucide:search"}
172+
Search indexes are generated at build time. Verify the `dist/pagefind/` directory exists after building docs.
173+
:::
174+
175+
:::card{label="OG thumbnails" icon="lucide:image"}
176+
Every page gets an auto-generated Open Graph image. Test with the [Twitter Card Validator](https://cards-dev.twitter.com/validator).
177+
:::
178+
179+
:::card{label="RSS feed" icon="lucide:rss"}
180+
The blog generates RSS feeds per locale at `/{locale}/rss.xml`. Test with a feed reader.
181+
:::
182+
183+
:::card{label="Sitemap" icon="lucide:map"}
184+
Astro generates a sitemap automatically. Verify it's accessible at `/sitemap-index.xml`.
185+
:::
186+
::::
187+
188+
## What's next
189+
190+
With your documentation deployed, you can focus on what matters — writing great content. The CI/CD pipeline ensures every push to `main` gets your changes live within minutes.
191+
192+
:::callout{variant="note" title="Need help?"}
193+
Check out the [deployment documentation](/en/explainer/deployment/docker) for detailed provider-specific guides, or open an issue on GitHub if you run into any problems.
194+
:::
195+
196+
Happy shipping!
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
---
2+
title: "A deep dive into Explainer's MDX components"
3+
description: Explainer v2 ships with a rich library of auto-imported MDX components — callouts, cards, steps, code groups, and more. Learn how they work and how to use them effectively to create engaging documentation.
4+
short_description: "Master the built-in MDX components that make your docs stand out."
5+
date: 2026-03-13
6+
tags: [tutorial, mdx, components, documentation]
7+
status: published
8+
author: leadcode_dev
9+
---
10+
11+
One of Explainer's greatest strengths is its **MDX component library**. Every component is auto-imported — no import statements needed — so you can focus on writing content, not boilerplate.
12+
13+
In this article, we'll walk through each component family, show practical examples, and share tips to get the most out of them.
14+
15+
## Callouts: guide your reader's attention
16+
17+
Callouts are the quickest way to highlight important information. Explainer supports five variants, each with a distinct visual style and semantic meaning.
18+
19+
:::callout{variant="info" title="When to use callouts"}
20+
Use callouts sparingly. When everything is highlighted, nothing is. Reserve them for genuinely important notes, warnings, or tips that readers shouldn't miss.
21+
:::
22+
23+
The syntax is straightforward:
24+
25+
```mdx
26+
:::callout{variant="warning" title="Breaking change"}
27+
The `config.legacy` option has been removed in v2.
28+
:::
29+
```
30+
31+
Available variants: `info`, `success`, `warning`, `danger`, and `note`. Each maps to a specific color scheme that works in both light and dark modes.
32+
33+
:::callout{variant="success" title="Pro tip"}
34+
You can omit the `title` attribute for a more compact callout — perfect for short one-liner notes.
35+
:::
36+
37+
## Cards and Card Groups: structured navigation
38+
39+
Cards are perfect for feature overviews, link collections, or any content that benefits from a visual grid layout.
40+
41+
::::card-group{cols=3}
42+
:::card{label="Simple syntax" icon="lucide:feather"}
43+
Write cards with a single directive — no JSX knowledge required.
44+
:::
45+
46+
:::card{label="Responsive grid" icon="lucide:layout-grid"}
47+
Card groups automatically adapt from 1 to 3 columns based on screen size.
48+
:::
49+
50+
:::card{label="Icons included" icon="lucide:smile"}
51+
Use any Lucide icon by name. They render inline with the card label.
52+
:::
53+
::::
54+
55+
The `cols` attribute on `card-group` controls the maximum number of columns. Cards with an `href` attribute become clickable links.
56+
57+
```mdx
58+
::::card-group{cols=2}
59+
:::card{label="Getting Started" icon="lucide:rocket" href="/en/explainer/getting-started"}
60+
Set up Explainer in under 5 minutes.
61+
:::
62+
63+
:::card{label="Configuration" icon="lucide:settings" href="/en/explainer/configuration"}
64+
Customize every aspect of your documentation.
65+
:::
66+
::::
67+
```
68+
69+
## Steps: sequential instructions
70+
71+
When documenting a process, steps provide a clear visual hierarchy with numbered indicators.
72+
73+
::::step-group
74+
:::step{title="Write your content"}
75+
Create `.mdx` files in the content directory. Explainer auto-discovers them and builds the navigation.
76+
:::
77+
78+
:::step{title="Use directives freely"}
79+
Add callouts, cards, code blocks — all auto-imported. No setup required.
80+
:::
81+
82+
:::step{title="Build and deploy"}
83+
Run `pnpm build` and deploy the static output anywhere. That's it.
84+
:::
85+
::::
86+
87+
Steps are especially useful for getting-started guides, installation instructions, and multi-stage tutorials.
88+
89+
## Code Groups: compare and contrast
90+
91+
Code groups let you show multiple code blocks in a tabbed interface — ideal for showing the same concept in different languages or configurations.
92+
93+
:::code-group
94+
```ts [TypeScript]
95+
interface User {
96+
name: string
97+
email: string
98+
}
99+
```
100+
101+
```python [Python]
102+
class User:
103+
name: str
104+
email: str
105+
```
106+
107+
```go [Go]
108+
type User struct {
109+
Name string
110+
Email string
111+
}
112+
```
113+
:::
114+
115+
The tab labels are extracted from the `[label]` syntax in each code block's meta string. Readers can switch between tabs without losing their scroll position.
116+
117+
## Rich code blocks
118+
119+
Beyond code groups, Explainer's code blocks support several enhancements out of the box:
120+
121+
- **Syntax highlighting** with dual themes (light and dark)
122+
- **Line numbers** for reference
123+
- **Title bars** showing the file name
124+
- **Line highlighting** to draw attention to specific lines
125+
- **60+ language icons** displayed automatically
126+
127+
```ts title="packages/ui/src/lib/contributors.ts"
128+
export async function fetchContributors(options?: FetchContributorsOptions): Promise<Contributor[]> {
129+
const owner = options?.owner ?? 'LeadcodeDev'
130+
const repo = options?.repo ?? 'explainer_v2'
131+
132+
const response = await fetch(
133+
`https://api.github.com/repos/${owner}/${repo}/contributors?per_page=100`,
134+
{ headers },
135+
)
136+
137+
return response.json()
138+
}
139+
```
140+
141+
## Combining components
142+
143+
The real power comes from combining components together. Here's a pattern we use frequently in the Explainer docs:
144+
145+
:::callout{variant="info" title="Prerequisites"}
146+
Make sure you have Node.js 22+ and pnpm installed before continuing.
147+
:::
148+
149+
::::step-group
150+
:::step{title="Clone and install"}
151+
```bash
152+
git clone https://github.com/LeadcodeDev/explainer_v2
153+
cd explainer_v2 && pnpm install
154+
```
155+
:::
156+
157+
:::step{title="Start the dev server"}
158+
```bash
159+
pnpm dev
160+
```
161+
162+
:::callout{variant="success"}
163+
All three apps start simultaneously — docs on `:4321`, blog on `:4322`, website on `:4323`.
164+
:::
165+
:::
166+
::::
167+
168+
## What's next
169+
170+
These components cover the most common documentation patterns. If you need something custom, Explainer's MDX pipeline supports standard React components too — just import and use them.
171+
172+
:::callout{variant="note" title="Explore the full reference"}
173+
Every component is documented in detail in the [MDX Components](/en/explainer/mdx-components/callout) section of the docs, with live examples and all available props.
174+
:::
175+
176+
We'd love to see what you build with these components. Share your documentation with us on GitHub!

0 commit comments

Comments
 (0)