Skip to content

Static Web Apps & Single Page Applications (SPAs)

MicroFly natively hosts static web applications—including Vite, React, Vue, Svelte, Astro, Next.js static exports, Hugo, and documentation sites—directly through its built-in high-performance web server.

Unlike backend processes, static web apps run with 0 MB RAM, 0% CPU idle consumption, and zero cold-start delay, while maintaining full support for atomic deployments, custom domains, automated TLS, and instant rollbacks.


1. Quick Example: Deploying a Vite / React SPA

Given a typical modern frontend build output (dist/ containing index.html and bundled assets), create an app.toml in your project root:

toml
name = "dashboard-frontend"
type = "static"
domain = ["app.mycompany.com"]

[static]
directory = "dist"             # Relative path to the build directory
spa = true                     # Single Page App: route non-file paths to index.html
clean_urls = true              # e.g., /about resolves to /about.html

# Cache Control Configuration
cache_control = "public, max-age=3600"
asset_cache_control = "public, max-age=31536000, immutable"
html_cache_control = "no-cache, must-revalidate"

[static.headers]
"X-Frame-Options" = "DENY"
"X-Content-Type-Options" = "nosniff"
"Referrer-Policy" = "strict-origin-when-cross-origin"

Deploy it to MicroFly:

bash
# Build your frontend assets locally or in CI:
npm run build

# Deploy the release atomically:
microfly deploy

2. Web Server Caching Configuration

MicroFly provides granular, production-grade HTTP caching out of the box to guarantee maximum browser cache efficiency while preventing users from being stuck on stale releases.

Caching Architecture

Content TypeDefault HeaderRationale
Entry Point (index.html)no-cache, must-revalidateBrowsers always perform a lightweight conditional ETag validation before rendering. When a new release is deployed, users receive the latest index.html instantly without manual hard-refreshing.
Fingerprinted Assets (/assets/*, *.js, *.css, fonts, images)public, max-age=31536000, immutableModern build tools (Vite, Webpack, Rollup) include content hashes in asset filenames (e.g. main-a8f3c1.js). These files can be cached permanently (1 year) in browser disk cache, achieving 0ms load times.
Standard Static Filespublic, max-age=3600Fallback cache duration for general assets.

Manifest Cache Settings

Configure caching policies directly in app.toml:

toml
[static]
# Default Cache-Control applied to standard static files:
cache_control = "public, max-age=7200"

# Long-term immutable caching for bundled/fingerprinted assets:
asset_cache_control = "public, max-age=31536000, immutable"

# Cache policy for HTML entrypoints and SPA fallback routes:
html_cache_control = "no-cache, must-revalidate"

# File patterns that qualify for asset_cache_control:
asset_patterns = [
  "/assets/*",
  "/static/*",
  "*.js",
  "*.css",
  "*.woff2",
  "*.svg",
  "*.png",
  "*.webp"
]

# Custom HTTP response headers injected into every response:
[static.headers]
"X-Frame-Options" = "DENY"
"Content-Security-Policy" = "default-src 'self'"

Automatic HTTP Conditional Requests (304 Not Modified)

MicroFly's static web server automatically handles HTTP ETag and Last-Modified headers:

  • If a browser sends If-None-Match: "<etag>" or If-Modified-Since, MicroFly compares the release file metadata and returns 304 Not Modified with zero response body payload.
  • Byte-range requests (Range: bytes=0-1024) are fully supported for video, audio, and large assets (206 Partial Content).

3. Single Page Application (SPA) Routing

In client-side frameworks (React Router, Vue Router, Nuxt, SvelteKit):

  1. A user visits /dashboard/analytics.
  2. The web server does not have a physical /dashboard/analytics file on disk.
  3. With spa = true, MicroFly automatically intercepts the missing path and serves index.html with status 200 OK.
  4. The client-side JavaScript router takes over and renders the requested view without 404 errors.

4. Clean URLs

With clean_urls = true, static sites (such as Hugo, Astro, or static HTML) can use clean, extensionless paths:

  • Visiting /about automatically serves about.html from the release directory.
  • Visiting /contact automatically serves contact.html.

MicroFly enforces strict filesystem isolation for static web apps:

  • Path Traversal Protection: All URL paths are normalized using filepath.Clean. Any request containing .. or null bytes that escapes the designated static root is rejected with 403 Forbidden.
  • Symlink Sandbox (os.OpenRoot): Symlinks are evaluated with Go's kernel-isolated root filesystem APIs. Symlinks pointing outside the application's release directory are rejected immediately.
  • Directory Indexing Disabled: Directory browsing is strictly disabled; requesting a folder without an index file returns 404 Not Found.

Released under the MIT License.