Home
VA.
Back to Projects

This site

Portfolio, studies, documentation and newsletter in one place — bilingual, no CMS, every piece of content versioned in Git.

2 min read

Stack

  • Next.js 16
  • TypeScript
  • Tailwind CSS 4
  • next-intl
  • MDX
  • Vercel

The problem

I had four things scattered around: an outdated portfolio, study notes in a note-taking app, technical documentation in loose files, and the itch to write a newsletter. None of them talked to each other, and keeping four places alive is the fastest way to keep none of them alive.

The idea was simple: one base, four sections, a single publishing flow.

How it works

There's no database and no CMS. Every piece of writing is an .mdx file under content/{locale}/{collection}/. Publishing means creating a file and running git push — Vercel does the rest.

content/
├─ pt/
│  ├─ projects/     ← portfolio
│  ├─ blog/         ← studies
│  ├─ docs/         ← documentation
│  └─ newsletter/   ← issues
└─ en/              ← same structure

A single reading layer (src/lib/content.ts) serves all four collections. It parses frontmatter with gray-matter, sorts, filters drafts and feeds every route's generateStaticParams — which means the whole site is generated statically at build time.

Decisions that paid off

Bilingual content with translated URLs

Route folders stay in English, but the Portuguese URLs are translated by next-intl. A PT reader sees /estudos, an EN reader sees /blog, and there's a single route file behind both. I wrote about this in detail in the blog.

A dark theme with a real toggle

Every colour on the site resolves to one of six CSS variables. Changing the entire visual identity means editing one block, and the light theme comes for free in the same move.

Partial translation doesn't become a 404

If a piece exists in Portuguese but not yet in English, switching languages takes the reader to that section's index instead of an error page. It's a three-line condition in each route, and it solves the most annoying problem of a bilingual site maintained by one person.

What was left out

Email capture, comments, search and analytics. None of them solve a problem I have today — and each one is another external service to keep alive. Once the newsletter has people waiting on it, subscriptions go in.

Tags

  • Next.js
  • MDX
  • i18n