A website using Astro and React
A rewrite of samber's awesome-prometheus-alerts using a new design and stack
I was interviewing for a front-end engineer gig with a startup using React and Astro for their marketing projects that I would work on. As an assignment, they wanted me to recreate samber’s awesome-prometheus-alerts with a new design. The source code for the rewritten website is up on GitHub. The website is hosted at awesome-prometheus.azan-n.com
I started the project by studying the Jekyll based awesome-prometheus-alerts project to figure out how it was using the YAML data from rules.yml to JSON using yq
, and eventually through a set of templates, generating HTML files.
I started by using js-yaml to fetch the data source rules.yml
and convert it to JSON on build time. I made the following observations:
- It might be a good idea to convert the
rules.yml
to JSON and store it in the git repository instead of fetching it every time we build, and re-fetch periodically since it is the only variable data source. (The original project does the same in the build step, I wonder why they store the default in YAML if they end up converting it to JSON anyway) - Simple Icons when used with astro-icon has no color by default, which isn’t an acceptable state.
- I never noticed this before but Astro components and
<script>
tags within them cannot share variables directly which is a bit of a pain. - I ran into npm issues with
package-lock.json
not handling OS-specific dependencies correctly. Using pnpm fixed thepackage-lock.json
issue, not sure how.
Async flashbacks
I hadn’t explored the React integration with Astro in a while and wanted to see if I could borrow some React components into the project. However, as of 10/06/2024, React in Astro is like async in JS, you make one function async and everything ends up being async. You make one component JSX/TSX and almost everything ends up being JSX/TSX.
With the React integration, the architecture of how to use Astro components and React components together has to be made carefully since framework components cannot use Astro components within them. I wanted syntax-highlighting to be done using Shiki on build-time because the code being highlighted does not change on the client. I was able to make this work by passing a statically rendered Astro component as a child to a React dialog. The experimentalReactChildren: true
property seems promising but it is rightly marked as experimental.
<div class="row-start-3 row-end-4">
<!-- React-based dialog to show exporter rules -->
<ServiceRulesDialog service={service} client:load >
<!-- Prerendered Astro content, prevents having to get a code=highlighter on runtime -->
<ExporterRules exporters={service.exporters} />
</ServiceRulesDialog>
</div>
Searching
Using React for handling the searching would, in the possibilities that I explored, make the Astro project a regular React SPA, with the pain points of the @astro/react
integration.
To prevent the same, I implemented searching using vanilla JS and HTML data attributes as follows:
<script>
const HIDDEN_CLASS = "hidden";
const SERVICE_CARD_SELECTOR = "[data-service-name]";
function filterServices(searchTerm: string) {
const sections = document.querySelectorAll("[data-group-name]");
// hide or unhide the element, animations would be nice
}
</script>
Looking ahead
JSX is great, it is expressive, components are functions and functions can be passed around and rendered, this allows for flexible composition, which I miss when using Astro components. I look forward to a time where I can do actual SSG using React components.