Static Sites
Deploy static HTML/CSS/JS sites without containers. Caddy serves them directly for maximum performance.
Overview
Static sites are pre-built files that don't require server-side processing:
- Landing pages & marketing sites
- Documentation
- Blogs (Hugo, Astro, Jekyll)
- SPAs (React, Vue, Svelte builds)
Benefits:
- No container overhead
- Instant deploys
- Low memory usage
- No Dockerfile needed
Quick Start
Manual Build
# Build your site
npm run build
# Deploy
bp deploybasepod.yaml:
name: mysite
type: static
public: dist/Auto Build (Recommended)
Let Basepod run the build command for you:
bp deploybasepod.yaml:
name: mysite
type: static
public: dist/
build:
command: npm run buildWith build.command set, bp deploy will:
- Check for uncommitted git changes
- Run your build command locally
- Upload the output directory to the server
TIP
This ensures you always deploy the latest build without forgetting to run npm run build first.
Framework Examples
React / Vite
npm create vite@latest my-app -- --template react
cd my-app
npm install
bp init --static
bp deploybasepod.yaml:
name: my-react-app
type: static
public: dist/
build:
command: npm run buildVue / Vite
npm create vite@latest my-app -- --template vue
cd my-app
npm install
bp deploybasepod.yaml:
name: my-vue-app
type: static
public: dist/
build:
command: npm run buildNuxt (Static/SSG)
npx nuxi init my-nuxt-app
cd my-nuxt-app
npm install
bp deploybasepod.yaml:
name: my-nuxt-app
type: static
public: .output/public/
build:
command: npm run generateTIP
Use npm run generate for static export, not npm run build.
Next.js (Static Export)
next.config.js:
module.exports = {
output: 'export'
}basepod.yaml:
name: my-next-app
type: static
public: out/
build:
command: npm run buildAstro
npm create astro@latest
cd my-astro-app
bp deploybasepod.yaml:
name: my-astro-app
type: static
public: dist/
build:
command: npm run buildSvelteKit (Static)
svelte.config.js:
import adapter from '@sveltejs/adapter-static';
export default {
kit: {
adapter: adapter()
}
};basepod.yaml:
name: my-svelte-app
type: static
public: build/
build:
command: npm run buildHugo
hugo new site mysite
cd mysite
bp deploybasepod.yaml:
name: my-hugo-site
type: static
public: public/
build:
command: hugoJekyll
basepod.yaml:
name: my-jekyll-site
type: static
public: _site/
build:
command: bundle exec jekyll buildVitePress / VuePress
basepod.yaml:
name: my-docs
type: static
public: docs/.vitepress/dist/
build:
command: npm run docs:buildPlain HTML
Just put your files in a folder:
my-site/
├── basepod.yaml
├── index.html
├── css/
│ └── style.css
└── js/
└── app.jsbasepod.yaml:
name: my-site
type: static
public: ./Public Directory Reference
| Framework | Build Command | Public Directory |
|---|---|---|
| Vite (React/Vue/Svelte) | npm run build | dist/ |
| Nuxt (SSG) | npm run generate | .output/public/ |
| Next.js (export) | npm run build | out/ |
| Astro | npm run build | dist/ |
| SvelteKit (static) | npm run build | build/ |
| Hugo | hugo | public/ |
| Jekyll | bundle exec jekyll build | _site/ |
| VitePress | npm run docs:build | docs/.vitepress/dist/ |
| Docusaurus | npm run build | build/ |
SPA Routing
For single-page apps with client-side routing (React Router, Vue Router, etc.), Basepod automatically serves index.html for all routes.
No configuration needed.
Custom Headers
Create a _headers file in your public directory:
/*
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
/assets/*
Cache-Control: public, max-age=31536000
/*.js
Cache-Control: public, max-age=31536000
/*.css
Cache-Control: public, max-age=31536000Custom Domain
name: my-site
type: static
public: dist/
domain: www.mydomain.comPoint your DNS to your Basepod server. SSL certificates are automatic.