Files
dzanan.net/Claude outputs/2026-09-06-dark-technical-redesign-design.md
amar.dzanan 4d754f33c1
All checks were successful
Deploy dzanan.net / deploy (push) Successful in 1m0s
redesign complete
2026-09-06 22:16:19 +02:00

9.2 KiB
Raw Permalink Blame History

dzanan.net — "Dark & technical" redesign

Date: 2026-09-06 · Status: approved by Amar (direction C of three mockups)

Goal

Replace the current warm/editorial design of dzanan.net with the "Dark & technical" direction: near-black surfaces with a faint grid, monospace labels, a terminal-style profile panel, and a single glowing green accent. The site serves both employers and consulting clients equally. The CV becomes a PDF that Amar provides; the site links to it.

Non-goals: new content for the case studies (text stays), a light theme, a CMS, new routes.

Scope

Kept: Angular 22 app structure, SSR + prerendering, SeoService, PageShellComponent (restyled), landing page, four /work/* case-study pages, SystemDiagramComponent (recoloured), not-found page, Tailwind v4 install, Docker deploy.

Removed: CvPageComponent + its spec, ThemeService, ThemeToggleComponent, the theme bootstrap script in src/index.html, the cv client route, the cv prerender route.

Added: public/cv.pdf (placeholder until Amar supplies the file), a 301 from /cv to /cv.pdf in src/server.ts, self-hosted fonts.

Visual system

Defined as CSS custom properties on :root in src/styles.scss; no .dark variant.

token value use
--bg #0D1015 page background
--panel #12161D cards, list panel, code panel
--panel-2 #0F1318 panel headers / inset
--line #232A33 borders, dividers
--line-strong #2A323D tag borders, button outline
--text #E6EAF0 primary text
--muted #8B95A5 secondary text
--dim #5C6672 tertiary text, comments
--accent #8BE04A labels, links, primary button, status dot
--accent-glow rgba(139,224,74,.22) button and dot glow
--code-key / --code-str / --code-num #7AA2F7 / #C3E88D / #F78C6C profile.json panel

Grid: linear-gradient lines at 2.8% white, 64px cell, fixed to the page background.

Type: JetBrains Mono (labels, nav, meta, code, buttons) and IBM Plex Sans (headings and body), self-hosted via @fontsource-variable/jetbrains-mono and @fontsource/ibm-plex-sans (weights 400/500/600) imported in styles.scss. Fallbacks: Consolas/Menlo/monospace and "Segoe UI"/system-ui/sans-serif. Base body 16px; headline scale clamp(2.4rem, 5vw, 3.9rem) for h1, clamp(1.75rem, 3vw, 2.1rem) for h2, letter-spacing -0.03em/-0.025em, weight 600.

Labels (.label): mono, 12px, uppercase, 0.08em tracking, accent colour, prefixed with // in markup (e.g. // selected work). Tags (.tag): mono 12px, 24px tall, 1px --line-strong border, 4px radius. Panels (.panel): --panel fill, 1px --line border, 10px radius. Buttons: 46px tall, 6px radius, mono 14px; .btn-accent accent fill with dark text and glow, .btn-line outlined.

Container: .shell = min(1160px, 100% - 40px) centred. Section spacing 96px desktop, 64px below 720px.

Pages

Header: sticky, --bg at 92% with blur, bottom border. Left: mono wordmark ~/ (accent)

  • dzanan.net (600). Right (desktop): mono nav work · experience · contact · cv.pdf, then a divider and the status ● available (accent dot with glow). cv.pdf is an <a href="/cv.pdf"> with a download icon, opens in a new tab. Below 720px the nav collapses to the existing signal-driven menu button; the status stays visible.

Navigation config: [{work,'/',#work},{experience,'/',#experience},{contact,'/',#contact}] plus the CV link rendered separately as a plain anchor (not a SectionNavItem).

Footer: mono 12px, Amar Džanan · Sarajevo, Bosnia and Herzegovina left; email and LinkedIn right.

Landing (/)

  1. Hero — two columns (1.05fr / .95fr, 64px gap), stacks below 1024px. Left: label Senior full-stack engineer — .NET · Angular · MCP; h1 "Complex systems, understood before changed."; lead paragraph "I modernize enterprise software and connect it to AI through narrow, validated, verified interfaces — the kind you can run in production and sleep at night."; buttons amar@dzanan.net (accent, mailto) and cv.pdf (outline, download). Right: profile.json terminal panel — title bar with three dots and file name, then a $ whoami --json line and a JSON object: name, role, stack [".NET","Angular", "TypeScript"], focus ["modernization","safe AI integration"], since 2018, location "Sarajevo · CET", open_to ["senior roles","consulting"], closing prompt with a blinking cursor. Rendered from a small typed data structure in the component so it can change without touching markup.
  2. // selected work (#work) — heading "Production systems, anonymized." and a right-aligned mono count 4 case studies. One .panel containing four rows (data-testid="project-row", routerLink to /work/<slug>): index (accent on the featured first row), title + one-line summary (a new short tagline field on PortfolioProject, ~60 chars), up to four stack tags (first four of stack), arrow. Hover: row background --panel-2, arrow turns accent. Below 720px: grid collapses to index+title, tagline, tags stacked.
  3. // experience (#experience) — grid 340px / 1fr. Left: 96px square grayscale portrait (NgOptimizedImage, 8px radius, 1px border), label, h2 "Eight years, one product at a time.", about paragraph, LinkedIn link. Right: four role rows (period mono 2025 — now, title + company, focus sentence), 1px dividers.
  4. // capabilities — three equal .panel cards: 01 System modernization, 02 Full-stack product delivery, 03 Safe AI integration, each with the existing detail text. Single column below 720px.
  5. Contact (#contact) — a .panel with a 1px accent-tinted border and inner glow: label // contact, h2 "Need a senior engineer who can understand the system before changing it?", .btn-accent mailto button, mono Sarajevo · CET / CEST.

Structured data (schema.org Person) unchanged.

Case study (/work/:slug)

Breadcrumb as a path: ~/work/ (dim) + slug (text), mono. Header: label <category> · <period>, h1 title, lead summary, then a meta strip in a .panel: role, period, stack tags. Sections keep content; labels become // 01 context, // 02 delivery, // 03 architecture, // 04 result; contributions as a numbered list with mono indices; decisions as a 2×2 .panel grid (single column < 720px); technology as a tag row. SystemDiagramComponent stays, recoloured: node fill --panel, stroke --line-strong, accent node stroke/text --accent, lines --line-strong, notes --dim, mono text. Prev/next as two .panel links. Contact block reused. The "View full CV" link points to /cv.pdf.

Not found

Terminal panel: $ open <path> then command not found: <path> in --code-num, a short sentence, and a .btn-line back to /. Server still returns 404.

Behaviour

  • Motion: hero children fade-up (opacity 0→1, translateY 12px→0, 480ms, 80ms stagger) once on load; cursor blink 1s step; row hover transitions 150ms. All wrapped in @media (prefers-reduced-motion: no-preference).
  • Smooth anchor scrolling with scroll-padding-top for the sticky header (kept).
  • Focus rings: 2px accent outline, 3px offset.
  • <meta name="theme-color"> → #0D1015; color-scheme: dark.

Server

src/server.ts: before the Angular handler, app.get('/cv', (_, res) => res.redirect(301, '/cv.pdf')). public/cv.pdf is served by the existing static middleware. Until Amar supplies the file, a one-page placeholder PDF saying "CV coming soon — amar@dzanan.net" is committed so the link never 404s. public/sitemap.xml drops /cv.

Files

Modified: styles.scss, index.html, server.ts, app.ts, app.routes.ts, app.routes.server.ts, app.routes.spec.ts, page-shell.component.ts, navigation.config.ts, landing-page.component.ts + spec, portfolio-page.component.ts

  • spec, system-diagram.component.ts, not-found-page.component.ts, portfolio-project.model.ts, portfolio-projects.data.ts, public/sitemap.xml, package.json/lock (fontsource packages).

Removed: features/cv/cv-page.component.ts, features/cv/cv-page.component.spec.ts, core/services/theme.service.ts, shared/ui/theme-toggle/theme-toggle.component.ts.

Added: public/cv.pdf (placeholder), this spec, the implementation plan.

Testing

  • Unit: route spec lists routes without cv; landing spec asserts the new h1, four project rows, a[href="/cv.pdf"], mailto and LinkedIn links, the four role titles; portfolio spec unchanged in intent; new not-found assertion optional. Run with headless Chromium.
  • Build: ng build (production, SSR, prerender of / and the four work pages) with zero errors and within budgets (component styles are inline SCSS; keep under 8kB each).
  • Visual: serve dist and screenshot /, one case study and /404 at 1440px and 390px; fix wrapping, overflow and contrast issues found.
  • Smoke: curl -I /cv → 301 to /cv.pdf; /cv.pdf → 200.

Delivery

Work happens in the cloud copy of the repo; changed and new files are written back to the dzanan.net folder on Amar's machine, removed files are moved into _to_delete/. Amar runs npm install locally afterwards (new font packages) and drops the real PDF over public/cv.pdf.