← Back to Home

Portfolio Projects

Lean static portfolio with interactive diagrams and self-hosted analytics

Lean static portfolio with interactive diagrams and self-hosted analytics

#portfolio#web

// Overview

This site: a statically exported Next.js portfolio with interactive architecture diagrams, served by nginx behind Caddy on a single small VPS, with privacy-friendly self-hosted GoatCounter analytics.

// Background

The challenge

Past projects exist — but there's nowhere to show them.

A GitHub link isn't a portfolio; a PDF isn't a demo.

01

No centralized showcase

Work lived across GitHub repos, local drives, old Notion

docs, and expired demo links — never in one place.

Interviewers get a repo list, not a story

02

Code repos don't communicate value

A README explains what the code does. It doesn't explain

the problem it solved, the tradeoffs made, or the impact.

Context lives in your head, not on the screen

03

No live proof of technical depth

Architecture diagrams in slides go stale. Without a running

app + interactive diagrams, depth stays invisible.

Claims without evidence aren't convincing

04

No indexed, findable web presence

GitHub profiles rank poorly for recruiters searching specific

skills. A personal domain with structured content does.

Good work that can't be found doesn't get you hired

05

Static platforms age out of date

A PDF or static site can't be updated without a rebuild.

New projects, new context, new skills — always out of sync.

Portfolio reflects who you were, not who you are

Net effect

Strong past work with nowhere to point — the depth of each

project invisible until you explain it live in an interview.

// Solution

Full-stack portfolio — Next.js App Router + PostgreSQL + MinIO

Data sources

PostgreSQL

porto_projects table

auto-migrated on boot

MinIO Object Store

S3-compatible bucket

images · diagrams · demos

Pipeline

Request

nginx → /porto/

/porto/api/

Request

Auth

jose JWT verify

career-ops token

Auth

Data

pg query

MinIO presign

Data

Render

Next.js SSR

App Router

Render

Serve

HTML + JSON

ISR-cached

Serve

Next.js static export · nginx · Caddy auto-TLS · GoatCounter (SQLite) · GitHub Actions deploy · Docker Compose

// Impact

Content lifecycle — before/after

Before

edit → commit → build → deploy (minutes)

After

edit in /manage → save → live

0

rebuilds to update

a project description

Time from edit to live< 1 sec
Auth surfaceverified JWT only

Feature matrix

Live project data

PostgreSQL CRUD via API routes

Admin CMS

/manage: JWT auth, CRUD + upload

Media CDN path

MinIO presigned · no binaries in git

Shared auth

jose JWT, shared career-ops token

Server-rendered

RSC data fetch, cached + tag-revalidated

SSR + ISR

App Router SSR + stale-revalidate

Stack metrics

API routes

8

Languages

2

DB tables

1

Runtime

Bun

StackNext.js 15 + TypeScript
Storagepg + MinIO + JWT

Full-stack: API + SSR + auth,

one Next.js app, deployed via Docker.

// Tech Stack

LayerTechnologies
FrontendNext.js 16 static export, React 19, TypeScript, Tailwind
Servingnginx, Caddy (auto-TLS)
AnalyticsGoatCounter (SQLite, self-hosted)
DeliveryGitHub Actions, rsync, Docker Compose

// Architecture & Diagrams

No architecture diagrams configured yet.

Disclaimer: sample visuals may contain anonymized, simulated, or non-production values for presentation purposes.

// Demo

No demo configured yet.