The link preview was a plain white screenshot of the hero. It is still
rendered from the real hero, so it cannot drift from the site, but now as
light type on the dark surface with a lit frame and binary digits coming
off its edge. The digits are seeded, so every run gives the same picture.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On a phone the homepage was about 29 screens long; it is now about 22.
The desktop layout is unchanged to the pixel.
Lists of equal items (automation notes, project fit, principles, reasons for
a web presentation, by hand vs. automated) are swiped through side by side
(SwipeRow) instead of stacked. The four service cards form a compact 2x2
grid, step lists spell out only the current step, the workflow legend and
the per-project task lists are left out, and sections use less padding.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Since the German version the legal pages live at /impressum and /datenschutz
and under /en/imprint and /en/privacy. The smoke test still expected
/imprint and /privacy to answer 200 and /impressum to redirect, so it has
been red on every deploy while the site was fine. A check that is always red
no longer shows a real outage.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A presentation built as a website instead of a slide file: why, for what,
and when slides are enough. The main drawing shows the same presentation as
a slide and as a web page on a projector, a laptop and a phone; the slide
keeps its format and shrinks, the page rearranges. Four small drawings stand
next to the reasons. No prices: none are agreed for this yet.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On a phone the headline was built from 4px cells and the background field
kept its desktop ink, so the digits were specks or not visible at all. The
headline now uses cells of at least 6px there, and the background digits are
larger and stronger below 640px.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The pulsing dashed rings around the example workflow read as a second,
broken frame. The panel now sheds a few digits at its left edge like the
other frames on light backgrounds, and the ring motion, which nothing else
used, is removed from BitAura.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The address is the one thing to act on in the contact section, but it was a
plain underlined line next to a glowing message card. A slow sheen now runs
through the letters and a light travels along the underline; on hover the
whole line lights up.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings the German main language (English under /en), the binary glow
effects with the refined drawings and calls to action, and the search
metadata onto the server-side analytics from v2.1.0.
Both sides had added apps/web/proxy.ts. It is now one request shell: it
picks the language and maps the address (routes.ts), and records the page
view server-side (pageview-decision.ts) for every request that is not a
redirect, using the public address the visitor asked for. The browser
analytics component and the /stats proxy route stay removed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The site now exists in German (at the root, with /impressum and /datenschutz)
and English (/en). A request without a language follows the visitor's choice
from the language switch, then the browser language, then German; the old
English legal addresses move to /en for good.
All visible texts are data in src/content/de.ts and en.ts, so components hold
none of their own. The header carries a DE/EN switch whose bit curtain covers
the page while it is swapped and reopens at the same reading position. Title,
description, canonical, hreflang, Open Graph, the share image, the sitemap and
the structured data are per language. The privacy notice now describes the
cookie that remembers the chosen language.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Dark surfaces now carry light: frames glow along their edge and shed binary
digits (BitAura), dark sections open with a lit seam (BitSeam), the career
path is a line of light and "My work" became a dark stage. Buttons carry a
travelling light and a spot that follows the pointer (BitGlow).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only the production deployment may be indexed; testing and preview builds
answer with noindex and a closed robots file. The homepage now describes the
person, the services and the FAQ as structured data, and title, description
and the 404 page are written for what people search for.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Next.js strips the router-internal headers (RSC, next-router-prefetch)
before the request proxy runs, so prefetch detection based on them never
fired: link prefetches were counted as page views. A page view is now a
browser navigation, identified by the standard sec-fetch-dest: document
header, which survives into the proxy. Prefetch payloads, subresource
fetches and metadata-less clients are skipped as non-navigation
requests.
Umami never received data: the client-side path (browser beacon to
/stats/api/send) has been dead in production. Pageviews are now
classified and recorded entirely on the server in the request proxy;
no tracking script ships to the browser anymore.
- Pure domain decision (decidePageview) filters real page views from
assets, infrastructure paths, prefetches and bot user agents
- Pure payload builder maps facts onto the Umami send contract as an
unnamed event, with the client identity travelling in headers
- proxy.ts wires request facts into the domain and fires the send
without delaying the response; configured via UMAMI_WEBSITE_ID and
UMAMI_API_ENDPOINT
- Removes the dead client analytics stack (components, adapters,
/stats proxy route) and its layout mount
The visitor picks what they need and a prepared email types itself out; one
press opens it in their own mail app with subject and body filled in. The
mailto link is built by a tested pure function (src/domain/email.ts, spec
first) and only in the browser, so the address still never appears in the
page source.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Section headlines are written out behind a column of digits, mono labels
resolve from binary, the portrait assembles itself from bits, section indexes
rattle and keep one bit alive, cards get corner marks, the header shows the
scroll position as an eight-bit number, pressed links and buttons shed a few
digits, and the work stage leans towards the pointer. All effects respect
reduced motion and leave the content readable without JavaScript.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The link preview used an old template with a blog description. The share
image is now a screenshot of the real hero (scripts/render-share-image.mjs),
served as Open Graph and Twitter image. Title and description come from one
place and are used by the page, the previews and the structured data. Adds an
apple touch icon and removes the old share-image template and its fonts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The site now presents one freelance developer on one page: hero, introduction,
four typical cases (developer for a product, make an app reliable, automate a
process, a website) with what you get, how it runs and what it costs, a
process automation section, technology and project fit, how I work, two live
references, questions and contact.
- Hero and closing headline are drawn from running binary digits.
- Each case explains its four steps with an animated drawing; the automation
section shows example workflows with work travelling between systems; a
pipeline run shows what a test catches before a release.
- Contact is one email address, kept in parts and assembled in the browser so
it never appears in the page source (src/domain/email.ts, spec first).
- Imprint and privacy pages added.
- The old site (blog, case studies, contact form, fixed-price pages, video
rendering and related scripts) is removed. Its URLs redirect to the homepage.
- The deploy smoke test checks the legal pages and the redirects instead of
the removed case study.
- Dev scripts use docker compose v2.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds dark design tokens, Inter + JetBrains Mono, a header with Notes,
Process, About and a Book a call button, and a footer with the availability
line driven by the tested domain core. Shared primitives live in
src/components/site, site constants in src/content/site.ts. Legacy pages
(blog, legal, contact, tags, technologies) keep a light surface via
LegacyLightSurface. Stub routes for /notes, /process and /book.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The shared base tsconfig had strict off, so null-safety and union narrowing
were not checked. Strict is now on for apps/web with 5 small typing fixes.
check-db.ts and migrate-drafts.js depended on Payload, which is no longer a
dependency, and are removed. CLAUDE.md no longer claims Payload.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
CLAUDE.md documents commands, the spec-first workflow, the functional-core
rule and a do-not list. A Claude Code Stop hook blocks finishing while
typecheck or unit tests fail. Permissions deny reading env files, hook
bypass flags, hard resets and recursive deletes, and ask before CI edits
or any push. Husky pre-commit now also typechecks and runs unit tests;
pre-push runs coverage and the mutation gate when src/domain changed.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Pure logic lives in apps/web/src/domain and must stay at 100% coverage and a
100% mutation score. The first unit is the availability logic for the hero:
parsing, resolving and formatting the next free capacity block.
Vitest is pinned to 4.1.11 because @stryker-mutator/vitest-runner 10.0.0
runs zero tests per mutant under vitest 5 and reports surviving mutants.
ESLint now ignores Stryker, coverage and report output.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Posts.ts.tmp, tmp.txt, wget_out.txt, build logs, a debug HTML dump and a
generated markdown output were tracked but unreferenced. tmp_posts.json is
kept because scripts/extract-to-mdx.js still reads it.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Defines positioning, site structure, offers and pricing, and implementation
order for repositioning the site from fixed-price websites to a senior
freelance engineer offering weekly capacity blocks.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>