Launch Your Documentation
Deploy your Mordoc documentation to production on your preferred hosting platform.
Launch Your Documentation
Deploy your Mordoc documentation to any hosting platform that serves static sites. This guide covers popular options and deployment strategies.
Deployment Overview
Mordoc generates static HTML files that can be hosted anywhere:
- Static hosting platforms: Netlify, Vercel, Cloudflare Pages
- Cloud storage: AWS S3, Google Cloud Storage, Azure Blob Storage
- Traditional hosting: Shared hosting, VPS, dedicated servers
- CDN platforms: Cloudflare, Fastly, AWS CloudFront
Because Mordoc generates standard static HTML, you're not locked into any specific platform. Choose based on your needs, budget, and existing infrastructure.
Pre-Deployment Checklist
Before deploying:
- [ ] Build completed successfully:
npm run build - [ ] Tested locally:
npm run preview - [ ] All links verified
- [ ] Search functionality tested
- [ ] Configuration finalized
- [ ]
baseUrlset correctly inconfig/site.json - [ ] Changes committed to version control
Popular Hosting Platforms
Netlify
Pros: Easy deployment, free tier, automatic HTTPS, preview deployments
Deploy with Git Integration
- Push your code to GitHub
- Go to netlify.com
- Click "Add new site" → "Import an existing project"
- Connect to GitHub
- Select your repository
- Configure build settings:
- Build command:
npm run build - Publish directory:
dist
- Build command:
- Click "Deploy site"
Deploy via Drag & Drop
- Build locally:
npm run build - Go to netlify.com
- Drag
dist/folder to deploy area - Site is live immediately
netlify.toml Configuration
Create netlify.toml in project root:
[build]
command = "npm run build"
publish = "dist"
[[redirects]]
from = "/*"
to = "/404.html"
status = 404Vercel
Pros: Excellent performance, free tier, serverless functions, automatic deployments
Deploy with Git
- Push to GitHub/GitLab/Bitbucket
- Go to vercel.com
- Click "Add New" → "Project"
- Import your repository
- Configure:
- Framework Preset: Other
- Build Command:
npm run build - Output Directory:
dist
- Click "Deploy"
vercel.json Configuration
{
"buildCommand": "npm run build",
"outputDirectory": "dist",
"rewrites": [
{ "source": "/(.*)", "destination": "/" }
]
}Cloudflare Pages
Pros: Global CDN, free tier, fast, DDoS protection
Deploy with Git
- Push to GitHub/GitLab
- Go to pages.cloudflare.com
- Click "Create a project"
- Connect your Git account
- Select repository
- Configure:
- Build command:
npm run build - Build output directory:
dist
- Build command:
- Click "Save and Deploy"
GitHub Pages
Pros: Free for public repos, simple setup, integrated with GitHub
GitHub Actions Deployment
Create .github/workflows/deploy.yml:
name: Deploy to GitHub Pages
on:
push:
branches: [main]
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci
- run: npm run build
- uses: actions/upload-pages-artifact@v2
with:
path: dist
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/deploy-pages@v2
id: deploymentEnable GitHub Pages in repository settings:
- Settings → Pages
- Source: GitHub Actions
- Save
Note: Update baseUrl in config/site.json:
{
"baseUrl": "https://username.github.io/repo-name"
}Cloud Storage Platforms
AWS S3 + CloudFront
S3 Bucket Setup
# Install AWS CLI
npm install -g aws-cli
# Configure credentials
aws configure
# Create bucket
aws s3 mb s3://docs.example.com
# Enable static website hosting
aws s3 website s3://docs.example.com --index-document index.html --error-document 404.html
# Upload build
aws s3 sync dist/ s3://docs.example.com --deleteBucket Policy
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::docs.example.com/*"
}]
}CloudFront Distribution
- Go to CloudFront console
- Create distribution
- Origin: Your S3 bucket
- Default root object:
index.html - Enable HTTPS
- Deploy
Google Cloud Storage
# Install gcloud CLI
# https://cloud.google.com/sdk/docs/install
# Authenticate
gcloud auth login
# Create bucket
gsutil mb gs://docs.example.com
# Configure for web hosting
gsutil web set -m index.html -e 404.html gs://docs.example.com
# Upload files
gsutil -m rsync -r -d dist/ gs://docs.example.com
# Make public
gsutil iam ch allUsers:objectViewer gs://docs.example.comTraditional Hosting
Shared Hosting / cPanel
- Build locally:
npm run build - Connect via FTP/SFTP
- Upload contents of
dist/topublic_html/orwww/ - Ensure
.htaccessis configured for clean URLs
.htaccess for clean URLs:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.html [L]VPS / Dedicated Server
With Nginx
- Build and upload files
- Configure Nginx:
server {
listen 80;
server_name docs.example.com;
root /var/www/docs;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
# Enable gzip compression
gzip on;
gzip_types text/html text/css application/javascript application/json;
}- Reload Nginx:
sudo nginx -t
sudo systemctl reload nginxWith Apache
ServerName docs.example.com
DocumentRoot /var/www/docs
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
# Enable compression
AddOutputFilterByType DEFLATE text/html text/css application/javascript
Docker Deployment
Dockerfile
FROM nginx:alpine
# Copy built files
COPY dist/ /usr/share/nginx/html/
# Copy nginx configuration
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]nginx.conf
server {
listen 80;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
gzip on;
gzip_types text/html text/css application/javascript;
}Build and Run
# Build image
docker build -t my-docs .
# Run container
docker run -d -p 80:80 my-docsContinuous Deployment
Automated Deployment Workflow
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Deploy to Netlify
uses: nwtgck/actions-netlify@v2
with:
publish-dir: './dist'
production-deploy: true
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}Custom Domain Setup
DNS Configuration
Point your domain to your hosting platform:
A Record (IP address):
Type: A
Name: @
Value: 192.0.2.1CNAME Record (hostname):
Type: CNAME
Name: docs
Value: your-site.netlify.appSSL Certificate
Most modern platforms provide free SSL:
- Netlify/Vercel: Automatic HTTPS
- Cloudflare: Free SSL with CDN
- Let's Encrypt: Free SSL for self-hosted
Let's Encrypt with Certbot
# Install certbot
sudo apt install certbot python3-certbot-nginx
# Get certificate
sudo certbot --nginx -d docs.example.com
# Auto-renewal
sudo certbot renew --dry-runPerformance Optimization
Enable Compression
Nginx:
gzip on;
gzip_comp_level 6;
gzip_types text/html text/css application/javascript application/json;Apache:
AddOutputFilterByType DEFLATE text/html text/css application/javascript
Cache Headers
Nginx:
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}Apache:
ExpiresActive On
ExpiresByType text/html "access plus 1 hour"
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
CDN Integration
Add your site to a CDN for global performance:
- Cloudflare: Free tier available
- AWS CloudFront: Pay as you go
- Fastly: Enterprise CDN
Monitoring and Analytics
Google Analytics
Add to config/site.json:
{
"analytics": {
"googleAnalytics": "G-XXXXXXXXXX"
}
}Plausible Analytics
Privacy-friendly alternative:
{
"analytics": {
"plausible": {
"domain": "docs.example.com"
}
}
}Monitoring Tools
- Uptime Robot: Monitor site availability
- Google Search Console: SEO monitoring
- Lighthouse CI: Performance monitoring
Troubleshooting
404 Errors on Refresh
Solution: Configure server to serve index.html for all routes.
Netlify: Add _redirects file:
/* /index.html 200Vercel: Already handled by framework preset
Nginx: Use try_files directive (see above)
Assets Not Loading
- Check
baseUrlinconfig/site.json - Verify asset paths start with
/ - Clear CDN cache
- Check browser console for errors
Slow Load Times
- Enable compression (gzip/brotli)
- Use CDN
- Optimize images
- Enable caching headers
- Minify assets (should be automatic)
Search Not Working
- Verify
dist/pagefind/directory exists - Check search index was generated during build
- Ensure JavaScript is not blocked
- Check browser console for errors
Post-Deployment
Verification Checklist
- [ ] Site loads at custom domain
- [ ] HTTPS is working
- [ ] All pages are accessible
- [ ] Search functions correctly
- [ ] Images and assets load
- [ ] Mobile responsive
- [ ] Performance is good (run Lighthouse)
Submit to Search Engines
Google Search Console:
- Add property
- Verify ownership
- Submit sitemap:
https://docs.example.com/sitemap.xml
Bing Webmaster Tools:
- Add site
- Verify ownership
- Submit sitemap
Monitor Performance
- Set up uptime monitoring
- Track analytics
- Monitor search console
- Check for broken links regularly
Best Practices
Documentation Deployment
- Test thoroughly before deploying
- Use version control for all changes
- Automate deployments via CI/CD
- Enable HTTPS always
- Use CDN for global users
- Monitor uptime and performance
- Keep dependencies updated
Rollback Strategy
Always be able to rollback:
Git-based:
# Revert last commit
git revert HEAD
git push
# Deployment happens automaticallyManual:
- Keep previous
dist/folder as backup - Upload previous version if needed
Next Steps
After launching:
- Monitor site performance and uptime
- Gather user feedback
- Iterate on content
- Keep documentation up to date
- Promote your documentation
Your documentation is now live! Remember to keep it updated and respond to user feedback. Good documentation is never truly "finished"—it evolves with your product.

