Back to projects

andreiburbulia.com — bilingual portfolio with a custom CMS

This site: Laravel 12 and React 18 through Inertia.js with server-side rendering, bilingual IT/EN content managed from a custom admin panel, images on Cloudflare R2, deployed to a VPS with nginx and systemd.

Tailwind CSSInertia.jsReact.jsJavaScriptPHP 8Laravel+5
andreiburbulia.com — bilingual portfolio with a custom CMS

Description

The site you are reading. Portfolio, technical blog and admin panel built as a single Laravel 12 application with a React 18 front end served through Inertia.js. Every piece of content — projects, work experience, education, skills, articles, messages from the contact form — lives in PostgreSQL and is editable from the admin area in both languages, with no code change and no redeploy. Ten managed entities, 52 React pages, 23 migrations, 69 PHPUnit tests green on GitHub Actions.

The problem

I work on SAP BTP for clients under non-disclosure agreements: the code is not public, screenshots cannot be shared, the client's name cannot be written down. A portfolio made of repository links — the obvious answer for many developers — was not available to me. So the problem was never to build a website: it was to decide what can go into a portfolio when the thing you do best cannot be shown. On top of that, most of the recruiters I am addressing are in Germany, Switzerland and the Netherlands: they read in English and they filter on exact technology names.

Constraints

The non-disclosure agreement applies here too: every project is described by scale and industry, never by name. Bilingualism had to be real rather than a toggle on interface strings — URLs, slugs, meta descriptions, feeds and sitemap all exist in both languages. The infrastructure is a single VPS, with no managed pipeline and no paid CDN. And since a portfolio that needs a deployment to fix one sentence stops being updated after a month, everything that counts as content had to live in the database, not in the code.

Architecture

Before writing the final layout I explored three directions as static HTML pages, still in the repository: technical magazine (serif and monospace, editorial density), dark workshop, terminal (all monospace, a shell prompt instead of a heading). I went with the dark route with magenta and purple accents: the terminal only spoke to people who already resemble me, and the magazine needed an amount of writing I did not have yet.

nginx → PHP-FPM → Laravel 12 → Inertia 2 → React 18 (Vite 7, Tailwind)
                      │              └── SSR: Node as a systemd unit
                      ├── PostgreSQL (translated content in json columns)
                      └── Cloudflare R2 (cover and inline images)
  • translations through spatie/laravel-translatable: one field, one json column, a distinct slug per language and fallback resolution, so a page missing its translation stays reachable;
  • uploads resized to 1600px and converted to WebP before anything is written to the remote disk;
  • a Markdown blog with syntax highlighting, where the public page and the admin live preview share the same rendering component;
  • RSS and sitemap generated from the same routes;
  • 69 PHPUnit tests on in-memory SQLite, plus Pint and an asset build on GitHub Actions.

Outcome

The site has been live at andreiburbulia.com since spring 2026 and keeps changing: I add a project or an article from the admin panel in a few minutes, in two languages, without opening an editor. Server-side rendering means crawlers and social previews see fully composed pages instead of an empty shell. I am not publishing traffic figures: the site is young and they would be noise. What I can say is that this portfolio became the one artefact of my work that a recruiter can actually open and inspect.

Technologies

Tailwind CSSInertia.jsReact.jsJavaScriptPHP 8LaravelLinuxAdministration VPSGitGitHubPostgreSQL