This template is built for SvelteKit SPAs on GitHub Pages, the main issue with GitHub Pages and SvelteKit SPAs
is that GitHub Pages cannot resolve dynamic routes, if you have a route like /blog/[slug], if you go
to it through SvelteKit's router (by lieu of an <a> tag or await goto('/blog/' + slug)) it works fine, but if you try
refreshing the page or going to the route manually by editing the URL, GitHub Pages will return a 404.
For the TL;DR on how this works, basically, we define a "fallback" page which is a page that simply starts the router,
in GitHub Pages, if you define a 404.html file, when it encounters a 404, it goes back to that page.
So SvelteKit generates a file called 404.html that starts the router if we define it in the adapter's options.
There is also a demo app you can find at https://vloddot.github.io/sveltekit-gh-pages-spa-template which showcases this.
To switch a SvelteKit app to an SPA, the best way is to use @sveltejs/adapter-static instead of @sveltejs/adapter-auto.
pnpm add -D @sveltejs/adapter-static
pnpm remove @sveltejs/adapter-auto # @sveltejs/adapter-auto is pre-installed in most SvelteKit setups.
...Then configure it to use @sveltejs/adapter-static instead of @sveltejs/adapter-auto and add some configuration for GitHub Pages
and the src/404.html file:
import adapter from '@sveltejs/adapter-static'; // edit this line
import { vitePreprocess } from '@sveltejs/kit/vite';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
// for more information about preprocessors
preprocess: vitePreprocess(),
kit: {
paths: {
// If you're using custom domains, this can be left out. Since GitHub Pages usually has
// a format of `<username>.github.io/<repositoryname>`, `base` needs to be set to accomodate
// that. Replace `sveltekit-gh-pages-spa-template` to your repository's name.
base: process.env.NODE_ENV == 'production' ? '/sveltekit-gh-pages-spa-template' : ''
},
adapter: adapter({ fallback: '404.html' }) // rely on `404.html` when rending dynamic routes
}
};
export default config;
You also need to create a src/routes/+layout.ts/js file to mark routes as prerendered and non-SSR.
export const prerender = true;
export const ssr = false;
If you're not using a custom domain (not <username>.github.io/<repositoryname>) and edited the base value in the SvelteKit configuration,
you need to replace all the routes that are through <a> tags, goto or redirect with {base}/{route}.
So if you are trying to route to /blog/[slug], you need to add {base}/blog/{slug} (and import { base } from '$app/paths')
instead of /blog/{slug} since without the {base}, in production code (GitHub Pages), it will try to route to /blog/[slug] which
doesn't exist, what exists however is /<repositoryname>/blog/[slug].
Note that this isn't necessary for relative routes so if you are making a dynamic route, something like
/blog/[slug]and/blog/foohas a "relative route", an<a>tag withhref="bar", there's no need to change it, since it will simply replace the current slug withbarwhen navigating to it.