My Homepage
A website built with Astro and Svelte
Welcome to my personal homepage! In this article you can learn about how this website was built, and what drove my decision making.
Built For Speed
Today, there is a plethora of front-end frameworks to choose from when building a personal website or blog. While researching options I came across the Astro project, which immediately resonated with my goal of building a lighting fast, content-driven, an mostly static website.
Astro is an opinionated open-source framework with the goal of building fast and cachable web pages. While it can be used to dynamically render content server-side or client-side, its default behaviour is to render static HTML pages. This simplifies prioritising loading speed and makes Astro one of the most capable and fastest static-site frameworks.
One of the most powerful features of Astro is the ability to use components written for other front-end frameworks such as Svelte or Vue. This hands an unprecedented amount of flexibility to developers to mix and match framework components and choose whichever framework is suited best to solve a particular problem. For example, I chose Svelte because of its feature rich animation library, but was also able to add a single component built in React when I couldn’t find a suitable library for Astro or Svelte.
Animations
Animations are satisfying. They present a simple way to make a static page feel more alive and organic. I’ve experimented with various animation types on this homepage, which are explained in more detail in the following sections.
Scroll Based Animations
There are many libraries to animate elements, when they enter the viewport. These usually rely on the
IntersectionObserver
-API and therefore require client-side JavaScript to be downloaded for the animations to work. One
of Astro’s main selling points is, that it ships 0 JavaScript by default and it therefore felt unnatural to me, to add
an animation library for this and lose one of the main advantages of the Astro framework.
The animation-timeline
property fills this gap
perfectly (although browser support is not great at the moment). It’s using normal CSS @keyframe
definitions in
combination with the view()
or scroll()
helpers and its usage should be quite familiar to people who have worked
with CSS animations before.
The slide-in animation of the text elements in the video above can be implemented with a few lines of CSS.
.timeline-slide-in-bottom {
animation-timeline: view();
animation-range: entry 100% contain 25%;
animation-name: slide-scale-in-bottom;
animation-fill-mode: both;
}
@keyframes slide-scale-in-bottom {
from {
transform: translateY(100px);
scale: 0.8;
opacity: 0;
}
to {
transform: translateY(0);
scale: 1;
opacity: 1;
}
}
View transitions
Astro generates multi-page applications (MPAs) by default. For each route a dedicated HTML page is generated and when
a user navigates to a new page the browser just serves the new document. This is great for performance, because
every individual page can be cached on the CDN. But it makes it more difficult to generate nice transitions between
elements, when a new page is loaded, which is fairly easy to achieve with single-page applications (SPAs). To fill this
feature gap, the View Transitions API has been
developed, which let’s the developer mark elements with a view-transition-name
and then the browser will generate
animations between elements with the same name across documents. Here is an example of what this looks like:
Only Chromium-based browsers support this API at the moment, however, Astro comes with a polyfill to make the transitions work in all browsers.
The Logo
During my PhD, I worked a lot with graph representations of clusters. One very commonly found structural pattern is that of the Icosahedron, one of the five Platonic solids. The image shown in the favicon (and footer) is just a projection of this 3-dimensional structure in to the 2d plane called a graph. It allows for easy identification of the underlying connectivity (edges) of the vertices of the structure.
This graph picture was created for my PhD thesis and I noticed fairly quickly, that it would pose as a great candidate for Svelte’s SVG drawing library.
To get this working, I had to separate the individually animated path sequences and make sure that they are represented by a single line without any outlines. All that was left now was to use Svelte’s draw function to draw in the individual path segments with slightly delayed timings for a more organic feel.
<script lang="ts">
import { draw } from "svelte/transition";
import { onMount } from "svelte";
let show = false;
onMount(() => {
show = true;
});
</script>
<svg>
{#if show}
<g>
<path
transition:draw={{ duration: 2500 }}
d="m 138.20133,96.169887 36.67167,-0.0021 -18.3441,45.885573 -48.88072,-28.2213 30.55424,-17.662998 18.32544,45.882238"
/>
<path
transition:draw={{ delay: 150, duration: 2500 }}
d="M 174.76114,96.115464 156.42349,64.357912 205.33361,57.301583 V 113.74417 L 174.75988,96.114924 205.33234,57.303514"
/>
...
</g>
{/if}
</svg>
Using the onMount
function is necessary, because Svelte’s transition directives only work when the markup gets
inserted into the DOM. This works well in combination with Astro’s client:visible
directive, so that the component
starts animating when it first appears in the viewport. The full component can be found
here.