AstroJS — SPA-like behavior using 404 pages
How to serve the default index.html for any SPA URL in AstroJS using static builds, no adapters necessary
Problem
While building SquadGPT using AstroJS, I faced an issue supporting paths like /conversation/uuid-1
and /jd/uuid-2
.
This is an issue because by default, AstroJS expects all routes to be known at build time. Given that theses are UUIDs, knowing all of them in advance is not possible.
Reading the UUIDs from the database is an overkill because this will mean redeploying the entire website every time a user starts a new Chat conversation.
To get around this, you can set the build
option inside astro.config.mjs to server
which tells the build process that certain (or all) files will be rendered by the server at run time.
This option was not available to me since the entire SquadGPT website is serverless and I wanted to avoid setting up a server just to render pages at run time.
Nor did I want to use an cloud provider specific Astro adapter to use things like CloudFlare’s Workers and AWS’s Lambda@Edge functions to render a page on demand.
Solution
This is where the 404 page came to the rescue.
Once you define a 404.astro
page, tools like npm run dev
and http-server
know to serve the compiled version of 404.astro
(i.e. 404.html
) when they cannot find a path.
This technique made it possible to test my pages in dev. All I did was to create a 404.astro
page which reads the url pathname and renders the correct component.
So, if the pathname is /conversations/abcd
, show the Conversations
component, else show the JD
component.
Limitations
This is great in dev
but I still have one more issue to solve.
My CloudFront distribution which serves the SquadGPT website isn’t npm run dev
or http-server
. So, by default, it doesn’t know how to handle 404 errors gracefully. That is, if you visit a SquadGPT page which does not exist, you will see an ugly 404 message like so.
Fortunately, CloudFront allows us to return a specific 404 page on hitting a path that doesn’t exist. Once I configure that, this 404 issue should go away.
If this doesn’t work, I could always fall set up a CloudFront Function to return the contents of the /conversations/index.html
regardless of whicc specific conversation the user asks for. The same function would also work for JDs
as well.