This is my site — a portfolio and blog, the page you're reading right now. Bilingual, English and Russian: this is where I post projects and notes. All the content lives in a CMS.
Built the whole thing myself: the frontend, the CMS setup and content model, both locales, SEO, and deployment.

Why PayloadCMS
I didn't want WordPress, Drupal or Joomla — I wanted to try something new. Building everything from scratch wasn't an option either: I also wanted some hands-on practice with Next.js and React on the server. While going through the options, I came across PayloadCMS.
I liked its development model: I define custom fields in code, the frontend is Next.js and React, and you can pick the database — MongoDB, SQLite or PostgreSQL. I went with PostgreSQL, for the practice with migrations.
Payload is written in TypeScript, and the types are generated straight from the schema — which makes refactoring safer. The frontend stays entirely mine: Payload serves the data, Next.js renders it.
Deploy and hosting
Everything runs on my VPS, in docker-compose. There are a few services: a container with the CMS itself (Next.js together with Payload) and a separate one with the PostgreSQL database. Cloudflare sits in front of the site — CDN and static caching.
A separate image is built for migrations. The production build is a compiled standalone Next.js bundle: lightweight, without the source or dev tooling, only what the running site needs. You can't run schema migrations from it, so a second image is built from the same Dockerfile — with the full code and dependencies. On release it applies migrations (payload migrate) before the new version of the app comes up. I also use it to run one-off scripts when I need to fix content directly.
Payload now holds everything: blog posts, portfolio projects, contacts. I tailored the admin panel to suit me as well.
Tech stack
- Frontend: Next.js 16 (App Router), React 19 Server Components, Tailwind CSS 4
- Backend and CMS: PayloadCMS 3 (Next.js + TypeScript), PostgreSQL
- Hosting: VPS, Docker Compose
- CDN and edge: Cloudflare
- Email: contact-form messages over SMTP (Brevo)
- Editor: Lexical in Payload — visual, not raw Markdown



