Personal site of Michael Schultz — portfolio, writing, projects, a live /listening page backed by Last.fm, and a Bluesky-powered status line on the homepage.
Built with SvelteKit, Tailwind CSS, and mdsvex for markdown posts. Most pages are prerendered; /listening and /api/status are server-rendered at request time.
Requires Node.js 24.x (see .nvmrc).
pnpm install
pnpm devOpen http://localhost:5173.
Search uses Pagefind and is only available after a production build:
pnpm build
pnpm startType-checking:
pnpm checkCopy .env.example to .env for local development:
| Variable | Purpose |
|---|---|
LASTFM_API_KEY |
Last.fm API key for /listening |
LASTFM_USER |
Last.fm username (default: michaelschultz) |
DATABASE_PATH |
SQLite path (default: ./data/listening.db) |
CRON_SECRET |
Optional bearer token for GET /api/cron/sync-listening |
BLUESKY_APP_PASSWORD |
Bluesky app password for pnpm status (optional) |
BLUESKY_HANDLE |
Bluesky handle for pnpm status (default: michaelschultz.com) |
The listening page syncs recent plays from Last.fm into SQLite on a schedule and when the cache is stale. An in-process cron job handles most updates; CRON_SECRET is only needed if you want to trigger syncs over HTTP.
Manual sync while the dev server is running:
pnpm sync:listeningThe homepage reads a short status sentence from a Bluesky record (com.michaelschultz.status/self) via /api/status. Publish updates locally:
pnpm status "Shipping something new"Create an app password in Bluesky settings. The lexicon schema lives in lexicons/com.michaelschultz.status.json.
cp .env.example .env
# edit .env
docker compose up -d --buildThe container serves the app on port 3000. Attach your own reverse proxy for TLS and public routing. Listening data is stored in the listening-data Docker volume.
Production configuration for this site is managed outside the repo (GitHub Environment secrets and deploy automation). Do not commit .env files.
src/routes/— pages and API routessrc/content/thoughts/— blog posts (.svx)src/lib/content/— work, games, and post metadatasrc/lib/listening/— Last.fm sync and SQLite cachesrc/lib/bluesky/— Bluesky status fetch + cachedeploy/— deployment scripts
