DEV Community

Cover image for SvelteKit Static Site HTTP Headers
Rodney Lab
Rodney Lab

Posted on • Originally published at rodneylab.com

SvelteKit Static Site HTTP Headers

✨ What is a Static Site?

In this post we look at how to set up SvelteKit static site HTTP headers. SvelteKit, similarly to tools like Next JS, lets you generate static as well as Server Side Rendered (SSR) sites. SSR is not to be confused with a static site generator (SSG) which is a tool for generating static pages. Static just means that the page is built once for all visitors (rather than custom built for every visitor) and is typically the same for every user. An example is a typical blog or news site. A site like Twitter however needs to show different content based on who logged in β€” tweets from the people you follow, messages from your contacts and so on. Typically since the content it different for every user, a static build will not suit this case.

You can create static sites in SvelteKit using the static adapter. Using that adapter, you can deploy your site to Cloudflare Pages, Netlify and Render among other hosting providers.

We will first take a look at the uses for custom static headers, then have a quick run through the differences between setting SvelteKit static site HTTP headers for static sites and SSR sites. Finally we will look at how you might go about adding custom HTTP headers to your static SvelteKit site. If that sounds appealing, let's read on!

πŸ˜• What do HTTP Headers do?

HTTP headers are sent along with the body as part fo the server response when you visit a website. The body contains the content you see while the headers contain meta data. These are different to the HTML head section which is included in the response body. As an example cookies are often sent in HTTP header responses from servers. Another example are the dreaded CORS Access Control headers! On your static site you might want to set custom HTTP headers to instruct search engine crawlers or bots not to crawl your site. On top you can use then to boost your site's security.

Here's an example of an HTTP header instructing a bot not to index a page:

X-Robots-Tag: noindex
Enter fullscreen mode Exit fullscreen mode

The HTTP headers are sent with a response from each page, and can be customised on a per-page basis. This would be useful if you had some pages you were happy for search engines to index while not wanting them to index others.

πŸ”Œ Using the SvelteKit Static Adapter

Just like there are SvelteKit adapters for building SSR sites to run on Cloudflare Workers, Netlify, Node-based environments and Render, there is an adapter for building static sites. Note you can use the same SvelteKit static adapter for all the hosts mentioned above. There is not too much to configuring it. First download the next version of the static the adapter into your project:

pnpm i -D @sveltejs/adapter-static@next
Enter fullscreen mode Exit fullscreen mode

Then update you svelte.config.js file to use the adapter:

/** @type {import('@sveltejs/kit').Config} */
import adapter from '@sveltejs/adapter-static';

const config = {
  kit: {
    adapter: adapter(),
    // hydrate the <div id="svelte"> element in src/app.html
    target: '#svelte'
    }
};

export default config
Enter fullscreen mode Exit fullscreen mode

Note you can also go for the half-in-half-out option, where you make only some pages static. In this case, you use the SSR adapter for your platform, then add this line to the load function in the Svelte file for any pages you want to static render:

<script context="module">
    export const prerender = true;
  ...
</script>
Enter fullscreen mode Exit fullscreen mode

βš–οΈ How is Adding Custom HTTP Headers different for Static Sites?

With server side rendered sites, you can use the src/hooks.js file to add any headers you want to the HTTP responses. As an example you can take a peek at the SvelteKit MDsveX Starter.

Because your node server, Lambda Function or Cloudflare worker which provides server side content sends the headers, you can update headers from the hooks.js file. With a static site, it is the Cloudflare, Netlify or Render servers which respond directly to HTTP requests. That does not mean you cannot add custom headers though! Typically, you add a _headers file to your build directory and you're away (with Render you update the headers in the Dashboard). We'll look at this next.

βš™οΈ Adding Custom HTTP Headers to your Static SvelteKit Site

In the previous section we saw you need to add a _headers file to your SvelteKit build directory. This will work with Cloudflare Pages and Netlify. By default, your build directory will be /build in the root directory of your project.

Probably the easiest way to create the _headers file is to write a short script that generates it and update your package.json file's build script to run that script. This way your host will generate the file automatically when you run builds.

To do this first update your package.json file:

{
  "name": "sveltekit-blog-mdx",
  "version": "1.0.0",
  "scripts": {
    "dev": "svelte-kit dev --port 3000",
    "build": "svelte-kit build && node ./generate-headers",
    "preview": "svelte-kit preview --port 3000",
    "generate:headers": "node ./generate-headers.js",
  },
  ...
}
Enter fullscreen mode Exit fullscreen mode

Then create a script which adds the headers you want in a generate-headers.js file in the root directory of your project:

import fs from 'fs';
import path from 'path';

const __dirname = path.resolve();
const buildDir = path.join(__dirname, 'build');

function main() {
  const headers = `/*
  X-Frame-Options: DENY
  X-XSS-Protection: 1; mode=block
  X-Content-Type-Options: nosniff
  Referrer-Policy: same-origin
  Permissions-Policy: accelerometer=(), autoplay=(), camera=(), document-domain=(), encrypted-media=(), fullscreen=(), gyroscope=(), interest-cohort=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), sync-xhr=(), usb=(), xr-spatial-tracking=(), geolocation=()
  Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
`;

  const headersFile = path.join(buildDir, '_headers');
  fs.writeFileSync(headersFile, headers);
}

main();
Enter fullscreen mode Exit fullscreen mode

This is just to give you an idea of what you might want to add. You might consider adding Content Security Policy headers or making the Permissions Policy headers less restrictive. If your aim is improving security, run a test on securityheaders.com or see the Mozilla Observatory as an alternative from this list of useful links:

If you are hosting your static site on Render, you can add headers in the Render dashboard.

πŸ™ŒπŸ½ SvelteKit Static Site HTTP Headers: What we Learned

In this post we saw:

  • what HTTP headers are,

  • how SSR sites differ from static sites,

  • a way you might include custom SvelteKit static site HTTP headers in your project.

I do hope there is at least one thing in this article which you can use in your work or a side project. As always get in touch with feedback if I have missed a trick somewhere!

Β πŸ™πŸ½ SvelteKit Static Site HTTP Headers: Feedback

Have you found the post useful? Do you have your own methods for solving this problem? Let me know your solution. Would you like to see posts on another topic instead? Get in touch with ideas for new posts. Also if you like my writing style, get in touch if I can write some posts for your company site on a consultancy basis. Read on to find ways to get in touch, further below. If you want to support posts similar to this one and can spare a few dollars, euros or pounds, please consider supporting me through Buy me a Coffee.

Finally, feel free to share the post on your social media accounts for all your followers who will find it useful. As well as leaving a comment below, you can get in touch via @askRodney on Twitter and also askRodney on Telegram. Also, see further ways to get in touch with Rodney Lab. I post regularly on SvelteKit as well as other topics. Also subscribe to the newsletter to keep up-to-date with our latest projects.

Top comments (0)