chore: bootstrap repo with PRD, tasks, design samples, and Mosaic scaffolding

Personal professional website for jasonwoltje.com, built on Payload CMS 3 +
Next.js 16 and deployed to w-docker0 (Docker Swarm) behind the existing
MosaicStack edge Traefik. Establishes the delivery contract before any
scaffold work begins:

- docs/PRD.md — stack, content model, routing, design system, CI, infra,
  acceptance criteria, assumptions, and escalation log
- docs/TASKS.md — milestone breakdown 0.0.1 → 0.1.0 MVP
- README.md, LICENSE (All Rights Reserved), .gitignore
- design-samples/ — stitch "Technical Editorial" mockups + DESIGN.md tokens
- images/ — source headshots (to be imported into Payload media on seed)
- .mosaic/ — orchestrator scaffolding (quality rails, repo hooks)

Scaffold (Next.js + Payload init) ships on feat/scaffold in a follow-up PR.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-13 21:05:06 -05:00
commit c800bef739
21 changed files with 1851 additions and 0 deletions

61
.gitignore vendored Normal file
View File

@@ -0,0 +1,61 @@
# dependencies
node_modules/
.pnpm-store/
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
# build output
.next/
out/
dist/
build/
*.tsbuildinfo
# env / secrets
.env
.env.*
!.env.example
*.pem
# runtime / logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
logs/
*.log
# OS / editor
.DS_Store
Thumbs.db
.vscode/
!.vscode/extensions.json
!.vscode/settings.json
.idea/
# testing
coverage/
.nyc_output/
playwright-report/
test-results/
# payload
media/
!design-samples/
!images/
# mosaic workspace state (runtime — committed scaffolds start empty)
.mosaic/orchestrator/state.json
.mosaic/orchestrator/matrix_state.json
.mosaic/orchestrator/tasks.json
.mosaic/orchestrator/state/
.mosaic/orchestrator/logs/
scripts/local/
# design samples zip (HTML + DESIGN.md kept as reference)
design-samples/*.zip

78
.mosaic/README.md Normal file
View File

@@ -0,0 +1,78 @@
# Repo Mosaic Linkage
This repository is attached to the machine-wide Mosaic framework.
## Load Order for Agents
1. `~/.config/mosaic/STANDARDS.md`
2. `AGENTS.md` (this repository)
3. `.mosaic/repo-hooks.sh` (repo-specific automation hooks)
## Purpose
- Keep universal standards in `~/.config/mosaic`
- Keep repo-specific behavior in this repo
- Avoid copying large runtime configs into each project
## Optional Quality Rails
Use `.mosaic/quality-rails.yml` to track whether quality rails are enabled for this repo.
Apply a template:
```bash
~/.config/mosaic/bin/mosaic-quality-apply --template <template> --target .
```
Verify enforcement:
```bash
~/.config/mosaic/bin/mosaic-quality-verify --target .
```
## Optional Matrix Orchestrator Rail
Repo-local orchestrator state lives in `.mosaic/orchestrator/`.
Run one cycle:
```bash
~/.config/mosaic/bin/mosaic-orchestrator-matrix-cycle
~/.config/mosaic/bin/mosaic-orchestrator-run --once
```
Run continuously:
```bash
~/.config/mosaic/bin/mosaic-orchestrator-run --poll-sec 10
```
Bridge events to Matrix:
```bash
~/.config/mosaic/bin/mosaic-orchestrator-matrix-publish
~/.config/mosaic/bin/mosaic-orchestrator-matrix-consume
```
Run until queue is drained (syncs from `docs/tasks.md` first):
```bash
~/.config/mosaic/bin/mosaic-orchestrator-drain
```
Set worker command if auto-detect does not match your CLI:
```bash
export MOSAIC_WORKER_EXEC="codex -p"
# or
export MOSAIC_WORKER_EXEC="opencode -p"
```
Use repo helper (foreground or detached):
```bash
bash scripts/agent/orchestrator-daemon.sh drain
bash scripts/agent/orchestrator-daemon.sh start
bash scripts/agent/orchestrator-daemon.sh status
bash scripts/agent/orchestrator-daemon.sh stop
```

View File

@@ -0,0 +1,18 @@
{
"enabled": false,
"transport": "matrix",
"matrix": {
"control_room_id": "",
"workspace_id": "",
"homeserver_url": "",
"access_token": "",
"bot_user_id": ""
},
"worker": {
"runtime": "codex",
"command_template": "bash scripts/agent/orchestrator-worker.sh {task_file}",
"timeout_seconds": 7200,
"max_attempts": 1
},
"quality_gates": ["pnpm lint", "pnpm typecheck", "pnpm test"]
}

10
.mosaic/quality-rails.yml Normal file
View File

@@ -0,0 +1,10 @@
enabled: false
template: ''
# Set enabled: true and choose one template:
# - typescript-node
# - typescript-nextjs
# - monorepo
#
# Apply manually:
# ~/.mosaic/bin/mosaic-quality-apply --template <template> --target <repo>

17
.mosaic/repo-hooks.sh Executable file
View File

@@ -0,0 +1,17 @@
#!/usr/bin/env bash
# Optional repo-specific hooks used by scripts/agent/*.sh
# Called by session-start.sh
# mosaic_hook_session_start() {
# echo "Run repo-specific startup checks"
# }
# Called by critical.sh
# mosaic_hook_critical() {
# echo "Run repo-specific critical queries"
# }
# Called by session-end.sh
# mosaic_hook_session_end() {
# echo "Run repo-specific end-of-session checks"
# }

8
LICENSE Normal file
View File

@@ -0,0 +1,8 @@
Copyright (c) 2026 Jason Woltje. All rights reserved.
The source code in this repository is the personal brand property of
Jason Woltje. No license is granted for reuse, redistribution, or
derivative works without explicit written permission from the copyright
holder.
Third-party dependencies retain their original licenses.

60
README.md Normal file
View File

@@ -0,0 +1,60 @@
# jasonwoltje.com — Professional Website
Personal brand + portfolio site for Jason Woltje. Payload CMS 3 on Next.js 16, Postgres 17, deployed to Docker Swarm (`w-docker0`) behind Traefik.
## Stack
| Layer | Choice |
|---|---|
| Framework | Next.js 16 (App Router) |
| CMS | Payload 3 (Next-integrated, admin at `/admin`) |
| DB | PostgreSQL 17 |
| Styling | Tailwind v3 (ported from stitch design tokens) |
| Fonts | Space Grotesk (display/labels) + Inter (body), self-hosted via `next/font` |
| Media | Local volume (migratable to S3/MinIO via Payload adapter) |
| Analytics | Umami (self-hosted) |
| CAPTCHA | Cloudflare Turnstile |
| Registry | `git.mosaicstack.dev` container packages (immutable `sha-*` tags) |
| CI | Woodpecker CI + Kaniko |
| Deploy | Portainer stack on `w-docker0` (Swarm) |
| Ingress | Edge Traefik (TLS) → per-swarm Traefik (`entrypoints=web`) |
## Repository layout
```
professional-website/
├── src/ # Next.js app + Payload config
├── public/ # static assets
├── design-samples/ # stitch design reference (HTML + DESIGN.md)
├── images/ # source headshots (pre-upload originals)
├── docs/
│ ├── PRD.md # product requirements
│ ├── TASKS.md # execution tracking
│ └── scratchpads/ # per-task working notes
├── Dockerfile # multi-stage build
├── docker-compose.swarm.yml # Portainer stack (prod)
├── .woodpecker/web.yml # CI pipeline
└── .env.example
```
## Local dev
```bash
pnpm install
cp .env.example .env # fill in local values
pnpm dev # Next + Payload on http://localhost:3000
```
Payload admin: http://localhost:3000/admin
## Documentation
- [`docs/PRD.md`](docs/PRD.md) — product requirements, scope, architecture decisions
- [`docs/TASKS.md`](docs/TASKS.md) — milestone + task tracking
- [`design-samples/stitch_jasonwoltje.com/silicon_ethos/DESIGN.md`](design-samples/stitch_jasonwoltje.com/silicon_ethos/DESIGN.md) — design system reference
## Deployment
Container images are built by Woodpecker and pushed to `git.mosaicstack.dev/jason.woltje/professional-website:sha-<short>`. The Portainer stack references immutable tags — `latest` is never used as a deploy reference.
See `docs/PRD.md` §Infrastructure for the full deploy runbook.

View File

@@ -0,0 +1,326 @@
<!DOCTYPE html>
<html class="dark" lang="en"><head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&amp;family=Inter:wght@300;400;500;600;700&amp;family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&amp;display=swap" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&amp;display=swap" rel="stylesheet"/>
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
<script id="tailwind-config">
tailwind.config = {
darkMode: "class",
theme: {
extend: {
colors: {
"primary": "#81ecff",
"secondary-container": "#9900ce",
"on-surface": "#f7f5fc",
"on-secondary": "#39004f",
"inverse-primary": "#006976",
"surface": "#0d0e12",
"on-secondary-container": "#fff5fc",
"error-dim": "#d7383b",
"inverse-surface": "#faf8ff",
"secondary-fixed-dim": "#ebadff",
"surface-container-lowest": "#000000",
"on-error": "#490006",
"surface-variant": "#24252c",
"tertiary-dim": "#2be800",
"surface-container-high": "#1e1f25",
"on-primary-fixed": "#003840",
"error-container": "#9f0519",
"background": "#0d0e12",
"primary-fixed-dim": "#00d4ec",
"tertiary-fixed": "#2ff801",
"on-background": "#f7f5fc",
"primary-dim": "#00d4ec",
"inverse-on-surface": "#54555a",
"primary-container": "#00e3fd",
"surface-dim": "#0d0e12",
"outline-variant": "#47484d",
"tertiary-fixed-dim": "#2be800",
"on-error-container": "#ffa8a3",
"on-tertiary-fixed": "#064200",
"on-secondary-fixed-variant": "#8400b2",
"surface-container-highest": "#24252c",
"on-tertiary-fixed-variant": "#0d6200",
"secondary": "#d873ff",
"on-tertiary": "#0d6100",
"surface-container": "#18191e",
"secondary-fixed": "#f1c1ff",
"outline": "#75757a",
"on-primary-container": "#004d57",
"on-tertiary-container": "#0b5800",
"tertiary": "#8eff71",
"primary-fixed": "#00e3fd",
"error": "#ff716c",
"on-surface-variant": "#abaab0",
"on-primary-fixed-variant": "#005762",
"on-primary": "#005762",
"surface-tint": "#81ecff",
"secondary-dim": "#bc00fb",
"surface-bright": "#2a2c32",
"surface-container-low": "#121318",
"on-secondary-fixed": "#580078",
"tertiary-container": "#2ff801"
},
borderRadius: {
"DEFAULT": "0.125rem",
"lg": "0.25rem",
"xl": "0.5rem",
"full": "0.75rem"
},
fontFamily: {
"headline": ["Space Grotesk"],
"body": ["Inter"],
"label": ["Space Grotesk"]
}
},
},
}
</script>
<style>
.material-symbols-outlined {
font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
}
.grid-pattern {
background-image: radial-gradient(rgba(129, 236, 255, 0.15) 1px, transparent 1px);
background-size: 24px 24px;
}
.glass-panel {
backdrop-filter: blur(24px);
}
</style>
</head>
<body class="bg-background text-on-background font-body selection:bg-primary selection:text-on-primary">
<!-- TopNavBar -->
<nav class="bg-[#0d0e12]/80 backdrop-blur-xl docked full-width top-0 sticky z-50 bg-gradient-to-b from-[#0d0e12] to-transparent">
<div class="flex justify-between items-center max-w-7xl mx-auto px-6 py-4">
<span class="text-xl font-bold tracking-widest text-[#81ecff] font-['Space_Grotesk'] uppercase tracking-tighter">JASON WOLTJE</span>
<div class="hidden md:flex items-center space-gap-8 gap-8 font-['Space_Grotesk'] uppercase tracking-tighter text-sm">
<a class="text-slate-400 hover:text-[#81ecff] transition-colors hover:opacity-80 transition-all duration-300 scale-95 active:scale-90 transition-transform" href="#">Home</a>
<a class="text-slate-400 hover:text-[#81ecff] transition-colors hover:opacity-80 transition-all duration-300 scale-95 active:scale-90 transition-transform" href="#">Projects</a>
<a class="text-[#81ecff] border-b-2 border-[#81ecff] pb-1 hover:opacity-80 transition-all duration-300 scale-95 active:scale-90 transition-transform" href="#">About</a>
<a class="text-slate-400 hover:text-[#81ecff] transition-colors hover:opacity-80 transition-all duration-300 scale-95 active:scale-90 transition-transform" href="#">Contact</a>
</div>
<div class="flex items-center gap-4">
<button class="material-symbols-outlined text-[#81ecff] hover:opacity-80 transition-all duration-300 scale-95 active:scale-90 transition-transform">dark_mode</button>
</div>
</div>
</nav>
<main class="max-w-7xl mx-auto px-6 space-y-32 py-20">
<!-- Status Terminal Indicator -->
<div class="flex items-center gap-3">
<div class="h-2 w-2 bg-tertiary rounded-full animate-pulse"></div>
<span class="font-label text-xs text-tertiary tracking-[0.2em] uppercase">SYSTEM STATUS: OPERATIONAL // LOC: 42.3601° N, 71.0589° W</span>
</div>
<!-- Hero: The Narrative Bio -->
<section class="grid grid-cols-1 lg:grid-cols-12 gap-12 items-start">
<div class="lg:col-span-7 space-y-8">
<div class="space-y-4">
<span class="font-label text-xs text-primary uppercase tracking-widest">01 // THE ARCHITECT</span>
<h1 class="text-6xl md:text-8xl font-headline font-bold leading-tight tracking-tighter">
ENGINEERING <br/>
<span class="text-transparent bg-clip-text bg-gradient-to-r from-primary to-secondary">LEADERSHIP.</span>
</h1>
</div>
<div class="space-y-6 text-lg text-on-surface-variant max-w-2xl leading-relaxed">
<p>
I bridge the gap between high-level executive strategy and the gritty reality of technical implementation. My career has been defined by a refusal to let "good enough" stand in the way of architectural excellence.
</p>
<p>
From scaling distributed systems to mentoring the next generation of staff engineers, I approach leadership as an engineering problem: optimize for flow, minimize friction, and ensure the foundation is robust enough to support infinite growth.
</p>
</div>
<div class="flex flex-wrap gap-4 pt-4">
<div class="px-4 py-2 bg-surface-container-highest border border-outline-variant/20 rounded-lg">
<span class="font-label text-[10px] text-secondary uppercase block mb-1">Expertise</span>
<span class="text-sm font-medium">System Design</span>
</div>
<div class="px-4 py-2 bg-surface-container-highest border border-outline-variant/20 rounded-lg">
<span class="font-label text-[10px] text-tertiary uppercase block mb-1">Philosophy</span>
<span class="text-sm font-medium">Radical Candor</span>
</div>
<div class="px-4 py-2 bg-surface-container-highest border border-outline-variant/20 rounded-lg">
<span class="font-label text-[10px] text-primary uppercase block mb-1">Focus</span>
<span class="text-sm font-medium">Platform Scaling</span>
</div>
</div>
</div>
<div class="lg:col-span-5 relative group">
<div class="absolute inset-0 bg-primary/20 blur-[80px] -z-10 opacity-30 group-hover:opacity-50 transition-opacity"></div>
<div class="aspect-square bg-surface-container border border-outline-variant/15 overflow-hidden rounded-xl relative">
<div class="absolute inset-0 grid-pattern opacity-40"></div>
<img alt="Jason Woltje" class="w-full h-full object-cover mix-blend-luminosity hover:mix-blend-normal transition-all duration-500" data-alt="Close up professional portrait of a tech leader with a thoughtful expression, warm studio lighting, modern minimalist background" src="https://lh3.googleusercontent.com/aida-public/AB6AXuBVEfC8hu53QsJGRrPNtChmaW12cFhhoV3w6ZGY5wNTNfTVLGXHvFfKpY16sItN9d9Zq_x7K0I0gzO6_w1qgGHJqYNeolpGT2NJLTdydyU9NFYIfkhxSydvdhylre06gNvEjvqpA4hg2tXQwOw7g97uhqnKU6LK_ytvuLJVdcuD33zGgJB6ZUTVKjxiJ0d_Urz4EOkSV26eJFvj2LTUlx7e5rly0o451mdjAgGfCbvaXhrVonp6rIqB61xdhIy_bRQocPr7iXhQlGs"/>
<div class="absolute bottom-4 right-4 bg-surface/80 backdrop-blur-md p-3 border border-outline-variant/20 rounded-lg">
<span class="font-label text-[10px] text-on-surface-variant block">TIMESTAMP</span>
<span class="font-headline font-bold text-primary">MARCH 2024</span>
</div>
</div>
</div>
</section>
<!-- Technical Deep-Dive: The Geek Side -->
<section class="space-y-12">
<div class="flex flex-col md:flex-row md:items-end justify-between gap-6">
<div class="space-y-4">
<span class="font-label text-xs text-secondary uppercase tracking-widest">02 // THE GEEK SIDE</span>
<h2 class="text-4xl md:text-5xl font-headline font-bold">HOME LAB &amp; TECH STACK.</h2>
</div>
<p class="text-on-surface-variant max-w-sm font-label text-sm uppercase leading-relaxed">
Analyzing the infrastructure that powers my personal experimentation.
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<!-- Stack Card -->
<div class="md:col-span-2 bg-surface-container-low rounded-xl p-8 border border-outline-variant/10 relative overflow-hidden group">
<div class="absolute top-0 right-0 p-8 opacity-5 group-hover:opacity-10 transition-opacity">
<span class="material-symbols-outlined text-[120px]">terminal</span>
</div>
<div class="relative z-10 space-y-8">
<div class="flex items-center gap-4">
<span class="h-px w-12 bg-primary"></span>
<h3 class="font-headline font-bold text-xl uppercase tracking-wider">Primary Stack</h3>
</div>
<div class="grid grid-cols-2 md:grid-cols-4 gap-6">
<div class="space-y-2">
<span class="font-label text-[10px] text-primary/60">LANGUAGE</span>
<p class="font-medium">TypeScript / Go</p>
</div>
<div class="space-y-2">
<span class="font-label text-[10px] text-secondary/60">FRONTEND</span>
<p class="font-medium">Next.js / Tailwind</p>
</div>
<div class="space-y-2">
<span class="font-label text-[10px] text-tertiary/60">DATABASE</span>
<p class="font-medium">PostgreSQL / Redis</p>
</div>
<div class="space-y-2">
<span class="font-label text-[10px] text-on-surface-variant">INFRA</span>
<p class="font-medium">K8s / Terraform</p>
</div>
</div>
<div class="pt-6 border-t border-outline-variant/10">
<div class="flex items-center gap-2 mb-4">
<span class="material-symbols-outlined text-sm text-tertiary">memory</span>
<span class="font-label text-xs text-on-surface-variant uppercase tracking-tighter">Current Build: Homelab V3.4</span>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div class="bg-surface-container-highest p-4 rounded-lg flex items-center gap-4">
<span class="material-symbols-outlined text-primary">dns</span>
<div>
<p class="text-sm font-medium">Proxmox Cluster</p>
<p class="text-[10px] font-label text-on-surface-variant uppercase">3x Micro Nodes</p>
</div>
</div>
<div class="bg-surface-container-highest p-4 rounded-lg flex items-center gap-4">
<span class="material-symbols-outlined text-secondary">storage</span>
<div>
<p class="text-sm font-medium">TrueNAS Scale</p>
<p class="text-[10px] font-label text-on-surface-variant uppercase">48TB ZFS Pool</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Maker Logic Card -->
<div class="bg-surface-container-highest rounded-xl p-8 border border-primary/20 relative overflow-hidden flex flex-col justify-between">
<div class="absolute inset-0 grid-pattern opacity-10"></div>
<div class="relative z-10 space-y-6">
<span class="material-symbols-outlined text-3xl text-primary">construction</span>
<h3 class="font-headline font-bold text-2xl">THE MAKER <br/>MINDSET.</h3>
<p class="text-sm text-on-surface-variant leading-relaxed">
Beyond code, I build mechanical keyboards, restore vintage audio gear, and obsess over home automation logic. If it has a circuit board, I've likely tried to optimize it.
</p>
</div>
<div class="relative z-10 pt-8">
<button class="w-full py-3 bg-primary text-on-primary font-label text-xs uppercase tracking-[0.2em] rounded-lg hover:bg-primary/90 transition-colors">
View Workbench
</button>
</div>
</div>
</div>
</section>
<!-- Soundtrack: The Audio Interface -->
<section class="space-y-12">
<div class="flex flex-col md:flex-row md:items-end justify-between gap-6">
<div class="space-y-4">
<span class="font-label text-xs text-tertiary uppercase tracking-widest">03 // SOUNDTRACK</span>
<h2 class="text-4xl md:text-5xl font-headline font-bold">AUDIO SIGNAL PATH.</h2>
</div>
</div>
<div class="grid grid-cols-1 lg:grid-cols-4 gap-8">
<!-- Music Player Mock -->
<div class="lg:col-span-3 bg-surface-container rounded-xl overflow-hidden border border-outline-variant/10 flex flex-col md:flex-row">
<div class="md:w-1/3 aspect-square relative overflow-hidden">
<img alt="Album Art" class="w-full h-full object-cover" data-alt="Cinematic moody abstract art with deep purples and blues, reminiscent of a modern synth-wave or techno album cover" src="https://lh3.googleusercontent.com/aida-public/AB6AXuBQuxLpB2MoIFqVbz9hhflkisIf05QTFsF5tyVrPKXuQOPjhgZdUQsaAC-mY9IntYA7nnVeTQ4wSRPc4PxVHf1eIAHJzk9w9xg3CZINS2y_RK2ESfj53GJdjfEPfVidpT86id4N0HvhR4R8QHImR8OEfOVKAsRqHe9spBuLuB-a39keaKc7tdcnxZEXZObcbq0NYdpYcelWlLTesIxn1nqzS1OdNGb_1LfnCiuiDQiWPaQOAw4O6QXjq0fWJsMibshOKQqVfYxC-Gg"/>
<div class="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent"></div>
<div class="absolute bottom-4 left-4">
<p class="text-xs font-label text-secondary uppercase">Now Playing</p>
<p class="font-headline font-bold text-xl">The Midnight Shift</p>
</div>
</div>
<div class="flex-1 p-8 flex flex-col justify-between space-y-8">
<div class="space-y-6">
<div class="flex items-center justify-between">
<span class="font-label text-[10px] text-on-surface-variant uppercase">ANALOG MASTER // 96KHZ 24BIT</span>
<span class="material-symbols-outlined text-tertiary">high_quality</span>
</div>
<div class="h-1 w-full bg-surface-container-highest rounded-full overflow-hidden">
<div class="h-full w-2/3 bg-primary"></div>
</div>
<div class="flex justify-between font-label text-[10px] text-on-surface-variant">
<span>02:44</span>
<span>04:12</span>
</div>
<div class="flex justify-center items-center gap-10">
<span class="material-symbols-outlined text-2xl text-on-surface-variant hover:text-primary transition-colors cursor-pointer">skip_previous</span>
<div class="h-14 w-14 bg-primary rounded-full flex items-center justify-center text-on-primary hover:scale-105 transition-transform cursor-pointer">
<span class="material-symbols-outlined text-3xl" style="font-variation-settings: 'FILL' 1;">play_arrow</span>
</div>
<span class="material-symbols-outlined text-2xl text-on-surface-variant hover:text-primary transition-colors cursor-pointer">skip_next</span>
</div>
</div>
<div class="flex flex-wrap gap-2 pt-4">
<span class="px-3 py-1 bg-surface-container-highest text-[10px] font-label text-secondary uppercase rounded">Progressive Metal</span>
<span class="px-3 py-1 bg-surface-container-highest text-[10px] font-label text-tertiary uppercase rounded">Post-Rock</span>
<span class="px-3 py-1 bg-surface-container-highest text-[10px] font-label text-primary uppercase rounded">IDM</span>
</div>
</div>
</div>
<!-- Gear List -->
<div class="space-y-4">
<div class="p-6 bg-surface-container-low border-l-2 border-primary rounded-r-xl">
<span class="font-label text-[10px] text-primary uppercase">Daily Drivers</span>
<p class="text-sm font-medium mt-1">Sennheiser HD800S</p>
</div>
<div class="p-6 bg-surface-container-low border-l-2 border-secondary rounded-r-xl">
<span class="font-label text-[10px] text-secondary uppercase">Interface</span>
<p class="text-sm font-medium mt-1">Universal Audio Apollo Solo</p>
</div>
<div class="p-6 bg-surface-container-low border-l-2 border-tertiary rounded-r-xl">
<span class="font-label text-[10px] text-tertiary uppercase">Monitor</span>
<p class="text-sm font-medium mt-1">Adam Audio T5V</p>
</div>
</div>
</div>
</section>
</main>
<!-- Footer -->
<footer class="bg-[#0d0e12] border-t border-[#81ecff]/10 py-12">
<div class="flex flex-col md:flex-row justify-between items-center max-w-7xl mx-auto px-6 gap-8">
<div class="text-slate-500 font-['Space_Grotesk'] text-[10px] uppercase tracking-widest">
© 2024 JASON WOLTJE // REV: 2.0.4
</div>
<div class="flex items-center gap-12 font-['Space_Grotesk'] text-[10px] uppercase tracking-widest">
<a class="text-slate-500 hover:text-[#d873ff] transition-colors opacity-100 hover:opacity-70" href="#">LinkedIn</a>
<a class="text-slate-500 hover:text-[#d873ff] transition-colors opacity-100 hover:opacity-70" href="#">GitHub</a>
<a class="text-slate-500 hover:text-[#d873ff] transition-colors opacity-100 hover:opacity-70" href="#">Twitter</a>
</div>
<div class="flex items-center gap-2">
<span class="w-2 h-2 rounded-full bg-tertiary"></span>
<span class="font-label text-[10px] text-slate-500 uppercase">SERVER STATUS: STABLE</span>
</div>
</div>
</footer>
</body></html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 KiB

View File

@@ -0,0 +1,263 @@
<!DOCTYPE html>
<html class="dark" lang="en"><head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>JASON WOLTJE // CONTACT</title>
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&amp;family=Inter:wght@300;400;500;600&amp;display=swap" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&amp;display=swap" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&amp;display=swap" rel="stylesheet"/>
<script id="tailwind-config">
tailwind.config = {
darkMode: "class",
theme: {
extend: {
"colors": {
"primary": "#81ecff",
"secondary-container": "#9900ce",
"on-surface": "#f7f5fc",
"on-secondary": "#39004f",
"inverse-primary": "#006976",
"surface": "#0d0e12",
"on-secondary-container": "#fff5fc",
"error-dim": "#d7383b",
"inverse-surface": "#faf8ff",
"secondary-fixed-dim": "#ebadff",
"surface-container-lowest": "#000000",
"on-error": "#490006",
"surface-variant": "#24252c",
"tertiary-dim": "#2be800",
"surface-container-high": "#1e1f25",
"on-primary-fixed": "#003840",
"error-container": "#9f0519",
"background": "#0d0e12",
"primary-fixed-dim": "#00d4ec",
"tertiary-fixed": "#2ff801",
"on-background": "#f7f5fc",
"primary-dim": "#00d4ec",
"inverse-on-surface": "#54555a",
"primary-container": "#00e3fd",
"surface-dim": "#0d0e12",
"outline-variant": "#47484d",
"tertiary-fixed-dim": "#2be800",
"on-error-container": "#ffa8a3",
"on-tertiary-fixed": "#064200",
"on-secondary-fixed-variant": "#8400b2",
"surface-container-highest": "#24252c",
"on-tertiary-fixed-variant": "#0d6200",
"secondary": "#d873ff",
"on-tertiary": "#0d6100",
"surface-container": "#18191e",
"secondary-fixed": "#f1c1ff",
"outline": "#75757a",
"on-primary-container": "#004d57",
"on-tertiary-container": "#0b5800",
"tertiary": "#8eff71",
"primary-fixed": "#00e3fd",
"error": "#ff716c",
"on-surface-variant": "#abaab0",
"on-primary-fixed-variant": "#005762",
"on-primary": "#005762",
"surface-tint": "#81ecff",
"secondary-dim": "#bc00fb",
"surface-bright": "#2a2c32",
"surface-container-low": "#121318",
"on-secondary-fixed": "#580078",
"tertiary-container": "#2ff801"
},
"borderRadius": {
"DEFAULT": "0.125rem",
"lg": "0.25rem",
"xl": "0.5rem",
"full": "0.75rem"
},
"fontFamily": {
"headline": ["Space Grotesk"],
"body": ["Inter"],
"label": ["Space Grotesk"]
}
},
},
}
</script>
<style>
.material-symbols-outlined {
font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
}
.glass-card {
background: rgba(36, 37, 44, 0.6);
backdrop-filter: blur(24px);
}
.grid-pattern {
background-image: radial-gradient(rgba(129, 236, 255, 0.1) 1px, transparent 1px);
background-size: 24px 24px;
}
</style>
</head>
<body class="bg-background text-on-background font-body selection:bg-primary/30 selection:text-primary">
<!-- TopNavBar Component -->
<header class="bg-[#0d0e12]/80 backdrop-blur-xl docked full-width top-0 sticky z-50 bg-gradient-to-b from-[#0d0e12] to-transparent">
<div class="flex justify-between items-center max-w-7xl mx-auto px-6 py-4">
<div class="text-xl font-bold tracking-widest text-[#81ecff] font-['Space_Grotesk'] uppercase tracking-tighter">
JASON WOLTJE
</div>
<nav class="hidden md:flex gap-8 items-center">
<a class="font-['Space_Grotesk'] uppercase tracking-tighter text-slate-400 hover:text-[#81ecff] transition-colors hover:opacity-80 transition-all duration-300" href="#">Home</a>
<a class="font-['Space_Grotesk'] uppercase tracking-tighter text-slate-400 hover:text-[#81ecff] transition-colors hover:opacity-80 transition-all duration-300" href="#">Projects</a>
<a class="font-['Space_Grotesk'] uppercase tracking-tighter text-slate-400 hover:text-[#81ecff] transition-colors hover:opacity-80 transition-all duration-300" href="#">About</a>
<a class="font-['Space_Grotesk'] uppercase tracking-tighter text-[#81ecff] border-b-2 border-[#81ecff] pb-1 hover:opacity-80 transition-all duration-300" href="#">Contact</a>
</nav>
<div class="flex items-center gap-4">
<button class="material-symbols-outlined text-[#81ecff] scale-95 active:scale-90 transition-transform">dark_mode</button>
</div>
</div>
</header>
<main class="min-h-screen relative">
<!-- Status Terminal Signature Component -->
<div class="fixed top-24 left-6 z-10 hidden xl:flex flex-col gap-1 items-start">
<div class="font-label text-[10px] text-tertiary uppercase tracking-[0.2em] bg-surface-container-high px-3 py-1 border-l-2 border-tertiary">
LOC: CONTACT_CORE
</div>
<div class="font-label text-[10px] text-slate-500 uppercase tracking-[0.2em] px-3">
STATUS: ENCRYPTED_HANDSHAKE
</div>
</div>
<section class="max-w-7xl mx-auto px-6 pt-16 pb-24 grid-pattern">
<div class="grid grid-cols-1 lg:grid-cols-12 gap-12 items-start">
<!-- Left Content: Editorial Header -->
<div class="lg:col-span-7 flex flex-col gap-6">
<div class="font-label text-sm text-secondary uppercase tracking-[0.3em]">01 // DIRECT CHANNELS</div>
<h1 class="font-headline text-6xl md:text-8xl font-bold tracking-tighter leading-none text-on-surface">
I'll find a <span class="text-primary">way to solve</span> your problem.
</h1>
<p class="text-on-surface-variant text-xl md:text-2xl max-w-2xl leading-relaxed mt-4">
Whether it's an architectural challenge, a messy deployment, or just a concept that needs refining—reach out. I build systems that endure.
</p>
<!-- Technical Meta Block -->
<div class="mt-12 grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="bg-surface-container-low p-6 border-l-2 border-outline-variant">
<span class="font-label text-[10px] text-primary uppercase tracking-widest block mb-2">AVAILABILITY</span>
<div class="flex items-center gap-3">
<div class="w-2 h-2 rounded-full bg-tertiary shadow-[0_0_10px_rgba(142,255,113,0.5)]"></div>
<span class="text-on-surface font-headline font-bold">ACCEPTING Q4 PROJECTS</span>
</div>
</div>
<div class="bg-surface-container-low p-6 border-l-2 border-outline-variant">
<span class="font-label text-[10px] text-secondary uppercase tracking-widest block mb-2">LOCAL TIME</span>
<span class="text-on-surface font-headline font-bold uppercase">14:42 UTC -05:00</span>
</div>
</div>
</div>
<!-- Right Content: Contact Form -->
<div class="lg:col-span-5 relative">
<div class="absolute -top-6 -right-6 w-32 h-32 bg-primary/5 rounded-full blur-3xl"></div>
<div class="glass-card p-8 rounded-lg border border-outline-variant/15 relative z-10">
<form class="flex flex-col gap-6">
<div class="group">
<label class="font-label text-[10px] text-on-surface-variant uppercase tracking-widest block mb-2">Full Name</label>
<input class="w-full bg-surface-container-lowest border-0 border-b border-outline-variant/50 focus:border-primary focus:ring-0 text-on-surface placeholder:text-outline transition-all py-3 px-0 font-headline uppercase tracking-tighter" placeholder="WALTER O'BRIEN" type="text"/>
</div>
<div class="group">
<label class="font-label text-[10px] text-on-surface-variant uppercase tracking-widest block mb-2">Email Address</label>
<input class="w-full bg-surface-container-lowest border-0 border-b border-outline-variant/50 focus:border-primary focus:ring-0 text-on-surface placeholder:text-outline transition-all py-3 px-0 font-headline uppercase tracking-tighter" placeholder="W.OBRIEN@CENTRAL.COM" type="email"/>
</div>
<div class="group">
<label class="font-label text-[10px] text-on-surface-variant uppercase tracking-widest block mb-2">Project Brief</label>
<textarea class="w-full bg-surface-container-lowest border-0 border-b border-outline-variant/50 focus:border-primary focus:ring-0 text-on-surface placeholder:text-outline transition-all py-3 px-0 font-headline uppercase tracking-tighter resize-none" placeholder="DESCRIBE THE SYSTEM ARCHITECTURE OR PROBLEM SET..." rows="4"></textarea>
</div>
<button class="mt-4 bg-primary text-on-primary font-label font-bold uppercase tracking-widest py-4 px-8 flex items-center justify-between hover:bg-primary-container transition-colors active:scale-[0.98]">
INITIALIZE HANDSHAKE
<span class="material-symbols-outlined text-lg">arrow_forward</span>
</button>
</form>
</div>
</div>
</div>
</section>
<!-- Newsletter Section (Mautic Focused) -->
<section class="bg-surface-container-low py-24 relative overflow-hidden">
<div class="absolute top-0 right-0 p-8">
<span class="font-label text-[120px] text-on-surface/[0.02] font-black select-none pointer-events-none">NEWSLETTER</span>
</div>
<div class="max-w-7xl mx-auto px-6">
<div class="flex flex-col md:flex-row items-center gap-12">
<div class="md:w-1/2">
<div class="font-label text-sm text-tertiary uppercase tracking-[0.3em] mb-4">02 // DATA STREAM</div>
<h2 class="font-headline text-4xl md:text-5xl font-bold tracking-tight text-on-surface mb-6">
Technical <span class="text-secondary">Insights</span>
</h2>
<p class="text-on-surface-variant text-lg leading-relaxed mb-8 max-w-lg">
Deep dives into Mautic automation, specialized infrastructure, and the occasional breakdown of a hobbyist synth engine. No spam, just technical value.
</p>
<div class="flex flex-wrap gap-3">
<span class="bg-surface-container-highest px-4 py-2 text-tertiary font-label text-[10px] tracking-widest uppercase border border-tertiary/20">System Architecture</span>
<span class="bg-surface-container-highest px-4 py-2 text-primary font-label text-[10px] tracking-widest uppercase border border-primary/20">Mautic Ops</span>
<span class="bg-surface-container-highest px-4 py-2 text-secondary font-label text-[10px] tracking-widest uppercase border border-secondary/20">Custom Fabric</span>
</div>
</div>
<div class="md:w-1/2 w-full">
<div class="p-1 bg-gradient-to-br from-primary via-secondary to-tertiary rounded-lg">
<div class="bg-surface-container-lowest p-8 md:p-12 rounded-lg flex flex-col gap-6">
<h3 class="font-headline text-2xl font-bold text-on-surface">Join the Jason's Updates</h3>
<div class="flex flex-col sm:flex-row gap-4">
<input class="flex-grow bg-surface-container-high border border-outline-variant/30 px-6 py-4 text-on-surface font-label uppercase tracking-widest focus:ring-1 focus:ring-primary focus:border-primary" placeholder="SYSTEM_MAILBOX@HOST.COM" type="email"/>
<button class="bg-white text-background px-8 py-4 font-label font-bold uppercase tracking-widest hover:bg-primary transition-colors">
SUBSCRIBE
</button>
</div>
<p class="font-label text-[10px] text-outline text-center uppercase tracking-tighter">
SECURE TLS ENCRYPTED ENDPOINT. UNSUBSCRIBE VIA ONE-CLICK HEADER.
</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Social Grid (Asymmetric Bento) -->
<section class="max-w-7xl mx-auto px-6 py-24">
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 h-[400px]">
<a class="col-span-2 row-span-2 group bg-surface-container hover:bg-surface-container-high transition-all flex flex-col justify-end p-8 border border-outline-variant/10 relative overflow-hidden" href="#">
<div class="absolute top-8 right-8 material-symbols-outlined text-4xl text-primary/20 group-hover:text-primary transition-colors">code</div>
<div class="relative z-10">
<span class="font-label text-xs text-primary uppercase tracking-widest block mb-1">GitHub</span>
<div class="font-headline text-3xl font-bold text-on-surface">PUBLIC REPOS</div>
<p class="text-on-surface-variant font-label text-[10px] mt-2 uppercase tracking-widest">Explore technical source code</p>
</div>
</a>
<a class="col-span-2 group bg-surface-container hover:bg-surface-container-high transition-all flex items-center justify-between px-8 border border-outline-variant/10" href="#">
<div>
<span class="font-label text-xs text-secondary uppercase tracking-widest block mb-1">LinkedIn</span>
<div class="font-headline text-2xl font-bold text-on-surface">PROFESSIONAL GRAPH</div>
</div>
<span class="material-symbols-outlined text-3xl text-secondary">share</span>
</a>
<a class="group bg-surface-container hover:bg-surface-container-high transition-all flex flex-col justify-center items-center p-6 border border-outline-variant/10" href="#">
<span class="material-symbols-outlined text-3xl text-tertiary mb-2">grid_view</span>
<span class="font-label text-xs text-on-surface-variant uppercase tracking-widest">Twitter</span>
</a>
<a class="group bg-surface-container hover:bg-surface-container-high transition-all flex flex-col justify-center items-center p-6 border border-outline-variant/10" href="#">
<span class="material-symbols-outlined text-3xl text-on-surface mb-2" data-icon="terminal">terminal</span>
<span class="font-label text-xs text-on-surface-variant uppercase tracking-widest">Polywork</span>
</a>
</div>
</section>
</main>
<!-- Footer Component -->
<footer class="bg-[#0d0e12] full-width py-12 border-t border-[#81ecff]/10">
<div class="flex flex-col md:flex-row justify-between items-center max-w-7xl mx-auto px-6 gap-8">
<div class="font-['Space_Grotesk'] text-[10px] uppercase tracking-widest text-slate-500">
© 2024 JASON WOLTJE // REV: 2.0.4
</div>
<div class="flex gap-12">
<a class="font-['Space_Grotesk'] text-[10px] uppercase tracking-widest text-slate-500 hover:text-[#d873ff] transition-colors opacity-100 hover:opacity-70" href="#">LinkedIn</a>
<a class="font-['Space_Grotesk'] text-[10px] uppercase tracking-widest text-slate-500 hover:text-[#d873ff] transition-colors opacity-100 hover:opacity-70" href="#">GitHub</a>
<a class="font-['Space_Grotesk'] text-[10px] uppercase tracking-widest text-slate-500 hover:text-[#d873ff] transition-colors opacity-100 hover:opacity-70" href="#">Twitter</a>
</div>
<div class="font-['Space_Grotesk'] text-[10px] uppercase tracking-widest text-[#81ecff]">
LATENCY: 12ms // CORE: ONLINE
</div>
</div>
</footer>
</body></html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

View File

@@ -0,0 +1,270 @@
<!DOCTYPE html>
<html class="dark" lang="en"><head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<link href="https://fonts.googleapis.com" rel="preconnect"/>
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600&amp;family=Space+Grotesk:wght@300;500;700&amp;display=swap" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&amp;display=swap" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&amp;display=swap" rel="stylesheet"/>
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
<script id="tailwind-config">
tailwind.config = {
darkMode: "class",
theme: {
extend: {
"colors": {
"primary": "#81ecff",
"secondary-container": "#9900ce",
"on-surface": "#f7f5fc",
"on-secondary": "#39004f",
"inverse-primary": "#006976",
"surface": "#0d0e12",
"on-secondary-container": "#fff5fc",
"error-dim": "#d7383b",
"inverse-surface": "#faf8ff",
"secondary-fixed-dim": "#ebadff",
"surface-container-lowest": "#000000",
"on-error": "#490006",
"surface-variant": "#24252c",
"tertiary-dim": "#2be800",
"surface-container-high": "#1e1f25",
"on-primary-fixed": "#003840",
"error-container": "#9f0519",
"background": "#0d0e12",
"primary-fixed-dim": "#00d4ec",
"tertiary-fixed": "#2ff801",
"on-background": "#f7f5fc",
"primary-dim": "#00d4ec",
"inverse-on-surface": "#54555a",
"primary-container": "#00e3fd",
"surface-dim": "#0d0e12",
"outline-variant": "#47484d",
"tertiary-fixed-dim": "#2be800",
"on-error-container": "#ffa8a3",
"on-tertiary-fixed": "#064200",
"on-secondary-fixed-variant": "#8400b2",
"surface-container-highest": "#24252c",
"on-tertiary-fixed-variant": "#0d6200",
"secondary": "#d873ff",
"on-tertiary": "#0d6100",
"surface-container": "#18191e",
"secondary-fixed": "#f1c1ff",
"outline": "#75757a",
"on-primary-container": "#004d57",
"on-tertiary-container": "#0b5800",
"tertiary": "#8eff71",
"primary-fixed": "#00e3fd",
"error": "#ff716c",
"on-surface-variant": "#abaab0",
"on-primary-fixed-variant": "#005762",
"on-primary": "#005762",
"surface-tint": "#81ecff",
"secondary-dim": "#bc00fb",
"surface-bright": "#2a2c32",
"surface-container-low": "#121318",
"on-secondary-fixed": "#580078",
"tertiary-container": "#2ff801"
},
"borderRadius": {
"DEFAULT": "0.125rem",
"lg": "0.25rem",
"xl": "0.5rem",
"full": "0.75rem"
},
"fontFamily": {
"headline": ["Space Grotesk"],
"body": ["Inter"],
"label": ["Space Grotesk"]
}
},
},
}
</script>
<style>
.material-symbols-outlined {
font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
display: inline-block;
vertical-align: middle;
}
.technical-grid {
background-image: radial-gradient(rgba(129, 236, 255, 0.15) 1px, transparent 1px);
background-size: 32px 32px;
}
.hero-gradient {
background: radial-gradient(circle at top right, rgba(129, 236, 255, 0.08), transparent 40%),
radial-gradient(circle at bottom left, rgba(216, 115, 255, 0.05), transparent 40%);
}
</style>
</head>
<body class="bg-background text-on-background font-body selection:bg-primary/30">
<!-- TopNavBar -->
<header class="bg-[#0d0e12]/80 backdrop-blur-xl docked full-width top-0 sticky z-50 bg-gradient-to-b from-[#0d0e12] to-transparent">
<nav class="flex justify-between items-center max-w-7xl mx-auto px-6 py-4">
<div class="text-xl font-bold tracking-widest text-[#81ecff] font-['Space_Grotesk'] uppercase tracking-tighter">
JASON WOLTJE
</div>
<div class="hidden md:flex items-center space-x-8 font-['Space_Grotesk'] uppercase tracking-tighter text-[14px]">
<a class="text-[#81ecff] border-b-2 border-[#81ecff] pb-1 hover:opacity-80 transition-all duration-300" href="#">Home</a>
<a class="text-slate-400 hover:text-[#81ecff] transition-colors hover:opacity-80 transition-all duration-300" href="#">Projects</a>
<a class="text-slate-400 hover:text-[#81ecff] transition-colors hover:opacity-80 transition-all duration-300" href="#">About</a>
<a class="text-slate-400 hover:text-[#81ecff] transition-colors hover:opacity-80 transition-all duration-300" href="#">Contact</a>
</div>
<div class="flex items-center gap-4">
<button class="text-[#81ecff] scale-95 active:scale-90 transition-transform">
<span class="material-symbols-outlined" data-icon="dark_mode">dark_mode</span>
</button>
</div>
</nav>
</header>
<main>
<!-- Hero Section -->
<section class="relative min-h-[921px] flex flex-col justify-center overflow-hidden technical-grid hero-gradient px-6 border-b border-outline-variant/10">
<!-- Status Terminal Component -->
<div class="absolute top-8 left-6 md:left-12 flex items-center gap-3">
<span class="flex h-2 w-2 rounded-full bg-tertiary shadow-[0_0_8px_#8eff71]"></span>
<span class="font-label text-[10px] text-tertiary uppercase tracking-[0.2em]">LOC: 39.0997° N, 94.5786° W | STATUS: ONLINE | REV: 2.0.4</span>
</div>
<div class="max-w-7xl mx-auto w-full pt-20">
<div class="grid grid-cols-1 lg:grid-cols-12 gap-12 items-center">
<div class="lg:col-span-8">
<span class="font-label text-primary text-xs tracking-[0.4em] uppercase mb-6 block">01 // THE MANIFESTO</span>
<h1 class="font-headline text-5xl md:text-8xl font-bold tracking-tighter text-on-surface leading-[0.9] mb-8">
I WILL FIND <br/>
<span class="text-transparent bg-clip-text bg-gradient-to-r from-primary to-secondary">A WAY,</span><br/>
OR I WILL <br/>
MAKE ONE.
</h1>
<p class="font-body text-xl md:text-2xl text-on-surface-variant max-w-2xl leading-relaxed">
A multidisciplinary architect of digital ecosystems and agricultural infrastructures. Executing vision through precision.
</p>
</div>
</div>
</div>
<!-- Absolute positioned crosshair deco -->
<div class="absolute right-12 bottom-12 hidden lg:block opacity-20">
<div class="relative w-32 h-32 border border-primary/40 rounded-full flex items-center justify-center">
<div class="w-full h-[1px] bg-primary absolute"></div>
<div class="w-[1px] h-full bg-primary absolute"></div>
</div>
</div>
</section>
<!-- Intro/Bio Section -->
<section class="py-24 px-6 bg-surface-container-low">
<div class="max-w-7xl mx-auto">
<div class="flex flex-col lg:flex-row gap-16 items-start">
<div class="lg:w-1/3">
<div class="relative group">
<div class="absolute -inset-1 bg-gradient-to-r from-primary to-secondary rounded-lg blur opacity-25 group-hover:opacity-50 transition duration-1000"></div>
<div class="relative aspect-square overflow-hidden rounded-lg bg-surface-container-highest">
<img alt="Jason Woltje" class="w-full h-full object-cover filter grayscale hover:grayscale-0 transition-all duration-700" data-alt="Professional portrait of a visionary leader with sharp features, dramatic lighting, modern tech studio background with blue accents" src="https://lh3.googleusercontent.com/aida-public/AB6AXuBzgaQlTkGK3JJtR7UxOmrZUhYrM-h2nWgxdGmXRyWDuPn_rkIc46M-Cp5o3R2Kn9_OvFmgF4jnk0cqhrFejntIj41FGxxm9XHSKjGgAj8VCeorf-QTgxCcEGtCT5JexeyFOtQRM5PBqwYUXMeHJXRkJJeBEreL7LJvynfDhOsNh6796oK1uUVhdTQ8B6o2Fp2O6we2zQapyVPk7tX0T7G0rSIMpB2xMAIPn87eZuX7BvWEtO9rXdUIKfg52cYSVC_-aQny1FqJJwM"/>
</div>
</div>
</div>
<div class="lg:w-2/3">
<div class="space-y-8">
<div class="inline-flex items-center px-3 py-1 rounded-full border border-primary/20 bg-primary/5 text-primary text-[10px] font-label uppercase tracking-widest">
Profile Summary
</div>
<h2 class="font-headline text-4xl md:text-5xl font-bold tracking-tight text-on-surface">
Engineering growth through technological mastery and strategic leadership.
</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-8 font-body text-on-surface-variant leading-relaxed">
<p>
As a <span class="text-primary font-semibold">CEO</span>, I build brands that resonate with clarity and purpose. My leadership is rooted in the philosophy that every challenge is an opportunity for architectural innovation.
</p>
<p>
As an <span class="text-secondary font-semibold">IT Manager &amp; Consultant</span>, I bridge the gap between traditional industry and high-velocity digital transformation, ensuring robust, scalable infrastructures.
</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Navigation Bento Grid (Core Areas) -->
<section class="py-24 px-6 relative">
<div class="max-w-7xl mx-auto">
<div class="mb-16">
<span class="font-label text-tertiary text-xs tracking-[0.4em] uppercase mb-4 block">02 // CORE OPERATIONS</span>
<h2 class="font-headline text-3xl font-bold tracking-tight">STRATEGIC VERTICALS</h2>
</div>
<div class="grid grid-cols-1 md:grid-cols-12 gap-6 h-auto md:h-[600px]">
<!-- DYOR Pro -->
<a class="md:col-span-8 group relative overflow-hidden rounded-xl bg-surface-container-highest border border-outline-variant/10 hover:border-primary/50 transition-all duration-500" href="#">
<div class="absolute inset-0 opacity-40 transition-transform duration-700 group-hover:scale-110">
<img alt="DYOR Pro" class="w-full h-full object-cover" data-alt="Abstract glowing blockchain visualization with nodes and network connections in vibrant cyan and purple neon colors" src="https://lh3.googleusercontent.com/aida-public/AB6AXuBt1gm_f0Nx6wJbjkLjJGbd4-LOuv5GQqstDFwR9KxF8Hy9Zdy--1o8BBco8bbw6OeYY9rlXaQzduO4mdNJUujPrrQYf_A_3tf6wKM0n2QjM1225tbbZ10q5wOwLJ6lh6wvtqWNQFjsT15NN9eegvt6ZGXNrrolU9GBwP4Re9OfpU7I8C4Uqe7YzGKAF5B_YM3Nzf1McZiXlKQTtESXycsMmMM73h_QVNqkjRJqKzTx2tTL53g6L8R3Ic3aJhrYab9Ne_op7uqy4aA"/>
</div>
<div class="absolute inset-0 bg-gradient-to-t from-background via-background/40 to-transparent"></div>
<div class="relative h-full flex flex-col justify-end p-8 md:p-12">
<div class="mb-4 text-primary">
<span class="material-symbols-outlined text-4xl" data-icon="monitoring">monitoring</span>
</div>
<h3 class="font-headline text-3xl md:text-5xl font-bold mb-4">DYOR PRO</h3>
<p class="font-body text-on-surface-variant max-w-md text-lg">Leading the vanguard of technical intelligence and decentralized insight. CEO &amp; Visionary lead.</p>
<div class="mt-8 flex items-center gap-2 text-primary font-label text-sm tracking-widest uppercase opacity-0 group-hover:opacity-100 transition-opacity">
Access Platform <span class="material-symbols-outlined" data-icon="north_east">north_east</span>
</div>
</div>
</a>
<!-- DDKansas -->
<a class="md:col-span-4 group relative overflow-hidden rounded-xl bg-surface-container-highest border border-outline-variant/10 hover:border-secondary/50 transition-all duration-500" href="#">
<div class="absolute inset-0 opacity-30 transition-transform duration-700 group-hover:scale-110">
<img alt="DDKansas" class="w-full h-full object-cover" data-alt="Clean minimal data dashboard reflected in a glass surface with soft purple glowing accents" src="https://lh3.googleusercontent.com/aida-public/AB6AXuAzyZRMOGp6Vmrs9RH551LpEku0C3uqV-3OwzcIlg3m8jLsFhtuhlrKa8uyKp_fEfoh_NZTeZSawLH8tcdVIhVxPXn0weoUoBQuEKDP8erOMY2522XDaWGbHzVXvK4hhZvm-OFrQhpCMJPvtEJWhK9tLYewJ-Axy4r-bJ8LGlOyVjQS3wvkB6WNigBpSw-t4H3RHJKpcT-vA4fycQ5N5ylv2-doi5HLYR-jQ47Fc3olAJ1eVV_IzFfN5Ae4Y37vRWd5uZ27LiXFh2I"/>
</div>
<div class="absolute inset-0 bg-gradient-to-t from-background via-background/20 to-transparent"></div>
<div class="relative h-full flex flex-col justify-end p-8">
<div class="mb-4 text-secondary">
<span class="material-symbols-outlined text-4xl" data-icon="query_stats">query_stats</span>
</div>
<h3 class="font-headline text-2xl font-bold mb-2">DDKANSAS</h3>
<p class="font-body text-on-surface-variant text-sm">Strategic consulting for high-performance enterprise data systems.</p>
</div>
</a>
<!-- Agricultural IT -->
<a class="md:col-span-12 group relative overflow-hidden rounded-xl bg-surface-container-highest border border-outline-variant/10 hover:border-tertiary/50 transition-all duration-500 min-h-[250px]" href="#">
<div class="absolute inset-0 opacity-20 transition-transform duration-700 group-hover:scale-105">
<img alt="Agricultural IT" class="w-full h-full object-cover" data-alt="Wide shot of a high-tech smart farm at dusk with glowing sensors and digital overlay elements on crop rows" src="https://lh3.googleusercontent.com/aida-public/AB6AXuCyV0cex39hqTefS4BcNe3O2jyop7w_xSF2yEGMMNGxHMrcpuhPZ7cP06so6Sdzz8XihlJjNvrKKYJYOj6SSRh8He7JMs398AsJ6XsMSCbbeLOYPrGxZqCOUil2erftsE9Q6r9t2h00fhjE3gtsxrP7SPrt6fJy1OJPFLkXPwl9nK078kyfsJsEDz2tavlsxHDertV7SUmvGDbsAWnWR0U3uIudtWHHA5-ZeY9xjxR6x2IMnU6up_SsI55lqxNzSpo4wb9Z7fsbbPc"/>
</div>
<div class="absolute inset-0 bg-gradient-to-r from-background via-background/60 to-transparent"></div>
<div class="relative h-full flex flex-col justify-center p-8 md:p-12 max-w-2xl">
<div class="mb-4 text-tertiary">
<span class="material-symbols-outlined text-4xl" data-icon="precision_manufacturing">precision_manufacturing</span>
</div>
<h3 class="font-headline text-3xl font-bold mb-2 uppercase tracking-tighter">AGRICULTURAL IT</h3>
<p class="font-body text-on-surface-variant text-lg">Infrastructure management for the modern landscape. Precision meeting the soil.</p>
</div>
</a>
</div>
</div>
</section>
<!-- Quote/Makers spirit -->
<section class="py-32 px-6 overflow-hidden">
<div class="max-w-4xl mx-auto text-center relative">
<div class="absolute top-0 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[500px] h-[500px] bg-primary/5 rounded-full blur-[100px]"></div>
<span class="material-symbols-outlined text-outline-variant/30 text-8xl mb-8" data-icon="format_quote">format_quote</span>
<p class="font-headline text-3xl md:text-5xl italic font-light tracking-tight text-on-surface leading-tight relative z-10">
"Precision is not just about measuring twice; it's about building the system that makes measurement obsolete."
</p>
<div class="mt-12 font-label text-primary tracking-[0.3em] uppercase text-sm">Jason Woltje // Principal Architect</div>
</div>
</section>
</main>
<!-- Footer -->
<footer class="bg-[#0d0e12] full-width py-12 border-t border-[#81ecff]/10">
<div class="flex flex-col md:flex-row justify-between items-center max-w-7xl mx-auto px-6 gap-8">
<div class="font-['Space_Grotesk'] text-[10px] uppercase tracking-widest text-[#81ecff]">
© 2024 JASON WOLTJE // REV: 2.0.4
</div>
<div class="flex items-center gap-10 font-['Space_Grotesk'] text-[10px] uppercase tracking-widest">
<a class="text-slate-500 hover:text-[#d873ff] transition-colors opacity-100 hover:opacity-70" href="#">LinkedIn</a>
<a class="text-slate-500 hover:text-[#d873ff] transition-colors opacity-100 hover:opacity-70" href="#">GitHub</a>
<a class="text-slate-500 hover:text-[#d873ff] transition-colors opacity-100 hover:opacity-70" href="#">Twitter</a>
</div>
<div class="text-slate-600 font-label text-[8px] tracking-[0.5em] uppercase">
ENGINEERED FOR EXCELLENCE
</div>
</div>
</footer>
</body></html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

View File

@@ -0,0 +1,292 @@
<!DOCTYPE html>
<html class="dark" lang="en"><head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&amp;family=Inter:wght@300;400;500;600&amp;display=swap" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&amp;display=swap" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&amp;display=swap" rel="stylesheet"/>
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
<script id="tailwind-config">
tailwind.config = {
darkMode: "class",
theme: {
extend: {
"colors": {
"primary": "#81ecff",
"secondary-container": "#9900ce",
"on-surface": "#f7f5fc",
"on-secondary": "#39004f",
"inverse-primary": "#006976",
"surface": "#0d0e12",
"on-secondary-container": "#fff5fc",
"error-dim": "#d7383b",
"inverse-surface": "#faf8ff",
"secondary-fixed-dim": "#ebadff",
"surface-container-lowest": "#000000",
"on-error": "#490006",
"surface-variant": "#24252c",
"tertiary-dim": "#2be800",
"surface-container-high": "#1e1f25",
"on-primary-fixed": "#003840",
"error-container": "#9f0519",
"background": "#0d0e12",
"primary-fixed-dim": "#00d4ec",
"tertiary-fixed": "#2ff801",
"on-background": "#f7f5fc",
"primary-dim": "#00d4ec",
"inverse-on-surface": "#54555a",
"primary-container": "#00e3fd",
"surface-dim": "#0d0e12",
"outline-variant": "#47484d",
"tertiary-fixed-dim": "#2be800",
"on-error-container": "#ffa8a3",
"on-tertiary-fixed": "#064200",
"on-secondary-fixed-variant": "#8400b2",
"surface-container-highest": "#24252c",
"on-tertiary-fixed-variant": "#0d6200",
"secondary": "#d873ff",
"on-tertiary": "#0d6100",
"surface-container": "#18191e",
"secondary-fixed": "#f1c1ff",
"outline": "#75757a",
"on-primary-container": "#004d57",
"on-tertiary-container": "#0b5800",
"tertiary": "#8eff71",
"primary-fixed": "#00e3fd",
"error": "#ff716c",
"on-surface-variant": "#abaab0",
"on-primary-fixed-variant": "#005762",
"on-primary": "#005762",
"surface-tint": "#81ecff",
"secondary-dim": "#bc00fb",
"surface-bright": "#2a2c32",
"surface-container-low": "#121318",
"on-secondary-fixed": "#580078",
"tertiary-container": "#2ff801"
},
"borderRadius": {
"DEFAULT": "0.125rem",
"lg": "0.25rem",
"xl": "0.5rem",
"full": "0.75rem"
},
"fontFamily": {
"headline": ["Space Grotesk"],
"body": ["Inter"],
"label": ["Space Grotesk"]
}
},
},
}
</script>
<style>
.material-symbols-outlined {
font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
}
.grid-pattern {
background-image: radial-gradient(circle, #47484d 1px, transparent 1px);
background-size: 24px 24px;
opacity: 0.1;
}
</style>
</head>
<body class="bg-background text-on-background font-body selection:bg-primary/30 selection:text-primary">
<!-- TopNavBar -->
<nav class="bg-[#0d0e12]/80 backdrop-blur-xl docked full-width top-0 sticky z-50 bg-gradient-to-b from-[#0d0e12] to-transparent flat no shadows">
<div class="flex justify-between items-center max-w-7xl mx-auto px-6 py-4">
<div class="text-xl font-bold tracking-widest text-[#81ecff] font-['Space_Grotesk'] uppercase tracking-tighter">
JASON WOLTJE
</div>
<div class="hidden md:flex items-center gap-8 font-['Space_Grotesk'] uppercase tracking-tighter">
<a class="text-slate-400 hover:text-[#81ecff] transition-colors hover:opacity-80 transition-all duration-300" href="#">Home</a>
<a class="text-[#81ecff] border-b-2 border-[#81ecff] pb-1 hover:opacity-80 transition-all duration-300" href="#">Projects</a>
<a class="text-slate-400 hover:text-[#81ecff] transition-colors hover:opacity-80 transition-all duration-300" href="#">About</a>
<a class="text-slate-400 hover:text-[#81ecff] transition-colors hover:opacity-80 transition-all duration-300" href="#">Contact</a>
</div>
<div class="flex items-center gap-4">
<button class="text-[#81ecff] hover:opacity-80 transition-all duration-300 scale-95 active:scale-90 transition-transform">
<span class="material-symbols-outlined">dark_mode</span>
</button>
</div>
</div>
</nav>
<main class="relative min-h-screen">
<!-- Status Terminal Component -->
<div class="fixed top-24 right-6 z-40 hidden lg:block">
<div class="bg-surface-container-high/60 backdrop-blur-md px-4 py-2 border-l-2 border-tertiary shadow-xl">
<p class="font-label text-[10px] uppercase tracking-[0.2em] text-tertiary">
LOC: 1,244 | STATUS: ONLINE | REV: 2.0.4
</p>
</div>
</div>
<!-- Hero Section -->
<header class="relative pt-16 pb-24 overflow-hidden">
<div class="absolute inset-0 grid-pattern pointer-events-none"></div>
<div class="max-w-7xl mx-auto px-6 relative z-10">
<div class="max-w-2xl">
<div class="inline-flex items-center gap-2 mb-6">
<span class="w-12 h-[1px] bg-primary"></span>
<span class="font-label text-xs uppercase tracking-widest text-primary">02 // PORTFOLIO</span>
</div>
<h1 class="font-headline text-5xl md:text-7xl font-bold tracking-tighter mb-8 leading-[0.9]">
TECHNICAL <br/>
<span class="text-transparent bg-clip-text bg-gradient-to-r from-primary to-secondary">ARCHITECTURES.</span>
</h1>
<p class="text-on-surface-variant text-lg max-w-lg leading-relaxed">
A curated selection of industrial infrastructure, research platforms, and independent consultancy projects engineered for high-performance environments.
</p>
</div>
</div>
</header>
<!-- Projects Technical Grid -->
<section class="max-w-7xl mx-auto px-6 pb-32">
<div class="grid grid-cols-1 lg:grid-cols-12 gap-8">
<!-- Project 1: DYOR Pro (Large Feature) -->
<article class="lg:col-span-8 group relative flex flex-col bg-surface-container-low overflow-hidden rounded-lg">
<div class="aspect-video overflow-hidden relative">
<img alt="DYOR Pro Platform" class="w-full h-full object-cover grayscale opacity-50 group-hover:grayscale-0 group-hover:opacity-100 transition-all duration-700 scale-105 group-hover:scale-100" data-alt="Abstract visualization of high-tech digital crypto data streams and analytical dashboard interfaces with neon blue accents in a dark void" src="https://lh3.googleusercontent.com/aida-public/AB6AXuB5z7FntnlEkUGFUR9HuXDxazWa19fH6BJXhJoB9zgSiVwZ-AbXMvjfciKI2nGA45py9l_MWn4k38_c2v6QNYzYxSM-KNNU8HDLff5XKjIXYREea6aKwlt1iLHt1knaoHhxAJaT4fGmqUT6X6Myn0RHoEoXDLqR2BI4Y2dr_znul1aq5CCfUP503_z_luY519bZ1pjWyOLPMchtkI3KPh_PI60wrVZlixIRNRRa5wk5GxWwQZznFKJZzMoL6LSd2AqrdOXzCAR8_7U"/>
<div class="absolute inset-0 bg-gradient-to-t from-surface-container-low via-transparent to-transparent"></div>
</div>
<div class="p-8 lg:p-12 relative">
<div class="flex flex-wrap items-center gap-4 mb-6">
<span class="font-label text-[10px] uppercase tracking-widest px-3 py-1 bg-primary/10 text-primary border border-primary/20">FOUNDER</span>
<span class="font-label text-[10px] uppercase tracking-widest px-3 py-1 bg-secondary/10 text-secondary border border-secondary/20">CRYPTO/RESEARCH</span>
</div>
<h3 class="font-headline text-4xl font-bold tracking-tight mb-4 group-hover:text-primary transition-colors">DYOR Pro</h3>
<p class="text-on-surface-variant mb-8 max-w-xl text-lg">
An institutional-grade research platform delivering deep-on-chain analytics and automated due diligence for decentralized financial markets.
</p>
<div class="grid grid-cols-2 gap-8 mb-10 border-t border-outline-variant/15 pt-8">
<div>
<h4 class="font-label text-[10px] uppercase text-outline tracking-widest mb-2">Technical Stack</h4>
<p class="font-label text-sm text-on-surface">Python, React, GraphQL, PostgreSQL</p>
</div>
<div>
<h4 class="font-label text-[10px] uppercase text-outline tracking-widest mb-2">Primary Role</h4>
<p class="font-label text-sm text-on-surface">CEO &amp; Lead Architect</p>
</div>
</div>
<a class="inline-flex items-center gap-3 px-8 py-4 bg-primary text-on-primary font-label font-bold text-xs uppercase tracking-widest rounded-md hover:shadow-[0_0_20px_rgba(129,236,255,0.4)] transition-all group-active:scale-95" href="#">
Launch Project
<span class="material-symbols-outlined text-sm">arrow_outward</span>
</a>
</div>
</article>
<!-- Project 2: Agricultural IT -->
<article class="lg:col-span-4 group bg-surface-container flex flex-col rounded-lg">
<div class="h-64 overflow-hidden relative">
<img alt="Agricultural IT Infrastructure" class="w-full h-full object-cover grayscale opacity-40 group-hover:grayscale-0 group-hover:opacity-80 transition-all duration-700" data-alt="Top-down view of automated irrigation systems and precision farming sensors in a modern greenhouse with cool technical lighting" src="https://lh3.googleusercontent.com/aida-public/AB6AXuDUBjHVwE3rQxEq-bQ3XO4L1zCy16b3qz7VEaPsjsXaWAv6SGjbHfYVr75D6pR7vJZm10R_0s2RdadynYwS8k3TdzIgBdOoN2SexYGFPAYT8nVt1bsNVDqP0uLa4Ez7ohnfRtfpKiXkpCLpGFL_myxXzsSuEo_Y57ahJFuwlytYK7hlPMoS-c8Ad_VcACEA1ljmF2nOA2CFTaGrtlkX7ecqbYloSe5X8upGC7f-GJUob7rhqlmA4a-B4yfwUGu47pnaypGYw8nbkow"/>
</div>
<div class="p-8 flex flex-col flex-grow">
<div class="mb-4">
<span class="font-label text-[10px] uppercase tracking-widest px-3 py-1 bg-tertiary/10 text-tertiary border border-tertiary/20">INFRASTRUCTURE</span>
</div>
<h3 class="font-headline text-2xl font-bold tracking-tight mb-4 group-hover:text-primary transition-colors">Agricultural IT</h3>
<p class="text-on-surface-variant text-sm leading-relaxed mb-8">
End-to-end IT management and infrastructure design for large-scale precision agriculture operations, focusing on IoT connectivity and field data telemetry.
</p>
<div class="mt-auto pt-6 border-t border-outline-variant/15">
<div class="mb-6">
<h4 class="font-label text-[10px] uppercase text-outline tracking-widest mb-1">Stack</h4>
<p class="font-label text-xs text-on-surface">IoT Hub, Cisco, Linux Clusters</p>
</div>
<button class="w-full py-4 border border-outline-variant/30 text-on-surface font-label font-bold text-xs uppercase tracking-widest rounded-md hover:bg-surface-container-high transition-colors">
View Details
</button>
</div>
</div>
</article>
<!-- Project 3: DDKansas -->
<article class="lg:col-span-5 group bg-surface-container flex flex-col rounded-lg">
<div class="p-8 lg:p-12">
<div class="mb-4">
<span class="font-label text-[10px] uppercase tracking-widest px-3 py-1 bg-secondary/10 text-secondary border border-secondary/20">CONSULTANCY</span>
</div>
<h3 class="font-headline text-3xl font-bold tracking-tight mb-4 group-hover:text-primary transition-colors">DDKansas</h3>
<p class="text-on-surface-variant leading-relaxed mb-8">
Independent technology consultancy providing bespoke digital transformation strategies and high-level architectural oversight for Midwest enterprises.
</p>
<div class="space-y-4 mb-8">
<div class="flex items-center gap-3">
<span class="material-symbols-outlined text-tertiary text-lg">check_circle</span>
<span class="font-label text-xs text-on-surface uppercase tracking-wider">Cloud Migration Strategy</span>
</div>
<div class="flex items-center gap-3">
<span class="material-symbols-outlined text-tertiary text-lg">check_circle</span>
<span class="font-label text-xs text-on-surface uppercase tracking-wider">Legacy System Refactoring</span>
</div>
<div class="flex items-center gap-3">
<span class="material-symbols-outlined text-tertiary text-lg">check_circle</span>
<span class="font-label text-xs text-on-surface uppercase tracking-wider">Fractional CTO Services</span>
</div>
</div>
<button class="inline-flex items-center gap-3 px-6 py-3 bg-surface-container-highest text-primary border border-primary/20 font-label font-bold text-xs uppercase tracking-widest rounded-md hover:bg-primary/5 transition-all">
Review Case Study
<span class="material-symbols-outlined text-sm">menu_book</span>
</button>
</div>
</article>
<!-- Technical Specs Bento Box -->
<article class="lg:col-span-7 bg-surface-container-low rounded-lg p-8 lg:p-12 relative overflow-hidden group">
<div class="absolute top-0 right-0 p-8 opacity-10">
<span class="material-symbols-outlined text-[120px]" style="font-variation-settings: 'FILL' 1;">architecture</span>
</div>
<h3 class="font-headline text-2xl font-bold tracking-tight mb-8">Core Methodologies</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
<div class="space-y-2">
<h4 class="font-label text-[10px] uppercase text-primary tracking-[0.2em]">Scale</h4>
<p class="text-on-surface font-light">Architecting systems capable of handling 100k+ concurrent telemetry streams without degradation.</p>
</div>
<div class="space-y-2">
<h4 class="font-label text-[10px] uppercase text-secondary tracking-[0.2em]">Security</h4>
<p class="text-on-surface font-light">Zero-trust architecture implementation for sensitive financial and agricultural data assets.</p>
</div>
<div class="space-y-2">
<h4 class="font-label text-[10px] uppercase text-tertiary tracking-[0.2em]">Efficiency</h4>
<p class="text-on-surface font-light">Optimizing CI/CD pipelines to reduce deployment overhead by an average of 40%.</p>
</div>
<div class="space-y-2">
<h4 class="font-label text-[10px] uppercase text-primary tracking-[0.2em]">Resilience</h4>
<p class="text-on-surface font-light">Designing multi-region disaster recovery protocols for mission-critical infrastructure.</p>
</div>
</div>
</article>
</div>
</section>
<!-- CTA Section -->
<section class="bg-surface-container-low py-24 relative">
<div class="max-w-7xl mx-auto px-6 text-center">
<h2 class="font-headline text-4xl md:text-5xl font-bold mb-8">HAVE A COMPLEX PROJECT?</h2>
<p class="text-on-surface-variant max-w-2xl mx-auto mb-12 text-lg">
I specialize in building bridges between legacy constraints and future-proofed technical excellence.
</p>
<div class="flex flex-col sm:flex-row justify-center gap-4">
<button class="px-10 py-5 bg-primary text-on-primary font-label font-bold text-sm uppercase tracking-widest rounded-md hover:shadow-[0_0_30px_rgba(129,236,255,0.3)] transition-all">
Inquiry Portal
</button>
<button class="px-10 py-5 border border-outline-variant/30 text-on-surface font-label font-bold text-sm uppercase tracking-widest rounded-md hover:bg-surface-container-high transition-colors">
View Resume
</button>
</div>
</div>
</section>
</main>
<!-- Footer -->
<footer class="bg-[#0d0e12] full-width py-12 border-t border-[#81ecff]/10">
<div class="flex flex-col md:flex-row justify-between items-center max-w-7xl mx-auto px-6 gap-8 font-['Space_Grotesk'] text-[10px] uppercase tracking-widest">
<div class="text-slate-500">
© 2024 JASON WOLTJE // REV: 2.0.4
</div>
<div class="flex gap-12">
<a class="text-slate-500 hover:text-[#d873ff] transition-colors opacity-100 hover:opacity-70" href="#">LinkedIn</a>
<a class="text-slate-500 hover:text-[#d873ff] transition-colors opacity-100 hover:opacity-70" href="#">GitHub</a>
<a class="text-slate-500 hover:text-[#d873ff] transition-colors opacity-100 hover:opacity-70" href="#">Twitter</a>
</div>
<div class="flex items-center gap-2 text-[#81ecff]">
<span class="w-2 h-2 rounded-full bg-[#81ecff] animate-pulse"></span>
SYSTEMS NOMINAL
</div>
</div>
</footer>
</body></html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 KiB

View File

@@ -0,0 +1,100 @@
# Design System Document: Technical Editorial
## 1. Overview & Creative North Star
### Creative North Star: "The Master Architect"
This design system is built for a persona that balances the precision of an engineer with the vision of an executive. It moves away from the "standard dashboard" aesthetic to embrace a **Technical Editorial** direction.
To break the "template" look, we utilize:
* **Intentional Asymmetry:** Hero sections and content blocks should avoid perfect 50/50 splits. Use 60/40 ratios to create a sense of dynamic movement.
* **The Overlap:** Technical elements (like grid patterns or terminal-style labels) should subtly overlap image containers or section breaks to suggest a "maker" spirit—building things that break out of the box.
* **Aggressive Typography Scales:** High-contrast sizing between massive display headers and tiny, precise monospace labels creates an authoritative, modern hierarchy.
---
## 2. Colors
The palette is rooted in a deep midnight foundation, punctuated by high-energy technical accents.
### Palette Strategy
* **Foundation:** `background` (#0d0e12) provides the "void" from which technical elements emerge.
* **Primary Accent:** `primary` (#81ecff) is our electric blue, used for critical actions and brand markers.
* **Technical Secondary:** `secondary` (#d873ff) and `tertiary` (#8eff71) provide depth. Use these for status indicators, code snippets, or to differentiate hobby-related content (Music/Making).
### The "No-Line" Rule
**Explicit Instruction:** Do not use 1px solid borders to separate sections.
Boundaries must be defined through:
1. **Background Shifts:** Use `surface_container_low` sections sitting on a `background` floor.
2. **Tonal Transitions:** Use a very subtle gradient transition between two surface tokens to imply a change in context.
### Surface Hierarchy & Nesting
Treat the UI as a series of nested physical layers.
* **Base:** `background`
* **Section:** `surface_container`
* **Card/Module:** `surface_container_highest` or `surface_container_lowest` (depending on whether you want it to recede or pop).
### The "Glass & Gradient" Rule
For floating navigation or modals, use semi-transparent `surface_bright` with a **24px Backdrop Blur**. Apply a signature gradient from `primary` to `primary_container` on main CTAs to give them a "lit from within" neon glow.
---
## 3. Typography
The typography strategy pairs the brutalist precision of technical fonts with the readability of a premium sans-serif.
* **Display & Headlines (Space Grotesk):** This is our "Editorial" voice. Its wide, technical, yet sophisticated. Use `display-lg` for hero statements to command attention.
* **Body & Titles (Inter):** High-readability sans-serif. Use `body-lg` for long-form thought leadership to ensure an "Executive" feel.
* **Labels (Space Grotesk - Monospace feel):** Use `label-md` in all-caps for technical metadata, tags, and small "geeky" details.
**Hierarchy Tip:** Pair a `display-md` headline with a tiny `label-sm` technical prefix (e.g., "01 // INTRODUCTION") to reinforce the maker/coder aesthetic.
---
## 4. Elevation & Depth
We avoid traditional drop shadows in favor of **Tonal Layering**.
* **The Layering Principle:** Place a `surface_container_highest` card inside a `surface_container_low` wrapper. The difference in hex value provides a sophisticated "lift" without the "dirty" look of grey shadows.
* **Ambient Shadows:** If a floating element (like a dropdown) requires a shadow, use a 40px blur with 6% opacity. The shadow color should be a tinted version of `primary` or `on_surface`, never pure black.
* **The "Ghost Border" Fallback:** If containment is needed for complex data, use the `outline_variant` token at **15% opacity**. This creates a "code-like" border that is felt rather than seen.
* **Glassmorphism:** Use `surface_variant` at 60% opacity with a blur for a "frosted terminal" effect, allowing background grid patterns to bleed through subtly.
---
## 5. Components
### Buttons
* **Primary:** High-contrast `primary` background with `on_primary` text. **Radius:** `md` (0.375rem). No border.
* **Secondary:** `surface_container_high` background with `primary` text.
* **Ghost:** Transparent background with `outline_variant` (20% opacity) border. Use for low-priority technical actions.
### Technical Chips
* Used for "Skills" or "Tools."
* **Style:** `surface_container_highest` background, `secondary` or `tertiary` text. Use `label-sm` for the font.
### Inputs
* **Style:** "Bottom-line only" or fully enclosed in `surface_container_low`.
* **States:** On focus, the `outline` should glow with `primary` and a subtle 4px outer blur.
### Cards & Lists
* **No Dividers:** Never use horizontal lines. Use `spacing-lg` (vertical white space) or alternate background tints between `surface_container` and `surface_container_low`.
* **Grid Pattern:** For hero cards, overlay a subtle 20px dot grid or cross-hair pattern to emphasize the "Technical/Maker" spirit.
### Additional Signature Component: "The Status Terminal"
A small, fixed-position component (or header element) that displays technical metadata about the current page (e.g., "LOC: 1,244 | STATUS: ONLINE | REV: 2.0.4"). Use `label-sm` in `tertiary` (terminal green).
---
## 6. Do's and Don'ts
### Do:
* **Do** use asymmetrical layouts. A photo of a "maker" project should be offset from the text grid.
* **Do** use monospace-style labels for all metadata to satisfy the "geeky" requirement.
* **Do** ensure high contrast in Light Mode; the `inverse_surface` must remain crisp and professional.
* **Do** use `primary_container` for subtle hover states on large cards.
### Don't:
* **Don't** use 1px solid borders at 100% opacity. They look like "out-of-the-box" templates.
* **Don't** use standard "web safe" blue. Only use the provided `primary` (#81ecff).
* **Don't** over-round corners. Stick to the `md` (0.375rem) or `sm` (0.125rem) scale to maintain a "sharp/technical" edge. `xl` is for specialized buttons only.
* **Don't** use shadows on cards that are sitting on the background; let tonal shifts do the work.

227
docs/PRD.md Normal file
View File

@@ -0,0 +1,227 @@
# PRD — jasonwoltje.com Professional Website
**Status:** Active
**Milestone:** 0.0.1 (pre-MVP bootstrap)
**Owner:** Jason Woltje
**Last updated:** 2026-04-13
---
## 1. Purpose
Build Jason Woltje's professional personal website (`jasonwoltje.com`) as a Payload CMSbacked portfolio + writing platform. The site anchors Jason's transition from IT Director to software engineer and showcases technical work, writing, and maker/music interests.
## 2. Goals
| Goal | Success criterion |
|---|---|
| Establish a credible engineer-executive brand | "Technical Editorial" design system from `design-samples/` rendered with high fidelity |
| Serve as portfolio for projects | CMS-authored `projects` collection rendered at `/projects` + `/projects/[slug]` |
| Publish long-form writing | `posts` collection + `/writing` and `/writing/[slug]` routes |
| Let Jason edit content without code | Payload admin at `/admin`, sole admin user |
| Deploy on existing homelab | Portainer stack on `w-docker0` behind Traefik; no new infra dependencies |
| Respect immutable-tag hard rule | Deployments reference `sha-<short>`; never `latest` |
## 3. Non-goals (v0.0.x)
- Multi-author CMS or role-based ACL
- Comments / community features
- E-commerce / subscriptions
- Search (Algolia, Meilisearch) — defer until content volume warrants
- Internationalization
- Native mobile app
## 4. Users
| Role | Scope |
|---|---|
| Public visitor | Read all published content, submit contact form, subscribe to newsletter (once Mautic is live) |
| Admin (Jason) | Full Payload admin: create/edit/publish content, manage media, view contact submissions |
## 5. Content model
### Collections
| Name | Purpose | Key fields |
|---|---|---|
| `users` | Payload auth. Jason only for v0.0.x | email, password, role (admin) |
| `media` | All uploads. Sharp-generated sizes: `thumb` (400), `card` (800), `hero` (1600), `og` (1200×630). `alt` required. | url, alt, credit, sizes |
| `categories` | Project/post taxonomy | name, slug, accent (`primary` / `secondary` / `tertiary` — maps to design tokens) |
| `projects` | Portfolio entries | title, slug, role, category (rel), summary, body (richText), stack (string[]), heroImage, gallery, externalUrl, featured (bool), order, status (draft/published), publishedAt, seo (group) |
| `posts` | Blog / long-form writing | title, slug, excerpt, body (richText + blocks: code, callout, image), category (rel), heroImage, tags (string[]), status, publishedAt, seo (group) |
| `gear` | Music/Making items (decorative only for v0.0.x) | name, type, notes, image, accent |
| `contactSubmissions` | Inbound form entries; admin-read only | name, email, brief, source, submittedAt, ipHash, status (new/replied/spam) |
### Globals
| Name | Fields |
|---|---|
| `home` | heroHeadline (richText), heroSub, statusTerminal (baked at build time), featuredProjects (rel[]), ctas |
| `about` | introBlock, makerMindsetBlock, soundtrackBlock, gearRefs (rel[]), timeline (year/title/note[]) |
| `contact` | availabilityBadge, timezoneLabel, directEmail, socialLinks (label, url, icon[]), newsletterEnabled (bool) |
| `resume` | summary, experience[] (company, role, dates, bullets), skills[], education[], pdfExport (auto-generated) |
| `navigation` | primaryLinks (label, href[]), footerStatusText |
| `seo` | siteTitle, defaultDescription, defaultOgImage, twitterHandle, jsonLdPerson |
## 6. Page routing (Next.js App Router)
| Route | Source | Rendering |
|---|---|---|
| `/` | `globals.home` + featured `projects` | ISR (revalidate 60s, on-demand via Payload `afterChange` hook) |
| `/about` | `globals.about` + `gear` | ISR |
| `/projects` | `projects` where status=published | ISR |
| `/projects/[slug]` | `projects` by slug | SSG + ISR fallback |
| `/writing` | `posts` where status=published | ISR |
| `/writing/[slug]` | `posts` by slug | SSG + ISR fallback |
| `/contact` | `globals.contact` | Static shell, client form |
| `/resume` | `globals.resume` | SSR, HTML |
| `/resume.pdf` | `globals.resume` | Dynamic, server-rendered PDF (`@react-pdf/renderer` or Puppeteer) |
| `/admin/**` | Payload admin | Dynamic, auth-gated |
| `/api/contact` | Custom endpoint | Dynamic (Turnstile verify + honeypot + Payload write + email) |
| `/api/health` | Healthcheck | Dynamic |
| `/sitemap.xml`, `/robots.txt`, `/rss.xml` | Generated | Dynamic w/ cache |
## 7. Design system
Source: `design-samples/stitch_jasonwoltje.com/silicon_ethos/DESIGN.md`
**Ported as-is to production:**
| Token family | Source |
|---|---|
| Colors (M3 tokens) | Inline `tailwind.config` in stitch HTMLs → `tailwind.config.ts` `extend.colors` |
| Typography | Space Grotesk (display/labels) + Inter (body), `next/font/google` self-hosted, CSS vars `--font-headline` / `--font-body` / `--font-label` |
| Icons | `lucide-react` (replaces Material Symbols CDN) |
| Tailwind plugins | `@tailwindcss/forms`, `@tailwindcss/container-queries` |
| Utilities | `.ghost-border` (outline-variant/15), `.glass-card` (backdrop-blur + surface-bright/60), `.neon-cta` (primary→primary-container gradient + cyan glow) |
**Hard design rules (from DESIGN.md):**
- No 1px solid borders at 100% opacity — tonal surfaces only
- No 50/50 splits — 60/40 asymmetric layouts
- Status Terminal on header/footer (`LOC / STATUS / REV`) — baked from build SHA
- Dark mode always-on (`<html class="dark">` permanent for v0.0.x)
**Implementation approach:** fixed Next pages composed of typed React section components (HeroHeadline, ProjectBentoGrid, MakerMindsetCard, AudioSignalPath, StatusTerminal, ContactForm, NewsletterBand, SocialBento). Content comes from Payload globals/collections. No generic drag-and-drop page builder — protects editorial asymmetry.
## 8. Services & integrations
| Service | Purpose | Status |
|---|---|---|
| Cloudflare Turnstile | Contact form CAPTCHA | To integrate (site key + secret) |
| Umami (self-hosted) | Analytics | To deploy separately (stack 2); site loads Umami tracker once URL known |
| Mautic (self-hosted) | Newsletter | NOT YET DEPLOYED — newsletter UI shows "Coming soon" or disabled state until Mautic endpoint exists |
| Resend / SMTP relay | Contact form notifications, Payload email | ASSUMPTION: SMTP credentials from existing homelab relay |
| Cloudflare DNS | `jasonwoltje.com` A record → w-docker0 edge (10.1.1.43) | DNS records to be added |
## 9. Infrastructure
| Element | Value |
|---|---|
| Deploy host | `w-docker0` (10.1.1.45), single-node Docker Swarm |
| Orchestration | Portainer (https://10.1.1.43:9443), endpoint ID 7 |
| Ingress | Edge Traefik on 10.1.1.43 (TLS termination, Let's Encrypt) → per-swarm Traefik on `w-docker0` (HTTP, `entrypoints=web`) |
| External overlay | `traefik-public` (pre-existing) |
| Registry | `git.mosaicstack.dev/jason.woltje/professional-website` (Gitea container packages) |
| CI | Woodpecker CI (ci.mosaicstack.dev), Kaniko builder |
| Image tags | `sha-<8-char>` (always), branch tag (`main`/`develop`), `vX.Y.Z` (on git tag). `latest` exists but is NEVER referenced by compose. |
### Traefik labels (canonical pattern)
Mirrors `mosaic-stack-website/docker-compose.swarm.yml`. Labels live under `deploy.labels` (Swarm). Router uses `entrypoints=web`; TLS handled at edge. Middleware: www→apex 301 redirect.
### Environment variables
| Var | Required | Notes |
|---|---|---|
| `WEB_IMAGE_TAG` | yes | Always `sha-<short>` or `vX.Y.Z`; CI sets, manual deploy updates |
| `PAYLOAD_SECRET` | yes | 32+ char random, Portainer-stored |
| `PAYLOAD_POSTGRES_USER` / `_PASSWORD` / `_DB` | yes | Portainer |
| `DATABASE_URI` | yes | Composed in compose from above |
| `PAYLOAD_PUBLIC_SERVER_URL` | yes | `https://jasonwoltje.com` |
| `NEXT_PUBLIC_SITE_URL` | yes | `https://jasonwoltje.com` |
| `TURNSTILE_SITE_KEY` / `_SECRET_KEY` | yes | Cloudflare Turnstile |
| `NEXT_PUBLIC_UMAMI_SRC` / `_UMAMI_WEBSITE_ID` | optional | Analytics; empty disables tracker |
| `SMTP_*` or `RESEND_API_KEY` | yes | Contact form notifications |
| `NEXT_PUBLIC_BUILD_SHA` / `_BUILD_REV` | yes | Baked at build for Status Terminal |
## 10. CI pipeline (Woodpecker, mirrors `website-web.yml`)
Stages (all depend via `depends_on`):
1. `install``pnpm install --frozen-lockfile`
2. `lint``pnpm lint`
3. `typecheck``pnpm typecheck`
4. `build``pnpm build` (validates Next)
5. `security-audit``pnpm audit --prod --audit-level=high`
6. `docker-build` — Kaniko → push `sha-<short>` + branch tag + `latest`-on-main
7. `security-trivy` — fail on HIGH/CRITICAL in built image
8. `link-package` — POST Gitea package→repo link
9. `deploy` (Phase 2, not v0.0.1) — Portainer API redeploy
10. `health-check` (Phase 2) — poll `/api/health`
For v0.0.1, ship through step 8. Initial deploy and subsequent redeploys are manual via Portainer UI until the auto-deploy step is wired.
## 11. Acceptance criteria (v0.0.1 → v0.1.0 MVP)
- [ ] Repo exists at `git.mosaicstack.dev/jason.woltje/professional-website` with PRD + TASKS + README + LICENSE committed
- [ ] Payload 3 + Next.js 16 scaffold boots locally (`pnpm dev` → admin accessible)
- [ ] Tailwind config extends design tokens from `DESIGN.md`
- [ ] All collections + globals defined and seeded with placeholder content
- [ ] All routes render without error (even with empty content)
- [ ] Contact form persists to `contactSubmissions` + emails notification
- [ ] Turnstile gating verified in staging
- [ ] Dockerfile builds reproducibly under Kaniko
- [ ] `.woodpecker/web.yml` present; first CI run pushes image to Gitea registry
- [ ] Trivy scan passes (no HIGH/CRITICAL)
- [ ] Compose stack (`docker-compose.swarm.yml`) deploys on `w-docker0` via Portainer
- [ ] Edge Traefik TLS config updated for `jasonwoltje.com`
- [ ] DNS records active at Cloudflare; apex + www resolve
- [ ] Site loads over HTTPS at both `jasonwoltje.com` and `www.jasonwoltje.com` (www redirects)
- [ ] `/admin` loads Payload admin, Jason can log in
- [ ] `/api/health` returns 200
- [ ] Lighthouse: Performance ≥ 85, Accessibility ≥ 95, SEO ≥ 95 on home page
## 12. Assumptions
- **ASSUMPTION:** SMTP relay credentials available from an existing homelab service or a new Resend free-tier key.
- **ASSUMPTION:** Cloudflare Turnstile site/secret keys will be provisioned on `jason@diversecanvas.com`'s CF account.
- **ASSUMPTION:** Umami will be deployed as a separate Portainer stack; if not ready by MVP, tracker loads only when `NEXT_PUBLIC_UMAMI_WEBSITE_ID` is set.
- **ASSUMPTION:** Mautic deployment is out of scope for this repo; newsletter UI is present but wired as "Coming soon" until a Mautic endpoint is provided.
- **ASSUMPTION:** Payload 3 is compatible with Next.js 16 at build time. If incompatibility emerges, fall back to Next.js 15 LTS — flagged as a rollback path, not an approval gate.
- **ASSUMPTION:** PostgreSQL 17 (alpine) for the `postgres` service. Payload supports pg 15+; no concerns expected.
- **ASSUMPTION:** Headshots in `images/` are pre-upload originals. They are imported into the Payload `media` collection as part of content seeding; originals may stay in repo or be removed at Jason's preference post-seed.
## 13. Escalations (require Jason's decision)
| ID | Topic | Impact |
|---|---|---|
| ESC-01 | Edge Traefik TLS config for `jasonwoltje.com` (new domain, not under `*.woltje.com` wildcard). Does Jason apply the config change, or delegate via runbook? | Blocks HTTPS |
| ESC-02 | Mautic deployment timeline — if it slips, newsletter UI remains stub for MVP | Soft; affects contact page polish |
| ESC-03 | SMTP credentials source — reuse existing relay, or provision Resend? | Blocks contact form email notifications |
| ESC-04 | Turnstile keys — Jason to provision at `cloudflare.com/dashboard` and drop values in Portainer env | Blocks spam-resistant contact form |
| ESC-05 | Analytics (Umami) stack — deploy alongside this site or as separate milestone? | Affects tracker wiring |
## 14. Risks
| Risk | Mitigation |
|---|---|
| Next.js 16 + Payload 3 version drift | Pin exact versions; fallback to Next 15 documented |
| Gitea package path normalization (`jason.woltje` dot) | Dry-run Kaniko push early; adjust image path if Gitea normalizes to `jason-woltje` |
| Single-node host loss | Volume backups (pg_dump + media tar) to offsite (B2/R2) — defer to v0.1.x |
| Contact form spam | Turnstile + honeypot + rate-limit on `/api/contact` |
| Design drift from stitch | Section components mirror stitch HTML structure; design review before v0.1.0 cut |
## 15. Out of scope / deferred
- Full page builder (Payload `blocks`) — consider only if writing volume justifies
- MinIO migration — triggered by >20 GB media or multi-replica frontend
- Authentik SSO — single-admin site doesn't need it
- Auto-deploy via Portainer API — Phase 2 after stable manual deploys
- Offsite backups — Phase 2
- Spotify / Last.fm integrations — decorative only per Jason's call
---
**Source of truth for tasks:** see [`docs/TASKS.md`](TASKS.md).
**Design source:** `design-samples/stitch_jasonwoltje.com/` (HTML mockups + `silicon_ethos/DESIGN.md`).

121
docs/TASKS.md Normal file
View File

@@ -0,0 +1,121 @@
# TASKS — jasonwoltje.com
**Milestone:** 0.0.1 — Bootstrap (repo, PRD, local scaffold)
**Next:** 0.0.2 — Design system port + collections
**MVP target:** 0.1.0 — Full site deployed on w-docker0, DNS live, all routes
Source of truth for scope: [`PRD.md`](PRD.md).
---
## Legend
| Status | Meaning |
|---|---|
| ☐ | pending |
| ◐ | in progress |
| ✅ | done |
| 🚫 | blocked — see `blocker` column |
| ⏭ | deferred |
---
## Milestone 0.0.1 — Bootstrap
| ID | Task | Status | Owner | Issue | Blocker |
|---|---|---|---|---|---|
| BOOT-01 | Create Gitea repo `jason.woltje/professional-website` | ✅ | orchestrator | — | — |
| BOOT-02 | Commit PRD + TASKS + README + LICENSE + `.gitignore` | ◐ | orchestrator | — | — |
| BOOT-03 | Push bootstrap commit to `main` | ☐ | orchestrator | — | — |
| BOOT-04 | Create first feature branch `feat/scaffold` | ☐ | worker | — | BOOT-03 |
## Milestone 0.0.2 — Scaffold + design system
| ID | Task | Status | Owner |
|---|---|---|---|
| SCAFF-01 | Initialize Next.js 16 + Payload 3 app in `src/` | ☐ | worker |
| SCAFF-02 | Configure pnpm workspace, TS strict, ESLint, Prettier | ☐ | worker |
| SCAFF-03 | Tailwind v3 config: port M3 tokens from stitch HTML | ☐ | worker |
| SCAFF-04 | `next/font`: Space Grotesk + Inter, CSS vars | ☐ | worker |
| SCAFF-05 | Install `lucide-react`, `@tailwindcss/forms`, `@tailwindcss/container-queries` | ☐ | worker |
| SCAFF-06 | Global utility classes: `.ghost-border`, `.glass-card`, `.neon-cta`, StatusTerminal baked vars | ☐ | worker |
| SCAFF-07 | Payload Postgres adapter + local `docker compose` for dev DB | ☐ | worker |
| SCAFF-08 | Health endpoint `/api/health` | ☐ | worker |
## Milestone 0.0.3 — Content model
| ID | Task | Status | Owner |
|---|---|---|---|
| CMS-01 | Collections: `users`, `media`, `categories`, `projects`, `posts`, `gear`, `contactSubmissions` | ☐ | worker |
| CMS-02 | Globals: `home`, `about`, `contact`, `resume`, `navigation`, `seo` | ☐ | worker |
| CMS-03 | Payload hooks: `revalidatePath` on publish | ☐ | worker |
| CMS-04 | Access control: admin-only for sensitive collections | ☐ | worker |
| CMS-05 | Seed script: placeholder content for all collections/globals | ☐ | worker |
## Milestone 0.0.4 — Pages + sections
| ID | Task | Status | Owner |
|---|---|---|---|
| UI-01 | Section components: HeroHeadline, ProjectBentoGrid, MakerMindsetCard, AudioSignalPath, StatusTerminal, ContactForm, NewsletterBand, SocialBento | ☐ | worker |
| UI-02 | `/` page composition | ☐ | worker |
| UI-03 | `/about` page composition | ☐ | worker |
| UI-04 | `/projects` + `/projects/[slug]` | ☐ | worker |
| UI-05 | `/writing` + `/writing/[slug]` | ☐ | worker |
| UI-06 | `/contact` (form + Turnstile + honeypot + rate-limit) | ☐ | worker |
| UI-07 | `/resume` + `/resume.pdf` (react-pdf or puppeteer) | ☐ | worker |
| UI-08 | Sitemap, robots, RSS | ☐ | worker |
## Milestone 0.0.5 — CI + container
| ID | Task | Status | Owner |
|---|---|---|---|
| CI-01 | Multi-stage `Dockerfile` (deps → build → runner, non-root, standalone Next output) | ☐ | worker |
| CI-02 | `.woodpecker/web.yml` — lint/typecheck/build/audit/Kaniko/Trivy/link-package | ☐ | worker |
| CI-03 | First CI run → image pushed to Gitea registry | ☐ | orchestrator |
| CI-04 | Verify image path: `jason.woltje` dot handling | ☐ | orchestrator |
## Milestone 0.0.6 — Deploy
| ID | Task | Status | Owner |
|---|---|---|---|
| DEP-01 | `docker-compose.swarm.yml` — web + postgres, traefik-public external, labels mirror mosaicstack-website | ☐ | worker |
| DEP-02 | `.env.example` committed | ☐ | worker |
| DEP-03 | **ESC-01:** Edge Traefik TLS config for `jasonwoltje.com` | 🚫 | Jason | ESC-01 |
| DEP-04 | Cloudflare DNS: A/CNAME for apex + www, proxied | ☐ | Jason | — |
| DEP-05 | Portainer stack creation on w-docker0 (endpoint 7), env vars populated | ☐ | orchestrator | DEP-03 |
| DEP-06 | First deploy smoke test: `/`, `/admin`, `/api/health`, www→apex 301 | ☐ | orchestrator | DEP-05 |
| DEP-07 | Payload admin bootstrap: Jason creates first admin user | ☐ | Jason | DEP-06 |
## Milestone 0.1.0 — MVP acceptance
See `PRD.md` §11 for full acceptance criteria. Gate conditions:
- All routes render
- Lighthouse thresholds met (Perf ≥85, A11y ≥95, SEO ≥95)
- Contact form end-to-end (submit → Payload → email)
- Headshots uploaded to media collection
- At least 1 project + 1 post published
- Release tag `v0.1.0` pushed; CI tagged build deployed
## Deferred (Phase 2)
| Task | Rationale |
|---|---|
| Auto-deploy via Portainer API | Defer until manual deploys are stable |
| Health-check gate in CI | Same |
| Umami analytics stack | Separate repo/stack |
| Mautic newsletter integration | Separate deploy; newsletter UI is stub until live |
| Offsite backups (B2/R2) | v0.1.x concern |
| MinIO migration | Triggered by volume growth |
---
## Active blockers / escalations
| ID | Description | Unblocks |
|---|---|---|
| ESC-01 | Edge Traefik TLS config for new domain `jasonwoltje.com` | DEP-03 → DEP-05+ |
| ESC-03 | SMTP/Resend credentials for contact form notifications | UI-06 email path |
| ESC-04 | Turnstile site + secret keys | UI-06 CAPTCHA |
Unblocking these does not gate scaffold work — only deploy and contact form completion.

Binary file not shown.

After

Width:  |  Height:  |  Size: 641 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB