Why I Built My Portfolio with Bun + Astro + MDX Instead of a More Complex Stack

I built a bilingual portfolio using Bun, Astro, and MDX to keep the stack minimal, fast, and fully version‑controlled. The choice was driven by concrete needs: static content, SEO, accessibility, and easy maintenance. The result is a site that builds in seconds, serves pure HTML, and enforces bilin…

When I started planning my new portfolio, I knew I needed a site that could showcase my work in both Portuguese and English, present projects and articles with their own identities, and do so with solid SEO and performance. I also wanted a maintenance model that would never require me to think twice about deployments or infrastructure costs. The question that guided every decision was simple: what is the simplest solution that can solve this problem?

Choosing the Right Toolchain

The first decision was to pick a toolchain that would handle everything from package management to runtime validation. I settled on Bun for its single‑purpose design: it runs TypeScript scripts directly, eliminates a separate transpilation step, and serves as the runtime for development scripts, builds, and validation checks. In my local environment, a full build renders every page in roughly two seconds, a performance that speaks to the tool’s efficiency.

Next, I chose Astro because the site is predominantly static. Astro generates HTML at build time, so every page is served as a pre‑rendered file without any application server or database. This model removes unnecessary JavaScript from the browser; the only script on the home page is a 277‑byte menu controller, and no client‑side framework is loaded. The result is a lean, SEO‑friendly site where each page arrives with its own canonical URL and language alternates.

For content, I used MDX. Articles and project cases live in the same repository, versioned alongside code, and go through the same review process. MDX allows me to embed React components in Markdown while keeping the content in plain files. Each piece of writing is validated via frontmatter that requires a bilingual pair, slug, category, and review status. Publishing is simply merging and building; rolling back is reverting a commit.

Bilingualism as Architecture

Bilingualism was not an afterthought; it shaped the entire architecture. Portuguese content lives under / and English under /en/. Every published item must exist in both languages, and the build process rejects any item lacking a reviewed counterpart. Each page carries its own canonical link and three alternates: the current language, the opposite language, and x-default. Drafts are excluded from the production build and only appear in a preview build, ensuring incomplete content never reaches users.

Because the system enforces bilingual pairs, I can guarantee consistency across languages. This double‑review process is a deliberate cost, but it is essential for the international reach I aim to achieve.

Quality Through Automation

Quality is baked into the pipeline. Every change undergoes strict type‑checking, linting, formatting, and unit tests for the publication model. I also run thirteen browser tests that cover reciprocal navigation between languages, keyboard‑only menu access, no‑JavaScript navigation, localized 404 pages, external link handling, and a 320px viewport reflow with automated WCAG checks. Artifact validation runs in both build modes, catching broken links or missing language pairs before deployment.

CI/CD is handled by GitHub Actions, which covers type checking, linting, unit tests, Playwright end‑to‑end tests, artifact validation, and production builds. The same CI‑approved artifact is deployed to a dedicated production branch and then pushed to Hostinger after explicit manual approval, following a Continuous Delivery model.

Performance in the Lab

I ran Lighthouse 13.4.1 in headless Chromium with mobile simulation (412×823 viewport, throttled network and CPU) for three runs per page. On the home page, performance and accessibility scores were 100 across all runs. Largest Contentful Paint (LCP) hovered between 1.5 s and 1.7 s, cumulative layout shift (CLS) was 0.0006, total blocking time (TBT) was zero, and the initial transfer size was about 93.5 KB. The lightness comes from roughly 6 KB of gzipped CSS, 0.2 KB of inline JavaScript, and 48 KB of fonts.

These lab numbers inform decisions but do not represent real‑user data. I never present them as such, and I acknowledge that the true user experience may differ.

Lessons Learned and Trade‑offs

Every choice carries a cost. By opting for a purely static site, I eliminated the need for a backend, database, or CMS. New content requires a commit, a build, and a deploy. I also forego React at launch, meaning richer interactivity will require a future rewrite. Analytics are absent, so I rely solely on lab metrics. Bilingualism doubles the review effort, but it is a deliberate investment in consistency and reach.

Ultimately, mature engineering is about matching complexity to the problem. A full‑stack monolith, SPA, or CMS could have worked, but they would introduce unnecessary capabilities and operational costs. By starting from the human problem—creating a maintainable, bilingual portfolio—I chose a stack that is simple, fast, and fully version‑controlled.

Why it matters

Choosing the right stack can mean the difference between a site that is easy to maintain and one that drags on with unnecessary complexity. This article shows how a focused, minimal approach can deliver performance, SEO, and bilingual support without the overhead of a full‑stack framework.

Key points

  • Bun unifies package management, runtime, and tooling, eliminating extra transpilation steps.
  • Astro’s static‑site generation keeps JavaScript minimal, improving load times and SEO.
  • MDX allows version‑controlled content with schema‑validated frontmatter, ensuring bilingual consistency.
  • A strict CI/CD pipeline enforces type safety, linting, testing, and artifact validation before deployment.
  • Performance metrics demonstrate that a lean stack can achieve top Lighthouse scores.
  • Trade‑offs include no backend, no analytics, and doubled review effort for bilingual content.

Frequently asked questions

Why not use a CMS like WordPress?

A CMS would add an external dependency, require logins, backups, and a bill, all of which add complexity that the project does not need.

Can I add more interactivity later?

Yes, but it would require revisiting the decision to avoid React at launch and potentially integrating a client‑side framework.

How do I deploy updates?

After passing all CI checks, the same artifact is manually approved and pushed to the production branch, then deployed to Hostinger.

Reporting drawn from

More from World

Felo News, House 42, Bridge Colony, Kot Lakhpat, Lahore, Pakistan
+92 308 4354717 · felopronews@gmail.com