About the project
I built this site with Angular and TypeScript to have one place for my projects, experience and reports. It has a light and dark theme, a few small interface animations and inline previews for the PDF reports. Pages are pre-rendered on the server with Angular Universal, which I mainly wanted for search engines and for link previews on social media, since a plain Angular app only serves them an empty shell. Everything runs in Docker so my laptop and my server build the same thing.
Automatic CV generation
The backend generates a PDF of my CV on request. Going to `/cv.pdf` makes the server compile a Typst template with the same data the CV section of the site uses, so when something changes I only have to update it in one place.
Each request passes the CV data into Typst as an input parameter, compiles the template in one pass and streams the PDF straight back in the response. Typst is a single static binary and renders fast enough that I did not bother with caching. The fonts are bundled next to the template and system fonts are switched off, because otherwise the output would depend on whatever happens to be installed on the machine. The Typst binary is copied into the Docker image as well.
From LaTeX to Typst. This used to compile a LaTeX template with a bundled TinyTeX toolchain, which needed two passes and took roughly 1.2s per request. Following Typst's automated PDF generation guide I moved it to a single Typst template fed through
sys.inputs. That brought it down to about 150ms and made the Docker image quite a bit smaller.
Markdown-based project pages
Every project page is a Markdown file with YAML frontmatter for the metadata such as title, images, keywords and quick links. These files are parsed and turned into HTML when the site is pre-rendered, so I can add a project without touching any Angular templates. The body supports images, headings, links and reference anchors. Each page also links to its own Markdown source if you want to read the original.
Translations
The site is available in English and Dutch. Interface labels, navigation and static text come from separate translation files that are loaded based on the selected locale. Project descriptions can be translated too by putting a locale-specific Markdown file next to the English one (content.en.md and content.nl.md). Not every project has a Dutch version yet, and the ones that do not simply fall back to English.
RSS feed
There is an RSS feed at `/feed.xml` if you want to follow new projects in a reader like Feedly. It uses the same project data and sitemap dates as the rest of the site, so I do not have to maintain it separately. Each entry has the title, description, cover image, tags and publish date.
Key features
- Responsive layout with light and dark theme support.
- Built with Angular, TypeScript and Node.js.
- Project pages with descriptions, images and report previews.
- Small UI animations and transitions.
- PDF previews for project reports directly on the site.
- Automatic CV generation through a /cv.pdf endpoint.
- Website CV section and PDF CV share the same data source.
- Server-side rendering for better performance and SEO.
- Typst-based CV compilation handled by the backend.