/Lab
HomeLab

Lab

This site is built like documentation on purpose. It is a place to share what I have learned, step by step, so students can follow the path instead of just looking at the result. This page explains how it works: the idea, the tools, the code and the design.

How this site worksUpdated Oct 2026
36pages, all pre-rendered
~103 kBshared JavaScript
0databases or CMS
1 dayfrom idea to live site

Why a docs site

Most portfolios are a list of wins. That is useful for recruiters, but not for a student who wants to know how to get there. Documentation has a different job: it explains, in order, so someone else can repeat it.

  • Logs read like a changelog of a career: where I studied, worked and what each step taught me.
  • Projects read like case studies: where the idea came from, what broke, what it became.
  • Every page has the same shape (lead, numbers, sections, “On this page”), so it is easy to skim and easy to come back to.
  • The look follows Vercel’s docs: quiet, black and white, with structure doing the work instead of decoration.

The goal is not to look impressive. The goal is that a student finishes a page and thinks: I could do the next step too.

Tech stack

Next.jsFramework
ReactUI
TypeScriptLanguage
CSSStyling
VercelHosting
PythonLogo processing
Claude CodeAI pair programmer
OrcaAI coding workspace
LayerToolWhy
FrameworkNext.js 15.5 (App Router)File-based routes, static generation, image and font optimization out of the box.
UIReact 19Server components by default; only interactive parts ship JavaScript.
LanguageTypeScript 5.9All content is typed, so a missing field is a build error, not a broken page.
StylingPlain CSS with design tokensOne globals.css with CSS variables. No Tailwind, no CSS-in-JS: small, readable, easy to theme.
FontsGeist Sans, Geist Mono, IBM Plex Sans ThaiLoaded with next/font, self-hosted, no layout shift. Thai falls back to Plex automatically.
Themenext-themes 0.4Light and dark mode with no flash on load; preference saved per visitor.
BookingCustom picker (+ optional Cal.com embed)Works with zero accounts today; switches to Cal.com with one environment variable.
ImagesPython + PillowTurns logos and my handwriting into transparent masks that follow the theme.
AIClaude Code in OrcaMy pair programmer: wrote the code, checked pages in a browser and deployed.
HostingVercelEvery deploy is a static build on a global CDN at natch-soros.vercel.app.

There is no database, CMS or backend. Every page is generated at build time from TypeScript files, which keeps the site fast, free to host and impossible to break with a bad login.

How the code is organized

app/
  page.tsx               home
  about/page.tsx         about me and the dream
  logs/                  career docs (overview + [slug])
  projects/              project docs (overview + [slug])
  talk/page.tsx          booking page
  lab/page.tsx           this page
  globals.css            design tokens and every style
components/
  header.tsx             nav, mega menu, mobile drawer
  sidebar.tsx            docs sidebar with Ctrl K filter
  toc.tsx                "On this page" with scroll spy
  docs.tsx               renders entries from content blocks
  career-path.tsx        Education / Venture / Tech tracks
  booker.tsx             calendar, slots, invite links
  logos.tsx              black and white logo strips
lib/
  site.ts                name, email, booking hours
  content/
    logs.ts  projects.ts  career.ts  orgs.ts  lab.ts

Content and layout are separate. A log or project is plain data: a title, a lead, some numbers and a list of sections. Each section is made of small blocks.

type Block =
  | string                                   // paragraph
  | { type: "list"; items: string[] }
  | { type: "steps"; items: { title; text }[] }   // timeline
  | { type: "roles"; items: { title; period; points }[] }
  | { type: "callout"; tone?: "note" | "accent"; text }
  | { type: "table"; head: string[]; rows: string[][] }
  | { type: "quote"; text }
  | { type: "code"; text; lang? };

To add a project, I add one object to projects.ts. The sidebar, mega menu, overview cards, timeline, prev/next links and the static page are all generated from it.

Design system

Everything is driven by a small set of CSS variables. Dark mode is the same variables with different values.

TokenLightDarkUsed for
--bg#ffffff#000000Page background
--fg#171717#edededMain text
--muted#666666#a1a1a1Secondary text
--border#ebebeb#1f1f1fLines, cards, grids
--accent#ff4d00#ff5a14Current items, dots, calendar
  • Accent color: the orange from my handwritten logo, used only for “now”: current roles, available days, the active section.
  • Type: Geist for Latin, tight letter-spacing on headings, mono for dates and labels.
  • Layout: a three-column docs grid (260px sidebar, 760px reading column, 220px table of contents) that collapses to one column on phones.
  • Lines instead of boxes: timelines, hairline borders and grid cells carry the structure, like Vercel’s docs.
  1. Handwritten logo → theme-aware mark

    The logo is a hand-drawn PNG. A short Python (Pillow) script turns the ink into an alpha mask. CSS paints it with currentColor through mask-image, so the same file is black in light mode and white in dark mode.

  2. Partner logos → one monochrome wall

    Every organization logo goes through the same pipeline: remove the background, keep only the shape as a mask, then render it in the theme color. Nearly thirty logos in different colors become one calm grid.

  3. The glow

    The hero is two radial gradients and a CSS drop-shadow on the masked logo, a nod to the glowing triangle on vercel.com.

Features worth explaining

Booking without a backend

  • Weekly hours, closed days and date overrides live in lib/site.ts.
  • Slots are calculated in Bangkok time and shown in the visitor’s own time zone with Intl.DateTimeFormat.
  • Confirming creates a Google Calendar invite with me as a guest, so the booking reaches my calendar without any server.
  • Setting NEXT_PUBLIC_CAL_LINK swaps the picker for a Cal.com embed with real availability and Meet links.

Email that always works

  • mailto: does nothing on computers without a mail app, so every email button copies the address (or a ready-made message) and offers “Open mail app” as a second option.

Docs navigation

  • Mega menu generated from the content categories.
  • Sidebar filter with Ctrl K.
  • “On this page” highlights the section you are reading as you scroll.

Career path in three tracks

  • Education, Venture and Tech, each oldest to newest, so the growth is readable one thread at a time.