Back to the home page
Developer profile

Rizmajer Máté Levente

Full-stack developer — React and Node.js

I build full-stack web applications, carrying the same work from the interface through the API to the database. Usually the kind of system that turns daily admin into a process that runs on its own — booking, ordering, internal records.

The fixed point in how I work is that a failure has to be loud. Tests, linting and build-time assertions catch what a review does not: on this site, for instance, the build stops if a Hungarian sentence slips onto the English version. Anything that breaks quietly is noticed by a visitor before it is noticed by me.

I am working towards TypeScript and a broader testing practice at the moment, which is why neither appears in the stack below: I do not write production code in them yet. I am open to developer roles and to contract work. If there is a technical detail you want that is not here, write to me; a specific question gets a specific answer.

How I build

Five areas, each with a position and the specifics behind it. What matters is not whether I know the names, but what I decide on when two solutions are both available.

Architecture

The smallest structure that carries the job. I add an abstraction when the second caller appears — before that, an interface with one implementation is not an abstraction, it is an extra file.

  • A fact lives in one place and everything else reads it from there. This site learned that the expensive way: the number of projects lived in four files at once, until one of them rotted into a false claim.
  • Shared decisions — motion timings, route paths, colour tokens, bilingual copy — live in their own modules, so they cannot quietly drift apart.

Frontend

One component per responsibility, shared behaviour in hooks. State lives where it is used, and anything derivable is not stored — the language, for instance, follows from the URL rather than from state.

  • Every asynchronous path has a loading, an error and an empty state, not just the happy one. An empty state is copy too, not a gap where a box should be.
  • Accessibility is not a layer added afterwards: a visible focus indicator on every interactive element, measured contrast rather than assumed contrast, and a static page when the visitor has asked for reduced motion.
  • Responsive work starts at the phone, because that is where most visitors arrive from — not at the wide viewport the developer happens to be sitting in front of.

Backend and data

REST endpoints organised by resource, with predictable status codes and error responses shaped like the successful ones — so the client does not need two ways of reading the same call.

  • Validation runs on the server as well. Checking in the browser is a convenience for the user, not a defence for the system.
  • Authentication and authorisation are two questions, not one: who you are, and what you may reach. Collapsed into a single role field, the second one can never be answered precisely.
  • Choosing the schema is a decision, not a habit: relational where the shape of the data is fixed, document-based where it is not. Changes go through migrations so they stay traceable.

Quality

Quality is not a phase at the end. Lint and tests after every change, and the build itself is a gate: if an assertion fails, nothing is written.

  • Tests describe behaviour, not implementation. Otherwise every refactor surfaces as a test failure, and the suite becomes an obstacle instead of a safety net.
  • The silent failure is the expensive one. Where the choice is between stopping loudly and degrading quietly, I take the stop — the translation helper throws on a missing string rather than falling back to Hungarian on an English page.

Production

Deployment is not the end of the work; it is where the earlier decisions become visible. If it cannot be rolled back or measured, I do not treat it as finished.

  • Security headers and a content security policy, so it is not only the code that limits what may run on the page, but the browser as well.
  • A crawler receives finished HTML, not an empty element for JavaScript to fill in later. That makes search visibility a structural question rather than a keyword one.
  • Configuration lives in environment variables rather than in code, and secrets never reach the browser.

What I work with

Split by what can be verified. Anything running in this repository can be opened and checked; the rest comes from delivered work. No percentage skill levels, because there is nothing behind them.

Frontend

Runs in this repository

  • React 19This site
  • JavaScript (ES modules)This site
  • Vite 8Build and dev server
  • Tailwind CSSToken-driven theme
  • React RouterBilingual routing
  • GSAPScroll and entrance motion

Backend

Runs in this repository

  • Node.jsThe build and prerender run in plain Node

Used in delivered projects

  • ExpressREST endpoints
  • REST APIOrganised by resource
  • JWTSession handling

Data

Used in delivered projects

  • PostgreSQLFixed-shape data, with migrations
  • MongoDBDocuments whose shape varies
  • SupabaseWebWise Studio

Testing and quality

Runs in this repository

  • Vitest138 tests across 21 files
  • Testing LibraryComponent behaviour
  • oxlintBefore every commit

Infrastructure and workflow

Runs in this repository

  • GitA branch per feature, small commits
  • GitHubPublic source
  • VercelDeploys from the main branch
  • npmBuild pipeline

This site, from the inside

The most checkable work I have is the page you are reading. Eight decisions, each with the reason behind it and the file it can be checked in — because a decision without its reason is a feature list, and a reason without a file is a claim.

Prerendered in Node, not in a headless browser

Sections stay transparent until an IntersectionObserver switches them on. Node has no IntersectionObserver, so every section renders fully visible — headless Chrome does have one, so a snapshot would capture everything below the fold as blank. It also keeps a Chromium download out of every deploy.

Source: scripts/prerender.mjs

Language follows from the URL, not from state

With the language held in state the server renders Hungarian into the HTML and hydration then flips it — a visible flash for the reader, and the crawler indexes whatever the server guessed. As a pure function of the path there is nothing to synchronise, and each language gets a real URL that can be linked to.

Source: src/i18n/locales.js

hreflang only where a twin actually exists

The two legal pages stay Hungarian on purpose: translating a binding document does not produce a second version of it, it produces a second document. But an hreflang pointing at a 404 makes a search engine drop the whole language cluster — so the generator checks that the twin exists before writing the tag.

Source: scripts/prerender.mjs

sitemap, robots and llms.txt generated, not hand-written

Maintained by hand, they went stale: llms.txt was publishing a price the pricing module no longer contained. A hand-written side file always lags behind the one thing nobody opens at deploy time. Generated from a single source, there is nothing left to forget.

Source: scripts/generate-static.mjs

Structured data derived, not duplicated

The JSON-LD carried eight FAQ answers copied in by hand, and they drifted: the visible page had the new price while the structured data still had the old one. That is precisely the text a search engine quotes, so the stale copy was the likelier one to be read. The block is now built from the source, leaving no second copy to forget.

Source: scripts/prerender.mjs

The build stops on the silent failures

Every check reports by finding nothing, so a broken checker and a clean page look identical. The build therefore hunts specifically for the failures nobody would notice: a section left transparent, Hungarian text on the English page, structured data left empty, a page title kept in two places. One of the checks exists to verify the checker itself.

Source: scripts/prerender.mjs

A content security policy with no inline script

The script-src allows only same-origin scripts, with no unsafe-inline — so there is nowhere to put a hydration data blob, and the prerender deliberately does not produce one. The constraint shaped the solution rather than being bolted on afterwards.

Source: vercel.json

Self-hosted fonts with a latin-ext subset

A font CDN once answered with a 200 that contained a "temporarily restricted" comment instead of CSS — body text fell back to a system face, with no error anywhere. Local files remove that, and the latin-ext subset removes the other half: the accented Hungarian characters no longer switch to a different face mid-word.

Source: src/fonts.css

Projects

I do not publish links or repositories for client projects: they are live systems holding real customer data. For my own projects I build demos anyone can open, and I am glad to walk through code in a conversation. The first client build is under way — the moment it is live, the link and the screenshot will be here.

Personal project

Business Value Builder

My own pricing page: it models how to quote a nearby business a price whose final total stays predictable up front.

Stack

  • React
  • TanStack Start

Personal project

WebWise Studio

An agency concept site for custom React/AI web applications — a prototype I started myself.

Stack

  • React
  • Supabase
  • Framer Motion

Working together

Three kinds of enquiry reach me, and all three land in the same place. You do not have to decide in advance which one you are — just say what the situation is.

A developer role
Employed or on contract. If your team needs a code sample or a technical conversation before going further, both are available.
Project work
A website or an internal system, at a price agreed up front. The prices and the process are published on the home page.
A technical question
If you only want to ask about a decision or an approach, that gets an answer too — including when nothing comes of it.

Prices and process on the home page