Skip to content

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

bash
# Build your site
npm run build

# Deploy
bp deploy

basepod.yaml:

yaml
name: mysite
type: static
public: dist/

Let Basepod run the build command for you:

bash
bp deploy

basepod.yaml:

yaml
name: mysite
type: static
public: dist/

build:
  command: npm run build

With build.command set, bp deploy will:

  1. Check for uncommitted git changes
  2. Run your build command locally
  3. 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

bash
npm create vite@latest my-app -- --template react
cd my-app
npm install
bp init --static
bp deploy

basepod.yaml:

yaml
name: my-react-app
type: static
public: dist/

build:
  command: npm run build

Vue / Vite

bash
npm create vite@latest my-app -- --template vue
cd my-app
npm install
bp deploy

basepod.yaml:

yaml
name: my-vue-app
type: static
public: dist/

build:
  command: npm run build

Nuxt (Static/SSG)

bash
npx nuxi init my-nuxt-app
cd my-nuxt-app
npm install
bp deploy

basepod.yaml:

yaml
name: my-nuxt-app
type: static
public: .output/public/

build:
  command: npm run generate

TIP

Use npm run generate for static export, not npm run build.


Next.js (Static Export)

next.config.js:

js
module.exports = {
  output: 'export'
}

basepod.yaml:

yaml
name: my-next-app
type: static
public: out/

build:
  command: npm run build

Astro

bash
npm create astro@latest
cd my-astro-app
bp deploy

basepod.yaml:

yaml
name: my-astro-app
type: static
public: dist/

build:
  command: npm run build

SvelteKit (Static)

svelte.config.js:

js
import adapter from '@sveltejs/adapter-static';

export default {
  kit: {
    adapter: adapter()
  }
};

basepod.yaml:

yaml
name: my-svelte-app
type: static
public: build/

build:
  command: npm run build

Hugo

bash
hugo new site mysite
cd mysite
bp deploy

basepod.yaml:

yaml
name: my-hugo-site
type: static
public: public/

build:
  command: hugo

Jekyll

basepod.yaml:

yaml
name: my-jekyll-site
type: static
public: _site/

build:
  command: bundle exec jekyll build

VitePress / VuePress

basepod.yaml:

yaml
name: my-docs
type: static
public: docs/.vitepress/dist/

build:
  command: npm run docs:build

Plain HTML

Just put your files in a folder:

my-site/
├── basepod.yaml
├── index.html
├── css/
│   └── style.css
└── js/
    └── app.js

basepod.yaml:

yaml
name: my-site
type: static
public: ./

Public Directory Reference

FrameworkBuild CommandPublic Directory
Vite (React/Vue/Svelte)npm run builddist/
Nuxt (SSG)npm run generate.output/public/
Next.js (export)npm run buildout/
Astronpm run builddist/
SvelteKit (static)npm run buildbuild/
Hugohugopublic/
Jekyllbundle exec jekyll build_site/
VitePressnpm run docs:builddocs/.vitepress/dist/
Docusaurusnpm run buildbuild/

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=31536000

Custom Domain

yaml
name: my-site
type: static
public: dist/
domain: www.mydomain.com

Point your DNS to your Basepod server. SSL certificates are automatic.

Released under the MIT License.