The Stack
Astro is a web framework designed for fast, content-driven websites. With heavy use of server-side rendering and a no-JS-by-default philosophy, Astro enables building performant sites with SEO optimisations - perfect for a blog. Astro is also UI-agnostic, meaning it supports plain old HTML, JS and CSS but also the integration of components from React, Vue, Svelte, Solid and more. Do not underestimate how smooth the transition to Astro can be for you if you know just one of these different component structures.
Contentful is a flexible, headless CMS platform with a powerful API and a generous pricing model allowing for a zero-cost CMS regardless of scale (when combined with static-site generation).
Tailwind has quickly solidified itself as an industry standard, allowing for extremely quick and flexible styling of any application. Styles can sit directly with the HTML of components, largely removing the need for stylesheets and the headaches that come with them.
Vercel is an incredible frontend hosting platform, with top-tier CI/CD integration with GitHub repositories. This blog builds and deploys on the Vercel pipeline in under 20 seconds. It’s primarily driven by Next.js, also maintained by the Vercel team, to allow hosting of static sites, server-side rendered sites, and hosting on the Edge. The free hobby tier includes 100GB of bandwidth, where the Pro tier offers up to 1TB of bandwidth for only $20/month.
Benefits
All in, the chosen stack currently incurs a monthly cost of £0 a month. Vercel’s generous 100GB of bandwidth has hosting covered, and Contentful is generous also, offering 10,000 records and 750GB of bandwidth for free.
It’s important to note that, due to the static nature of the Astro site where all pages are pre-compiled at build time, the usage of the Contentful API is extremely minimal; We only request content at build time, not on each page request.
Fetching content and compiling all pages at build time isn’t just a cost-saving trick - it also helps pages feel incredibly quick for users (I hope you’ve noticed) and bakes in content as raw, static HTML for search engine crawlers, greatly helping with SEO.
This website achieves 100/100 on all 4 metrics (Perf, Accessibility, SEO and Best Practices) of the Chrome Lighthouse report, something that would be difficult to achieve with something less sophisticated like vanilla React.
Limitations
No stack is perfect for all use cases, and Astro is no different. Astro is, first and foremost, designed for building content-first websites. This means it does an incredible job of fetching data from remote sources and compiling static HTML with minimal (or zero) JavaScript at request-time, but if you’re looking to build an application that is driven by real-time data, you may find the benefits of Astro start to dissolve.
This isn’t to say Astro cannot fetch and display real-time information on a client - it can - it’s just that Astro should most likely be avoided if that’s all you’re going to do.
It’s hard to say at what mixture of pre-compiled and real-time data fetching Astro pays off or starts to weaken; I’ll leave that question to you to decide for your use case.
Starting with Astro
Note: Commands that use npm can all be swapped to your package manager of choice (yarn, pnpm, etc).
Astro, like many modern frameworks, offers a very easy start-up experience. See here for how.
npm create astro@latest
Unlike most other frameworks, Astro offers integrations to help configure common 3rd party tools like Tailwind.
For this website, I configured a number of these integrations:
React
Vercel
Tailwind
sitemap
image
partytown
Where each integration has an interactive wizard to guide you through what the integration is doing.
npx astro add react
npx astro add vercel
npx astro add tailwind
npx astro add sitemap
npx astro add image
npx astro add partytown
This is all that’s needed to configure these various integrations - we can now use React components, Tailwind styling, host in Vercel, auto-generate a sitemap, host processes like Google Analytics in a web worker via Partytown, and convert out images into optimised formats for the web.
The Contentful CMS
For content on the blog, I didn’t want to have to write markdown or manually commit and deploy changes to the site. This is where a headless CMS comes in - we simply modify our content in the CMS, and our site will fetch and display that content when a page is requested.
With Astro, this is a bit different. Due to Astro statically generating our web pages during our build, the process of fetching and displaying content isn’t done at request time. Does this mean we need to manually rebuild and redeploy our site every time we want to change content?
Yes, and no. Rebuilding in response to content changes is controlled via a webhook from Contentful, and thanks to the zero-downtime hosting from Vercel users will never see this happen. It allows us to stay 100% statically generated without adding maintenance headaches with redeployments and has no impact on user experience. 🎉
Signing up for Contentful is free and quick, here.
Combining React and Astro Components
Due to the nature of Astro, it’s possible to write components in both Astro and React style components.
For the most part, I utilised Astro components for pages (as this enables the use of statically generated pages and dynamic routing) and React components for purely structural and behavioural sections of pages. For example, React was used for Blog cards or tag links, and a progress bar indicating how far through a blog post a user is.
There is no reason to not go 100% Astro; I’m just more comfortable writing these simple components in React FCs.
Client-side Components
By default, all components are rendered statically on the server. This isn’t what we want in all scenarios though. The previously mentioned progress bar is a good example of a component that we want to run on the client.
If the component was only rendered statically on the server, the progress bar would never move.
To instruct Astro to ship a component to the client to be rendered there is simple - only the client:load
attribute is needed. This attribute is set at the point of render, not on the component itself, which allows us to conditionally render it server or client side, depending on the scenario.
Hosting in Vercel
Hosting an application in Vercel is incredibly easy - simply sign up for a free plan and create a project, pointing it to a GitHub repository.
There are no build scripts or pipelines to manage as there is in other tools like Azure DevOps - Vercel understands many of the popular frontend frameworks and understands how to build them for you.
Rebuilding the statically generated content on CMS change
As our site is generated ahead of time at the point of build within Vercel, we need to tell Vercel to build the app whenever the content in the CMS changes.
Luckily, both Contentful and Vercel both offer the ability to publish and subscribe to webhooks - whenever content is changed in Contentful, a webhook is fired to Vercel and a build is triggered.
Vercel also features 0 downtime deployments, so the process of rebuilding and redeploying the site after content changes causes no interruption to users.
Open Source
This site is 100% open source and all code can be found here.