LogoFreestyle
Guides

Static File Hosting

Deploy static websites and assets using Freestyle's native static file hosting

Freestyle's native static file hosting lets you deploy HTML, CSS, JavaScript, images, and other assets directly without needing a server. Perfect for static sites, documentation, landing pages, and modern framework outputs.

Overview

Freestyle provides built-in static file hosting options that serve your files efficiently. You can:

  • Deploy pure static sites without any server code
  • Serve public assets at your domain root
  • Serve framework-specific static directories with custom paths
  • Mix static files with dynamic server routes

Sign up at dash.freestyle.sh, create an api key, and configure it in your environment.

.env
FREESTYLE_API_KEY=your-api-key
npm i freestyle

Quick Start: Pure Static Site

For a completely static site with no server needed:

import { freestyle } from "freestyle";

const { deployment, domains } = await freestyle.serverless.deployments.create({
  repo: "https://github.com/your-username/your-static-site",
  domains: ["my-site.style.dev"],
  staticOnly: true,
  publicDir: "public", // Your static files directory
});

console.log("Deployed to:", domains[0]);

That's it! Freestyle serves all files from your public directory directly.

Static File Hosting

Freestyle offers multiple options for serving static files. Choose the approach that matches your site structure.

Public Directory: Root-Level Files

Serve files from a directory at your domain root:

const { deployment, domains } = await freestyle.serverless.deployments.create({
  repo: "https://github.com/your-username/your-site",
  domains: ["my-site.style.dev"],
  staticOnly: true,
  publicDir: "public", // All files served at root
});

Files are served without any path prefix:

  • public/favicon.ico/favicon.ico
  • public/robots.txt/robots.txt
  • public/index.html/index.html
  • public/about/index.html/about/index.html

publicDir is commonly used with Next.js, Hugo, Jekyll, and other frameworks that have a public/ directory for static assets.

Static Directory with Custom Path

Serve a specific directory at a specific URL path prefix:

const { deployment, domains } = await freestyle.serverless.deployments.create({
  repo: "https://github.com/your-username/your-site",
  domains: ["my-site.style.dev"],
  staticOnly: true,
  staticDir: ".next/static",
  staticPathPrefix: "/_next/static", // Files at this path
});

Files are served at the specified prefix:

  • .next/static/chunk.js/_next/static/chunk.js
  • .next/static/style.css/_next/static/style.css

Use staticDir with staticPathPrefix for framework-specific asset directories like Next.js's _next/static or Nuxt's .nuxt/dist/client.

Prerendered HTML

Serve prerendered HTML files that map to URL paths:

const { deployment, domains } = await freestyle.serverless.deployments.create({
  repo: "https://github.com/your-username/your-site",
  domains: ["my-site.style.dev"],
  staticOnly: true,
  prerenderedDir: "out", // Hugo, Jekyll, Static export output
});

When a request comes in, Freestyle looks for:

  • out/about.html for /about
  • out/index.html for /
  • out/blog/post.html for /blog/post

Perfect for static site generators like Hugo, Jekyll, Eleventy, or Next.js static exports.

Advanced Configuration

Clean URLs

Remove .html extensions from filenames:

const { deployment, domains } = await freestyle.serverless.deployments.create({
  repo: "https://github.com/your-username/your-site",
  domains: ["my-site.style.dev"],
  staticOnly: true,
  publicDir: "public",
  cleanUrls: true, // /about.html becomes /about
});

When cleanUrls: true:

  • Visiting /about.html redirects to /about
  • /about serves public/about.html
  • Perfect for HTML-only sites

Trailing Slashes

Control whether trailing slashes are required:

const { deployment, domains } = await freestyle.serverless.deployments.create({
  repo: "https://github.com/your-username/your-site",
  domains: ["my-site.style.dev"],
  staticOnly: true,
  publicDir: "public",
  trailingSlash: true, // /about/ required, /about redirects
});

Custom Headers

Set HTTP headers for caching, security, etc.:

const { deployment, domains } = await freestyle.serverless.deployments.create({
  repo: "https://github.com/your-username/your-site",
  domains: ["my-site.style.dev"],
  staticOnly: true,
  publicDir: "public",
  headers: [
    {
      source: "^/assets/.*$",
      headers: [
        { key: "Cache-Control", value: "max-age=31536000, immutable" },
      ],
    },
    {
      source: ".*",
      headers: [{ key: "X-Content-Type-Options", value: "nosniff" }],
    },
  ],
});

Redirects

Set up URL redirects:

const { deployment, domains } = await freestyle.serverless.deployments.create({
  repo: "https://github.com/your-username/your-site",
  domains: ["my-site.style.dev"],
  staticOnly: true,
  publicDir: "public",
  redirects: [
    {
      source: "^/old-page$",
      destination: "/new-page",
      permanent: true, // 308 permanent redirect
    },
    {
      source: "^/blog/(.*)$",
      destination: "/posts/$1",
      permanent: false, // 307 temporary redirect
    },
  ],
});

Rewrites

Rewrite URLs internally without changing the browser URL:

const { deployment, domains } = await freestyle.serverless.deployments.create({
  repo: "https://github.com/your-username/your-site",
  domains: ["my-site.style.dev"],
  staticOnly: true,
  publicDir: "public",
  rewrites: [
    {
      source: "/api/(.*)",
      destination: "https://api.example.com/$1",
    },
    {
      source: "/docs/(.*)",
      destination: "/documentation/$1",
    },
  ],
});

Common Site Generators

Next.js Static Export

const { deployment, domains } = await freestyle.serverless.deployments.create({
  repo: "https://github.com/your-username/nextjs-site",
  domains: ["my-site.style.dev"],
  staticOnly: true,
  build: {
    command: "npm run build",
  },
  publicDir: "out", // Next.js static export output
});

Hugo

const { deployment, domains } = await freestyle.serverless.deployments.create({
  repo: "https://github.com/your-username/hugo-site",
  domains: ["my-site.style.dev"],
  staticOnly: true,
  build: {
    command: "hugo",
  },
  publicDir: "public", // Hugo output directory
  cleanUrls: true,
});

Jekyll

const { deployment, domains } = await freestyle.serverless.deployments.create({
  repo: "https://github.com/your-username/jekyll-site",
  domains: ["my-site.style.dev"],
  staticOnly: true,
  build: {
    command: "jekyll build",
  },
  publicDir: "_site", // Jekyll output directory
});

Eleventy (11ty)

const { deployment, domains } = await freestyle.serverless.deployments.create({
  repo: "https://github.com/your-username/eleventy-site",
  domains: ["my-site.style.dev"],
  staticOnly: true,
  build: {
    command: "npx eleventy",
  },
  publicDir: "_site", // Eleventy output directory
});

Deploying with Git

Simply push your static site to a Git repository and deploy:

import { freestyle } from "freestyle";

const { deployment, domains } = await freestyle.serverless.deployments.create({
  repo: "https://github.com/your-username/my-static-site",
  branch: "main", // Optional: specify branch
  domains: ["my-site.style.dev"],
  staticOnly: true,
  publicDir: "public", // Your output directory
});

console.log("Deployed to:", domains[0]);

Next Steps

On this page

Freestyle AI

Documentation assistant

Experimental: AI responses may not always be accurate—please verify important details with the official documentation.

How can I help?

Ask me about Freestyle while you browse the docs.