Skip to content
albert.gorgori
Engineering

Decisions, not technology names

A list of technologies says what was used. A decision record says what the problem was, what else was considered, why those were rejected, and what was accepted as a consequence — including the parts that hurt.

Decision records

6 decisions

  • typed-tool-registryportfolio-mcp · 2026-09

    A typed tool registry between any model and the data

    Problem

    An MCP client — someone else's agent, running on someone else's machine — needs to read portfolio content. The naive shapes, giving it a query interface or handing over the whole dataset, both make the caller responsible for correctness of access.

    Constraints
    • The model must never be able to widen its own read scope.
    • The same capabilities must serve MCP clients and any future transport.
    • Adding a capability should be one file change, not a change per transport.
    Considered and rejected
    • Whole dataset in the system prompt

      Works at this size and fails at any other. It also removes every observation point: no per-capability latency, no tool-selection metric, no authorization seam.

    • A generic query or SQL tool

      Maximum expressiveness for the model is maximum blast radius. It moves domain logic into generated queries, which is exactly where it cannot be tested.

    • Framework-managed tools (AI SDK primitives)

      Couples the tool contract to one client library, when the contract has to be served over MCP to clients I do not control.

    Decision

    One registry of named tools. Each declares a description, a Zod input schema, an access level and a handler. Transports adapt to the registry; the registry knows nothing about transports.

    Reasoning
    • A Zod schema per tool turns model output into a parse step with a defined failure mode.
    • An access level per tool makes authorization a property of the capability rather than a rule in a prompt.
    • Transport independence is what makes the MCP endpoint a thin adapter rather than a second implementation.
    • Named, described tools are what a calling model actually selects between — the description is part of the contract.
    What this bought
    • The model orchestrates capabilities and never formulates a read.
    • Each call is independently measurable — latency, outcome and argument validity.
    • A new capability is one registry entry, available to every transport at once.
    What it cost
    • The model can only answer what a tool exposes; unanticipated questions need a new tool.
    • More ceremony than passing a JSON blob to the prompt — the cost is paid up front.
  • mcp-handrolled-jsonrpcportfolio-mcp · 2026-09

    Hand-roll the MCP JSON-RPC subset instead of adding the SDK

    Problem

    Exposing the portfolio over MCP needs initialize, tools/list and tools/call. The MCP SDK targets stdio and long-lived sessions; this endpoint is a stateless route handler on a static-first deployment.

    Constraints
    • The route must stay stateless and edge-friendly.
    • tools/list must be generated from the same Zod schemas the tools already declare.
    Considered and rejected
    • The official MCP SDK

      Session and transport machinery this deployment does not have, to implement three methods whose wire format is fully specified.

    • No MCP endpoint at all

      Removes the part of the claim that is actually checkable by a reader.

    Decision

    Implement the JSON-RPC 2.0 subset directly in a route handler, generating JSON Schema for tools/list from the registry's Zod schemas.

    Reasoning
    • Three methods of a published spec is less code than the adapter that would wrap the SDK.
    • One registry stays the single source of truth, and JSON Schema is generated from the Zod schemas that actually run.
    • Stateless request/response matches how the site is deployed.
    What this bought
    • A real, connectable endpoint with no new runtime dependency.
    • Schema drift between validation and the published contract is structurally impossible.
    What it cost
    • Only the implemented subset is supported — no resources, prompts, or notifications.
    • Spec changes are mine to track.
  • server-components-defaultportfolio-mcp · 2026-09

    Server Components by default, client islands by exception

    Problem

    A portfolio arguing for engineering quality has to be fast, and the usual failure is shipping an interactive framework to render static prose.

    Constraints
    • Content pages must be prerendered and require no client JavaScript to read.
    • Only one surface genuinely needs interactivity: the theme toggle.
    Considered and rejected
    • Client-side app shell

      Pays hydration cost on every page to serve interactivity that one component needs.

    Decision

    Every route is a Server Component and statically prerendered. Interactivity is isolated to a named client island; the MCP route handler is the only dynamic endpoint.

    Reasoning
    • Reading the site should cost a document, not a bundle.
    • Isolating client code makes the interactive surface auditable at a glance.
    What this bought
    • Static HTML for all content routes; JavaScript is scoped to real interaction.
    What it cost
    • Interactive state cannot be lifted casually — crossing the boundary is a deliberate act.
  • static-data-modulesportfolio-mcp · 2026-09

    Typed modules as the content store, not a database

    Problem

    Portfolio content needs a home that both the pages and the MCP tools read from.

    Constraints
    • Content changes at the speed of a git commit.
    • Invalid content should fail loudly and early.
    Considered and rejected
    • A CMS or database

      Operational surface, latency and a runtime dependency for data that changes a few times a year and is already reviewed in pull requests.

    • Markdown with frontmatter

      Weaker typing at exactly the boundary a caller reads across; the structure is relational, not prose.

    Decision

    TypeScript modules parsed through Zod at module load, read by a thin query layer.

    Reasoning
    • Content errors become build failures.
    • The whole site prerenders, so reads cost nothing at runtime.
    • The query layer is the seam to move behind a database later, if that day comes.
    What this bought
    • Type safety end to end; zero runtime data dependency; trivially cacheable.
    What it cost
    • Editing content requires a deploy, and there is no non-technical editing path.
  • css-variable-themingportfolio-mcp · 2026-09

    Theme with CSS custom properties, not dark: variants

    Problem

    The site needs light and dark themes that respect the system setting and an explicit toggle, without a flash of the wrong theme.

    Constraints
    • The toggle must beat the system preference in both directions.
    • No colour may be defined only inside a media query.
    Considered and rejected
    • dark: utility variants throughout

      Doubles every colour decision at each call site and scatters the palette across the codebase.

    Decision

    One token set on :root, redefined under prefers-color-scheme for untouched visitors and under [data-theme] for an explicit choice. Components reference semantic tokens only.

    Reasoning
    • The palette lives in one file and components never name a colour.
    • A tiny inline script applies the stored choice before paint, so there is no flash.
    What this bought
    • Single source of truth for colour; both themes stay correct by construction.
    What it cost
    • Per-component theme overrides are deliberately awkward.
  • zustand-client-stateathlio · 2025

    Zustand for interactive client state

    Problem

    Global client state was required for an interactive training UI — state shared across routes and components, distinct from server data.

    Constraints
    • Server state is already owned by the data layer; this is application state only.
    • TypeScript ergonomics matter more than ecosystem size at this scale.
    Considered and rejected
    • Redux Toolkit

      Ceremony out of proportion to the amount of state involved.

    • React Context

      Re-render behaviour degrades as the shared state grows.

    • Jotai

      Atomic model is a good fit, but the store model matched how this state is used.

    Decision

    Zustand.

    Reasoning
    • Low ceremony and a small API surface.
    • Strong TypeScript ergonomics without generics gymnastics.
    • Appropriate for application state, with server state kept out of the store.
    What this bought
    • Very little boilerplate; selectors keep re-renders contained.
    What it cost
    • Fewer guardrails than Redux — store discipline has to be maintained by convention.
Human + agent

Division of work

Agents write a large share of the code. That changes what the engineering job is, not whether there is one.

Human — me
  • Product
  • Architecture
  • System design
  • Trade-offs
  • Security
  • Code review
  • Final decisions
Agents
  • Implementation
  • Test generation
  • Refactoring
  • Documentation
  • Research
  • Codebase exploration
  • Debugging

My role isn't to write every line of code. It's to design the system that makes the right code get written.

HUMANTASK / PRDORCHESTRATORARCHITECTCODERTESTERREVIEWERGITHUB · CIDEPLOYAGENTSHUMAN
Skills

Banded by how they are used

Core means daily production use. Production means real work, not every day. Learning means no production experience yet — listed as learning rather than claimed.

Frontend

Where most of five years has been spent: component architecture, rendering strategy and the parts of the browser that decide whether an app feels fast.

  • Reactdaily
  • Next.js (App Router)daily
  • TypeScriptdaily
  • Tailwind CSSdaily
  • shadcn/uidaily
  • GraphQL / Apollo Clientproduction
  • Accessibility (WCAG)production

State & data

Choosing the right kind of state for the problem, and keeping server data out of client stores.

  • Zustanddaily
  • React Queryproduction
  • Reduxproduction
  • React Contextdaily

Backend & data layer

APIs, persistence and the boundaries between them.

  • Node.jsdaily
  • Expressproduction
  • PostgreSQLproduction
  • Supabaseproduction
  • MongoDBproduction
  • REST API designdaily

AI & agents

Tool design, orchestration and the boundary work that makes model-driven systems safe to run.

  • LLM APIs (Anthropic)production
  • Tool / function callingproduction
  • Model Context Protocolproduction
  • Agent skillsproduction
  • Structured outputs (Zod)daily
  • Agent evaluationproduction
  • AI SDKproduction

Quality & delivery

Testing, review and the pipeline that carries work to production.

  • Vitest / Jestproduction
  • ESLint / Prettierdaily
  • Git / GitHub Actionsdaily
  • Verceldaily
  • Dockerproduction
  • Code reviewdaily

Microsoft 365

Enterprise platform work from the Avanade and Enzyme years — the context where most 'internal tooling' actually lives.

  • SPFxproduction
  • SharePoint Online / On-Premproduction
  • PnP JSproduction
  • SAPUI5production

Learning now

Honest about what is in progress rather than claimed.

  • React Native (Expo)learning
  • Stripe Connectlearning
Build log

Real commits, read at build time

Git history from this repository. Entries marked agent-assisted carry a co-author trailer written by the tooling at commit time — evidence, not a claim.

  • 2026-09-25feat: update CV and add new skills documentation90b27c0
  • 2025-12-01fix: Update CV files with improved formatting and recent experience details122 files changed, 11005 insertions(+), 2455 deletions(-) 6db53e4
  • 2025-11-03feat: Add Vercel Analytics integration to layout and update dependencies3 files changed, 0 insertions(+), 0 deletions(-) c6c9ab2
  • 2025-11-03fix: Reorder FinWallet entry in SIDE_PROJECTS for consistency3 files changed, 40 insertions(+), 3 deletions(-) 70d9807
  • 2025-11-03fix: Correct date for Athlio Training App in WORKS section1 file changed, 6 insertions(+), 6 deletions(-) 034b69a
  • 2025-11-03feat: Update header to include links and improve navigation1 file changed, 1 insertion(+), 1 deletion(-) 4b4fbce
  • 2025-05-26Scaffolding curriculum pages19 files changed, 180 insertions(+), 40 deletions(-) c4da74e
  • 2025-05-26mobile view5 files changed, 67 insertions(+) de8822b
  • 2025-05-26Adjustments and languages added1 file changed, 2 insertions(+), 2 deletions(-) 426a2b5
  • 2024-12-18last updates16 files changed, 151 insertions(+), 44 deletions(-) 0c9f67c

Source: git log, read at build time. Full history on GitHub