My personal website: a single-page profile (about, timeline, projects, publications) plus project detail pages and an Impressum page.
- Frontend: React + Vite
- Routing: React Router (home page plus two sub-page routes)
- Styling: hand-written CSS (
src/styles.css). Light or dark, following the reader's system setting; no web fonts, no CSS framework, no scroll animations. A single 860px column set in a serif (Charter, falling back to Georgia), with the plain-document structure of karpathy.ai: head, timeline, publications, projects. - Icons:
react-icons - Content:
src/data/timeline.jsx(career timeline) andsrc/data/projects.js(projects and papers) drive the home page.
src/main.jsxrenders<App />;src/App.jsxdefines the routes and wraps them insrc/components/Layout.jsx.src/components/Layout.jsxis only the shared footer plus an<Outlet />; there is no navigation bar. Sub-pages carry their own "back" link.src/pages/Home.jsxrenders the whole home document: head (photo, name, social icons), the timeline, projects, publications./projectsand/resumeredirect to/, since both now live on the home page.
- Timeline (
src/data/timeline.jsx): each entry has ayear(the large numeral), an optionaluntillabel under it, an optionallogo, and abodywritten as JSX so it can contain links. Adding an organisation logo takes a few steps beyond dropping a file insrc/assets/logos/; they are listed at the top ofsrc/data/timeline.jsx, next to the entries themselves. Every tile is the same square whatever shape the mark is, and rows have a fixed height so the gaps between logos stay identical. Both come from the tokens at the top ofsrc/styles.css(--logo-box,--logo-gutter); an entry whose text grows past that height falls out of the rhythm on its own. - Projects (
src/data/projects.js):type: 'software'entries render in the projects section,type: 'paper'entries in publications (papers also carry avenue).linkis the repo, store or PDF the entry points at, and it appears only on the detail page at/projects/<slug>, not in the home page preview.bodyis the text of that page.
index.html: HTML shell (mounts#root)src/main.jsx: React entry point (renders<App />and imports global styles)src/App.jsx: route table (/,/projects/:slug,/impressum)src/components/Layout.jsx: the page container, shared footer and<Outlet />src/components/BackLink.jsx: the way back to the home page from a sub pagesrc/components/ExternalLink.jsx: outward links, opened in a new tabsrc/components/ScrollToTop.jsx: resets scroll on navigation, honours anchorssrc/hooks/useDocumentTitle.js: sets the tab titlesrc/pages/*: page componentssrc/data/*: timeline and project contentsrc/assets/*andpublic/*: images and static assets (e.g.favicon.ico)
This repo also keeps the hosting setup I use for the site:
Dockerfile: builds the Vite app and serves it via Vite's preview serverdocker-compose.yml: wires the app container to Caddy (plus Watchtower)Caddyfile: reverse-proxy + compression + a small set of security headers