'Sevltekit 404 error when refreshing dynamic route

I want a static page that loads content dynamically based on URL, for example like this: https://example.com/pokemon/id

It can load on the server or on the client-side like a single page aplication.

svelte.config.js

import adapter from '@sveltejs/adapter-static';

    export default {
        kit: {
            adapter: adapter({
                pages: 'build',
                assets: 'build',
                fallback: null
            }),
        }
    };

[id].svelte

<script context="module">
export const hydrate = false;
    import { getPokemonById } from "../../stores/pokestore";
    export async function load(ctx) {
        let id = ctx.page.params.id;
        const pokeman = await getPokemonById(id);
        return { props: { pokeman }}
    }
</script>
<script>
    export let pokeman;
    const type = pokeman.types[0].type.name;
</script>
<svelte:head>
    <title>Pokedex - {pokeman.name}</title>
</svelte:head>

<div class="flex flex-col items-center">
    <h1 class="text-4xl text-center my-8 uppercase">{pokeman.name}</h1>
    <p>Type: <strong>{type}</strong> | Height: <strong>{pokeman.height}</strong>
        | Weight: <strong>{pokeman.weight}</strong>
    </p>
    <img class="card-image" src={pokeman.sprites['front_default']} 
    alt={pokeman.name}
    />
</div>

This works fine if go on the homepage and click on the link:

<a href={`/pokeman/${pokeman.id}`}><h2>{pokeman.name}</h2></a>

But if I refresh this page I got error 404 because this page doesn't exist.

I can't generate all subpages during build time, because they are dynamic.

I host this website on Firebase hosting.



Solution 1:[1]

Highly likely this is a redirection issue.

When you click the link from the homepage you do not actually 'go' to this page, sveltekit changes the url but you stay on the same page, you can see this by clicking 'open in new tab'.

What is happening here is that when you go directly to the page your server cannot find this page, hence the 404 page. You need to set up a redirect system that reroutes all your page back to the root page (sveltekit routing will take it from there).

How this is setup depends on your host

Solution 2:[2]

Svelte community on Discord helped me with my problem.

Because I host website on the Firebase hosting I had to add rewrite rules in firebase.json like this:

"hosting": {
    "public": "build",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  },

Solution 3:[3]

In case it's helpful, this is what I'm using in my .htaccess file on an Apache server to solve this problem:

# Redirect all to the index
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
</IfModule>

A refresh will load the main index.html page, but it still retains the prior url (which isn't right): domain.com/sample/url

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Stephane Vanraes
Solution 2 Xstyler
Solution 3 Clifton Labrum