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>
61
.gitignore
vendored
Normal 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
@@ -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
|
||||
```
|
||||
18
.mosaic/orchestrator/config.json
Normal 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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
@@ -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&family=Inter:wght@300;400;500;600;700&family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&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 & 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>
|
||||
|
After Width: | Height: | Size: 405 KiB |
@@ -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&family=Inter:wght@300;400;500;600&display=swap" rel="stylesheet"/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&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>
|
||||
|
After Width: | Height: | Size: 242 KiB |
@@ -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&family=Space+Grotesk:wght@300;500;700&display=swap" rel="stylesheet"/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&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 & 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 & 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>
|
||||
|
After Width: | Height: | Size: 338 KiB |
@@ -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&family=Inter:wght@300;400;500;600&display=swap" rel="stylesheet"/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&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 & 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>
|
||||
|
After Width: | Height: | Size: 298 KiB |
100
design-samples/stitch_jasonwoltje.com/silicon_ethos/DESIGN.md
Normal 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. It’s 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
@@ -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 CMS–backed 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
@@ -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.
|
||||
BIN
images/Jason_fullsize-scaled.jpg
Normal file
|
After Width: | Height: | Size: 641 KiB |
|
After Width: | Height: | Size: 128 KiB |
|
After Width: | Height: | Size: 168 KiB |