Skip to content

A website using Astro and React

A rewrite of samber's awesome-prometheus-alerts using a new design and stack

Posted on:
2 min

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:

  1. 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)
  2. Simple Icons when used with astro-icon has no color by default, which isn’t an acceptable state.
  3. I never noticed this before but Astro components and <script> tags within them cannot share variables directly which is a bit of a pain.
  4. I ran into npm issues with package-lock.json not handling OS-specific dependencies correctly. Using pnpm fixed the package-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

The lighthouse score is pretty good for something that uses React, and was built in a day or so.

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.