My personal portfolio website — a landing page with project and work-experience sections, theming (light/dark), and SEO.
- Nuxt 4 (Vue 3, Nitro server)
- @nuxt/content v3 — Markdown content, backed by SQLite (
better-sqlite3) - Tailwind CSS v4 via
@tailwindcss/vite - @nuxt/image, @nuxt/fonts
- @nuxtjs/seo (sitemap, robots, OG image, schema.org)
- @nuxtjs/color-mode for theming
- @vercel/analytics for pageview/traffic analytics
- Package manager: pnpm (pinned via
packageManagerinpackage.json)
Install dependencies:
pnpm installStart the dev server on http://localhost:3000:
pnpm devpnpm build # build the Nitro server output into .output/
pnpm preview # locally preview the production buildThe server entry point is .output/server/index.mjs. It listens on HOST/PORT
(defaults 0.0.0.0:3000, or whatever you set via env).
The included Dockerfile is a multi-stage build (Alpine):
docker build -t personal-website .
docker run -p 3002:3002 personal-websiteThe container serves on port 3002 (PORT/HOST are set as ENV; override at
runtime if your platform injects its own $PORT).
@nuxt/content v3 uses better-sqlite3, a native C++ addon, to serve content
from a SQLite database. This affects the Docker build in two ways:
- Build stage needs
python3 make g++to compilebetter-sqlite3(no musl prebuilt binary ships for Alpine). - Runtime stage needs
libstdc++installed — the compiled addon links against it at load time. The basenode:alpineimage does not include it, so withoutapk add libstdc++the server crashes on startup withError loading shared library libstdc++.so.6, and the container never comes up (a fronting proxy will show a generic 500 / "temporarily unavailable").
Both are already handled in the Dockerfile — keep them if you edit it.
This repo is linked to the murphy-site project (zenith-codes-projects team),
framework preset Nuxt.js. Nitro auto-detects the vercel build preset from
the VERCEL env var Vercel sets during builds — no nitro.preset override is
needed in nuxt.config.ts (that would break the Docker build, which doesn't set
that env var).
Set these in the project's Environment Variables (see .env.example for the
full list):
NUXT_PUBLIC_POCKETBASE_URL— required; the app throws on boot without it.REDIS_URL— provisioned automatically by the Vercel Marketplace Upstash integration (rediss://…, TLS implied by the scheme). The docker-compose Redis (dragonflydb) instead uses discreteREDIS_HOST/REDIS_PORT/REDIS_PASSWORD(+REDIS_TLS=trueif the provider needs it) — seeserver/utils/redis.ts. Rate limiting is skipped (fails open) if neither is set.
Analytics is @vercel/analytics, enabled
automatically via the @vercel/analytics/nuxt module — no env vars needed
(zero-config on Vercel).
Deploy with vercel deploy (preview) or vercel deploy --prod.
This repo uses semantic-release with
Conventional Commits. Versioning and CHANGELOG.md are generated automatically
from commit messages in CI.