All projectsPersonal Portfolio & Blog

Personal Portfolio & Blog

A blog-first personal portfolio built with React, Vite, and Tailwind CSS v4. Blog posts and projects are written as Markdown files — no backend required.

reactvitetailwindmarkdown

Overview

This is the portfolio you're currently reading. I built it as a way to learn Vite, practice Tailwind CSS v4, and have a place to write publicly.

The design goal was simple: maximum readability, minimum noise. Black and white. Good typography. Fast load times.

How it works

There's no backend, no CMS, no database. Content is stored as Markdown files:

src/
├── posts/          ← blog posts as .md files
└── projects/       ← project writeups as .md files

Vite's import.meta.glob picks up all .md files at build time:

const rawFiles = import.meta.glob('/src/posts/*.md', {
  query: '?raw',
  import: 'default',
  eager: true,
});

Each file has YAML frontmatter (title, date, tags, etc.) parsed by front-matter, and the body is rendered by react-markdown with GFM support and syntax highlighting.

Tech stack

LayerTechnology
FrameworkReact 19 + Vite 8
RoutingReact Router v7
StylingTailwind CSS v4
Markdownreact-markdown + remark-gfm
Syntax highlightingrehype-highlight + highlight.js
FontsPlus Jakarta Sans + Lora (Google Fonts)

Design decisions

Why no backend? Zero friction. To publish a post, I write a Markdown file and push to GitHub. The site is statically deployable to Netlify or GitHub Pages.

Why serif for body text? Blog posts are meant to be read at length. Studies consistently show that serif typefaces improve readability for long-form content. Lora is well-optimised for screens.

Why black and white? Color is a distraction when you're trying to read. The constraint forces hierarchy to come from typography and spacing, not color accents.

Future plans

  • RSS feed generation
  • Open Graph images for social sharing
  • Reading time estimate on blog posts
  • Tag filtering on blog list page