cesnimda
29ecfc0e79
fix: case-study TOC sidebar wasn't sticking (grid stretch made it as tall as content)
2026-07-12 19:53:30 +02:00
cesnimda
dabcc68b21
fix: externalize hoisted scripts so CSP script-src 'self' allows them
...
CI / quality (push) Successful in 2m3s
CI / e2e (push) Failing after 10s
CI / lighthouse (push) Failing after 10s
CI / relay (push) Successful in 49s
Deploy / deploy (push) Failing after 6s
CI / images (push) Has been skipped
Astro was inlining the theme/nav/observer bundle as <script type="module">.
The deployed nginx CSP blocks inline scripts, so the reveal observer never
ran and every [data-reveal] section stayed at opacity:0 (space reserved,
nothing visible). Force JS external via assetsInlineLimit.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-07-11 13:17:24 +02:00
cesnimda
c877c61e3e
deploy: publish site on host port 1337; nginx proxies /api/contact; auto-deploy
...
CI / quality (push) Has been cancelled
CI / e2e (push) Has been cancelled
CI / lighthouse (push) Has been cancelled
CI / relay (push) Has been cancelled
Deploy / deploy (push) Has been cancelled
CI / images (push) Has been cancelled
- site nginx listens on 1337; proxies /api/contact to the relay over the internal
network (single public port; TLS terminates upstream at Cloudflare)
- trailing-slash rewrite moved inside location / so /api/contact isn't redirected
- compose: publish ${SITE_PORT:-1337}, internal bridge network, no Traefik labels
(non-destructive — does not touch the WordPress apex router)
- .gitea/workflows/deploy.yml: on push to main, runner rebuilds + restarts the stack
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-07-10 10:00:33 +02:00
cesnimda
8132c202ba
fix: mobile theme toggle + UI polish; refresh both case studies
...
- fix: theme toggle did nothing on mobile — duplicate id=theme-toggle bound only the
desktop button; bind all [data-theme-toggle] instead (root cause)
- header: 2px gap top/bottom; TraceMotif svg 24->28 so the status dot isn't clipped
- remove private git.cesnimda.uk links (footer, contact, mobile nav, JSON-LD sameAs);
soften homelab diagram label
- both projects now 'in development'; about wording: Gmail analytics -> inbox cleanup
- JobTrack: refreshed to current app (Kanban pipeline, deterministic CV match, assistive
AI, EF Core) + new mockups; InboxIntel: .NET 10, pgvector + Ollama semantic search,
inbox-health analytics, split-view + new mockups; meta descriptions updated
- new ATS CV PDFs (from the new docx, via Word)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-07-10 09:54:30 +02:00
cesnimda
bfa8cfd357
feat: homelab case study from live infra; Traefik-based deploy
...
- rewrote homelab (content + topology diagram + stack) from a live inspection of the host:
Ubuntu 24.04, ~30 Docker services behind Traefik (Cloudflare-fronted, TLS, HTTP/3),
Authentik SSO forward-auth, CrowdSec, Pi-hole, self-hosted Gitea + CI runner, socket-proxy,
per-app network isolation; WordPress framed as being decommissioned (not future arch)
- deploy: docker-compose now uses Traefik labels + traefik_proxy network (was assumed nginx
edge); .env.example adds SITE_HOST/TRAEFIK_ENTRYPOINT; colophon + ARCHITECTURE/DOCKER/
DEPLOYMENT specs corrected nginx-edge -> Traefik (site container still serves via nginx)
- PROJECT_STATUS: pre-launch checklist updated; infra section added
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-04 11:23:09 +02:00
cesnimda
a10418ab93
fix: CV split-button height + LinkedIn redirect; tooling tidy
...
- CV split button: make the chevron <details> flex and the summary full-height so the
toggle matches the primary button height (verified 39.1px == 39.1px)
- nginx: /Linkedin now 301s to the real profile (linkedin.com/in/connor-babbington)
- prettier-ignore .pnpm-store; gitignore .claude/settings.local.json; e2e port 4321->4399;
dev preview autoPort
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-04 11:22:48 +02:00
cesnimda
b4b293bdb4
feat: real headshot + JobTrack seed-data screenshots
...
- portrait: warm outdoor headshot, cropped 4:5 and optimised to WebP (800x1000, 116kB),
used in hero + about
- JobTrack case study: three real seed-data captures (applications, dashboard, reminders)
optimised to WebP (~40kB each) replacing the placeholder skeletons
- alts/captions updated to match the real screens
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-04 11:22:48 +02:00
cesnimda
18c556bd54
feat: ATS-safe CV rework (EN + NO), replacing scrambled two-column PDFs
...
CI / quality (push) Has been cancelled
CI / e2e (push) Has been cancelled
CI / lighthouse (push) Has been cancelled
CI / relay (push) Has been cancelled
CI / images (push) Has been cancelled
- single-column, real-text PDFs: standard headings (Summary, Skills, Experience,
Projects, Education), consistent dates, no letter-spacing
- 'Systems Developer, eight years experience' (drops 'mid-level'); apprentice->developer
progression shown; Projects section added; Norwegian written natively (errors fixed)
- one page each, ~8 kB (was 132/172 kB); verified clean ATS text extraction + reading order
- generator committed to tools/cv (content.js + pdfkit/docx builders) for reproducibility
- editable .docx kept alongside; site file-size labels updated
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-04 07:22:57 +02:00
cesnimda
743cce306b
docs: finalise PROJECT_STATUS + TODO; lint public browser script
...
CI / quality (push) Has been cancelled
CI / e2e (push) Has been cancelled
CI / lighthouse (push) Has been cancelled
CI / relay (push) Has been cancelled
CI / images (push) Has been cancelled
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-04 06:24:12 +02:00
cesnimda
9088dcffb9
feat: Docker images, compose stacks, nginx config, Gitea CI
...
- site image: multi-stage node build -> unprivileged nginx (non-root, read-only)
- nginx: CSP + security headers, immutable asset caching, revalidated HTML,
canonical trailing slash, preserved /Linkedin 301, legacy-WP 410s, custom 404
- externalise theme-init so CSP uses script-src 'self' (no inline hash)
- prod + dev compose; .env.example; relay Dockerfile fixed (image ships app user)
- Gitea Actions: quality, e2e, lighthouse budgets, relay build, image push on main
- verified: both images build; relay healthz 200; site serves EN/NO with CSP + redirect
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-04 06:21:35 +02:00
cesnimda
033c9ec315
test: vitest unit + playwright e2e suites; fix a11y, contrast, no-JS reveal
...
- vitest: dictionary parity, slug-map bijection, content-schema validation, JSON-LD (23)
- playwright: both locales, language-switch mapping (incl. no-JS), CV downloads,
form happy-path + honeypot, axe a11y on 5 templates x 2 themes (23)
- fix: raise ink-faint + light accent to meet WCAG AA 4.5:1 (axe-verified)
- fix: gate reveal animations behind html.js so content is visible without JS
(progressive enhancement - was hidden at opacity 0); scan reduced-motion path
- fix: validate contact form before the anti-bot time-trap (no false success)
- chore: ESLint node globals, typed diagram props, resvg fontFiles, prettier pass
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-04 06:14:18 +02:00
cesnimda
1b5204e7f8
feat: build-time OpenGraph images (satori-free, resvg + vendored TTFs)
...
- one 1200x630 PNG per page per locale, design-system styled
- hand-built SVG rasterised by resvg (handles variable fonts; satori cannot)
- vendored Space Grotesk / Inter / JetBrains Mono TTFs for deterministic offline builds
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-04 01:35:28 +02:00
cesnimda
2330f374fc
feat: case-study template, all pages, routing, sitemap, 404
...
- case-study components: CsHeader, TldrBox, MiniToc, SectionRenderer, DecisionList,
ArchDiagram (data-driven), Gallery, NextPrev, CaseStudyPage
- standalone pages: projects index, about, experience, contact (with form),
cv hub, colophon — all EN/NO compositions
- full route tree: EN root + /no localised slugs (prosjekter, om-meg, erfaring,
kontakt, kolofon, hjemmelab) per ROUTING_SPEC
- bilingual 404 with trace-fray motif; robots.txt + sitemap.xml from slug map
- Portrait atom; reusable sections gain header/eyebrow toggles for standalone pages
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-04 01:30:32 +02:00
cesnimda
9a6d0edf6d
chore: add favicon (CB monogram)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-04 01:20:47 +02:00
cesnimda
1fce1b3cec
feat: core layout, UI atoms, homepage + behaviour modules
...
- UI atoms: Chip, Button, SplitCvButton, LangSwitch, ThemeToggle, Card,
SectionLabel, TraceMotif, FramedImage
- core: Base/Seo/Header/MobileNav/Footer/HintBar/SkipLink/ThemeScript
- homepage sections: Hero, ProofStrip, SkillsGrid, ProjectCards,
ExperienceTimeline, AboutTeaser, ContactBand + Homepage composition (EN/NO)
- behaviour modules: theme, nav (overlay/hint/copy/header), observer (reveal/spy),
lightbox, form — progressive enhancement, fail-silent
- SEO head component: meta, hreflang from slug map, JSON-LD, OG references
- move content data to src/data (avoid Astro reserved content-collection folder)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-04 01:20:46 +02:00
cesnimda
2184a1892f
feat: content layer — zod schemas, validated bilingual data, locale view models
...
- schema.ts: zod schemas per DATA_MODEL (profile, projects, experience, skills, meta)
- nested {en,no} model: invariant facts once, prose twice; validated at build
- content: profile, skills, experience (with apprentice->developer progression),
JobTrack + InboxIntel case studies with data-driven arch diagrams, homelab capability page
- per-page SEO meta (EN/NO)
- content.ts: locale-resolved view models; CV PDFs wired
- deviation from literal Astro-collections logged in PROJECT_STATUS with rationale
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-04 01:05:21 +02:00
cesnimda
63db8bf254
feat: i18n layer — locales, slug-map contract, typed dictionaries
...
- locales.ts: locale codes, html lang, hreflang, OG locale
- slugMap.ts: EN/NO route table + section anchors, twin-path resolver (the tested contract)
- typed EN/NO dictionaries implementing one interface (missing key = compile error)
- useDict accessor + interpolate helper; no runtime i18n library
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-04 00:54:02 +02:00
cesnimda
9a75f73550
chore: temporary smoke-test home page (replaced in pages milestone)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-04 00:51:16 +02:00
cesnimda
ff27b918ae
chore: scaffold Astro 5 project with token/style layer
...
- Astro 5 static config (trailing-slash canonical, i18n en-root/no-prefixed)
- Tailwind 4 over CSS custom-property tokens (both themes via [data-theme])
- design tokens: colour/spacing/type/radius/motion per Phase 1 specs
- motion layer with reduced-motion overrides
- strict TypeScript, ESLint flat config, Prettier
- self-hosted variable fonts (Space Grotesk / Inter / JetBrains Mono)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-04 00:51:15 +02:00