Static sites

Deploy a folder of pages, styles, scripts and pictures, as your build makes it, and it is served over HTTPS at an address of its own on filefreak.page. From your terminal, from CI, or from a folder in your drive. Part of Pro, $9.99 a month.

Deploy a folder

filefreak login
filefreak sites create my-site
filefreak sites deploy ./public --site my-site

With the CLI installed and signed in, sites create makes the site. Its name is the start of its address, so this one is https://my-site.filefreak.page. sites deploy sends the folder as it is, such as a build's dist or out, makes the deploy live as soon as it is ready, and prints the address. Deploying again sends only the files whose bytes the site does not have already.

On the website, a folder in My files deploys from its three dots, and its files are copied, so changing the folder afterwards does not change the site. The desktop client deploys a folder on your computer the same way. Each site's page on the website lists its deploys.

HTTPS, at an address of its own

Every site is served over HTTPS at https://<name>.filefreak.page, with a certificate FileFreak looks after: there is nothing to set up or renew. A visitor who asks for an http:// address is sent to the same one over HTTPS. Browsers only ever open a .page address over HTTPS in any case.

Each deploy has an address of its own as well, https://<deploy>--my-site.filefreak.page, which keeps working whichever deploy is live: deploy with --no-live, look at it there, then make it live.

A domain of your own

With Pro, your sites can answer at up to 10 domains of your own, such as www.example.com. Add one on the site's page or with filefreak sites add-domain my-site www.example.com, and make the two DNS records it gives where the domain's DNS is kept: a TXT record that proves the domain is yours, and a CNAME that sends its visitors to the site. Its certificate is issued once the CNAME is there, and then the site answers at the domain too, with plain HTTP sent to HTTPS. A bare domain, example.com, works where its DNS host can point it with ALIAS, ANAME or CNAME flattening.

Deploy from CI

In a build, where nobody is there to sign in, the CLI takes an app's key in FILEFREAK_KEY instead, and asks no questions. Under Developers, make an app, make the site in it (on its page, or with filefreak sites create my-site --app my-app), and give the app a key that may only deploy sites. Keep the key in your CI's secrets as FILEFREAK_KEY, then:

curl -fsSL https://filefreak.io/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
filefreak sites deploy ./out --site my-site --quiet

--quiet prints only what goes wrong, and the address. A key like this reaches its own app's sites and no others: it can make a site, deploy, and choose which deploy is live. Renaming or deleting a site, taking it offline and its domains stay with you, on the website or with filefreak login. A personal key cannot deploy a site. The developer API deploys the same way, for a program of your own.

To deploy on every push to GitHub, add this workflow to the repository as .github/workflows/deploy.yml, with the key in the repository's secrets as FILEFREAK_KEY. Put your own build where it says, and the folder it makes in place of ./out.

name: Deploy the site
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      # Your own build, which writes the site to ./out
      - run: npm ci && npm run build
      - name: Deploy to FileFreak
        env:
          FILEFREAK_KEY: ${{ secrets.FILEFREAK_KEY }}
        run: |
          curl -fsSL https://filefreak.io/install.sh | sh
          export PATH="$HOME/.local/bin:$PATH"
          filefreak sites deploy ./out --site my-site --quiet

Redirects and headers of your own

Put a _redirects file and a _headers file at the top of the folder you deploy, written as Cloudflare Pages and Netlify read them, and each deploy follows its own from the moment it is live. They are rules, not pages: they are not served as files.

# A page that moved
/old-page /new-page 301
# A whole section, keeping the rest of the address
/blog/* /posts/:splat 301
# One part of the address, carried across
/docs/:version/start /docs/:version/getting-started 301
# Somewhere else altogether
/chat https://chat.example.com/ 302

Each line is where from, where to, and the status: 301, 302, 303, 307 or 308, and 302 when none is given. * matches the rest of an address and is written into the destination as :splat; :name matches one part, up to the next slash. The first rule that matches is followed, top to bottom, even where the deploy has a file at the address. The query goes along, unless the destination has one of its own. A line that cannot be followed is skipped: a 200 rewrite, a 404, or a condition on the query, a country or a cookie.

# Every page
/*
  Content-Security-Policy: default-src 'self'
  X-Frame-Options: DENY
# Files whose names change when their contents do
/assets/*
  Cache-Control: public, max-age=31536000, immutable
# Pictures need no policy
/*.png
  ! Content-Security-Policy

Each rule is an address pattern at the start of a line, then its headers, indented. A request gets the headers of every rule it matches: a header two rules set has both values, joined with a comma, and ! Name takes one away. A pattern can name a domain as well, as https://www.example.com/*. What the edge itself decides is not yours to set: Set-Cookie, the length and the encoding, the ETag, X-Content-Type-Options, and Location, which is a redirect's.

A _redirects file may have 2,000 rules for plain addresses and 100 with a * or a placeholder, each line up to 1,000 characters. A _headers file may have 100 rules, each line up to 2,000 characters. Each file is at most 128 kB, and a deploy with a larger one is refused. Where Netlify reads these files differently, the edge does as Cloudflare Pages does: a rule with no status is a 302, not a 301, and a rule is followed even where a file is at its address, so Netlify's ! after a status changes nothing.

A password on a site

Give a site a password on its page, or with filefreak sites password my-site, and visitors are asked for it before they see anything of the site: at its address, at its own domains and at each deploy's own address. Somebody who gives it is let in on that address for 7 days. Changing the password, even to the same one, asks everybody again, within a minute. Wrong guesses are limited for each site and for each visitor.

A page behind a password is sent with Cache-Control: private, whatever your own headers say, so nothing between you and a visitor keeps a copy for anybody else.

Every deploy kept, and instant to go back to

filefreak sites deploys my-site
filefreak sites live my-site 3

A site keeps its 10 newest deploys besides the live one. Making one live, an older one or one kept back, is a click on the site's page or one command: nothing is uploaded again, and visitors are served it within a minute.

filefreak sites live my-site --offline takes the site offline: visitors are told so, and nothing is deleted. Making a deploy live puts it back.

How pages are answered

  • /about/ is answered with /about/index.html. /about is answered with a file named /about, then /about.html, and otherwise, where /about/index.html is there, with a redirect to /about/. A build made with trailing slashes, or without them, works as it is.
  • An address with no file is a 404, with your own /404.html if the deploy has one.
  • A site made as a single-page app (filefreak sites create my-site --single-page, or the box on its page) answers an address with no file of its own and no extension with /index.html, for an app that finds its own pages. A site exported page by page is not one: filefreak sites update my-site --single-page false changes it, from CI too, and visitors see it within a minute.
  • Every file is sent with Cache-Control: public, max-age=0, must-revalidate and an ETag, so a browser asks each time, is told in a few bytes when nothing changed, and never shows an old deploy from its own cache.
  • Each file is sent as the type its extension says, with X-Content-Type-Options: nosniff.
  • Names that start with a dot, such as .git, .env and .DS_Store, are left out of every deploy, except .well-known, so a folder's own housekeeping is never published by accident.
  • A site is its files: GET and HEAD are answered, and no code runs on the server.

Every site is at an address under filefreak.page, and until that name is on the Public Suffix List, which browsers use to keep such sites apart, the sites there share cookies: any of them can set one the others are sent. Keep sign-ins in local storage or IndexedDB, which belong to your site's address alone.

What a site may hold

WhatHow much
Sites on Pro20
Sites on FreeNone. Sites are part of Pro.
Files in a deploy20,000
A fileUp to 100 MB
A deployUp to 1 GB in all
Deploys keptThe live one, and the 10 newest besides it
A site's name3 to 40 lower-case letters, digits and hyphens. A deleted or renamed site's name is kept for you for 90 days.

Visitors, and what they cost

What a site holds counts toward your storage, each file's bytes once however many deploys have it. What its visitors download counts toward your downloads: Pro includes 50 GB a month, then 10 cents a GB, up to the spending limit you set, $10 a month to begin with. The edge keeps each file it fetches for a day in each place it serves from, and only that fetch counts: a file the edge has already, or a browser being told nothing changed, costs nothing.

At the spending limit, a page the edge does not have is answered with “This site is resting”, and browsers are asked to come back in an hour, while the files it has go on being served. Raise the limit and the site carries on within a minute. An app can have a limit of its own, and an app at its limit rests all its sites. On Free, sites are not served. How Pro is charged

Who visits

Turn on analytics for a site and see its visitors, pages, where they came from, how fast the pages were and the errors visitors met, with no cookie and nothing stored on a visitor's device. Your files do not change: the edge adds its script to each page as it serves it. What you see can be saved as CSV or JSON, and filefreak analytics report my-site prints the same from a terminal.

Not here yet

  • Rewrites and proxying: answering one address with another's file, or with another server's answer, as a 200 rule does elsewhere.

Start with Pro

Sites, apps and the developer API come with Pro, with 250 GB of storage and 50 GB of downloads a month for all of it. The CLI is free on every plan.