How I built my microservices portfolio website stack

Introduction
harrytang.xyz is my personal website, but I did not want it to be only a static online CV. I wanted to build a small real-world platform that shows how I design, develop, deploy, and maintain web applications.
This microservices portfolio is built with Next.js for the frontend, Strapi CMS for content management, Remark42 comments for discussion, Algolia search for article discovery, and Kubernetes GitOps for deployment. It is a compact project, but it includes many of the same ideas I use in production systems: separated services, typed data fetching, SEO, cache invalidation, container images, environment-based configuration, and automated deployment.
Architecture
The project is split into several services and workspaces:
- web - the public Next.js application.
- headless - the content backend.
- remark - Remark42 email templates and comment configuration.
- infra - Kubernetes, Kustomize, Gateway API, Sealed Secrets, and Flux GitOps manifests.
The idea is simple: each part has a clear responsibility. Next.js renders the website, the CMS manages content, Remark42 comments handle discussions, Algolia search makes articles easier to find, and GitOps keeps deployments reproducible.
This microservices portfolio is small enough to understand quickly, but complete enough to demonstrate how different services communicate in a practical application.
Frontend with Next.js
The Next.js application is responsible for all public pages, including Home, About, Articles, Projects, Expertise, Gear, Search, and dynamic CMS pages. It uses the App Router, TypeScript, Tailwind CSS, reusable components, and server-side data fetching from the backend.
The frontend is not only rendering content. It also handles dynamic metadata, Open Graph data, Twitter cards, canonical URLs, sitemap generation, robots.txt, and JSON-LD structured data. For example, blog pages generate article schema, the home page generates profile schema, and article lists generate item list schema.
This is important because a microservices portfolio should not only look good. It should also be readable by search engines, social platforms, and automated tools.
Content management with Strapi CMS
Strapi CMS is the content backbone of the project. I created content types for blog posts, pages, projects, profile, work history, skills, and gear. This means I can update most of the website from the CMS instead of changing source code.
For me, this microservices portfolio is also a practical way to show how content modeling and frontend rendering work together.
The Strapi CMS schema also includes a shared SEO component. It stores meta titles, meta descriptions, meta images, social metadata, keywords, canonical URLs, and structured data. This keeps SEO fields close to the content and makes publishing more consistent.
The project uses Strapi plugins for SEO, GraphQL, i18n, users and permissions, email, and S3-compatible uploads. It also supports different database backends through environment variables, which makes it easier to move between local development, staging, and production.
Articles, comments, and search
The article system is one of the most important parts of this microservices portfolio. Blog posts are managed in the CMS, fetched by the Next.js frontend, rendered with metadata, and listed with pagination. Individual article pages support media, markdown-style content, code highlighting, social sharing, and related content.
Remark42 comments add a self-hosted comment system. I like this approach because the discussion layer is separate from the frontend and can be deployed as its own service. The comment component also follows the site theme, so Remark42 comments work properly in both light and dark mode.
Algolia search makes the article archive easier to use. Articles from Strapi CMS are converted into Algolia records with title, description, image, keywords, and dates. The frontend uses a search modal with highlighted results and avoids sending empty queries. This keeps Algolia search useful without making the interface noisy.
The current indexing flow is handled by the Next.js revalidation endpoint when Strapi sends content events. This keeps article search updates close to the publishing workflow instead of relying on a separate manual script.
Together, Strapi CMS, Remark42 comments, and Algolia search turn the website from a simple portfolio into a small publishing platform.
Cache invalidation and publishing flow
One challenge with a CMS-driven Next.js site is keeping pages fast while still updating content quickly. To solve this, the project includes an authenticated revalidation API route.
When Strapi CMS sends a create or update event, Next.js can revalidate static paths and cache tags. Blog updates can also update Algolia search records and purge Cloudflare cache. This keeps the microservices portfolio fast for visitors while still giving me a practical publishing workflow.
The result is a good balance: pages can be cached aggressively, but content changes can still reach the public website without a full redeploy.
Deployment and GitOps
The project can run locally with Docker Compose, while the production deployment is handled separately through Kubernetes manifests.
For production, the infrastructure is managed with Kubernetes and GitOps. The infra workspace includes Kustomize base manifests and separate overlays for staging and production. It also includes Gateway API routes, ConfigMaps, Sealed Secrets, persistent volumes, Flux image automation, and Slack alerts.
The Next.js and Strapi CMS services use multi-stage Docker builds. The Next.js container runs as a non-root user, and the Kubernetes deployment stores Next.js build data in a persistent volume. Remark42 comments also use persistent storage so discussion data is not lost between deployments.
This GitOps setup shows how I think about infrastructure: configuration should be versioned, environment-specific changes should be clear, and deployment should be repeatable.
Testing and quality
I added tests because this microservices portfolio is also a demonstration of engineering discipline. The Next.js application has Jest tests for data helpers, components, metadata generation, pagination, Cloudflare cache purging, revalidation logic, markdown rendering, and theme behavior.
There are also Playwright tests for key pages, navigation, blog pages, metadata endpoints, sitemap.xml, robots.txt, and gallery behavior. These tests help make sure the site still works after changes to content fetching, routing, or UI components.
The project also uses TypeScript, Biome, Renovate, Docker builds, and CI-friendly scripts. These tools keep the codebase maintainable as the website grows.
Skills demonstrated
This project showcases several skills:
- Next.js application architecture with the App Router.
- Strapi CMS modeling and API integration.
- Technical SEO with metadata, Open Graph, sitemap, robots.txt, and JSON-LD.
- Remark42 comments integration and theme-aware script loading.
- Algolia search indexing and React InstantSearch UI.
- Docker and multi-stage container builds.
- Kubernetes deployment with Kustomize and Gateway API.
- GitOps automation with Flux, image policies, and Sealed Secrets.
- Cloudflare cache management.
- Jest and Playwright testing.
- Environment-based configuration for staging and production.
Conclusion
harrytang.xyz is more than a place to list my experience. It is also a working example of the kind of systems I like to build: practical, automated, content-friendly, and easy to operate.
This microservices portfolio combines frontend development, backend content modeling, search, comments, caching, deployment automation, and testing in one project. It gives visitors a normal website experience, but behind the scenes it shows my full-stack and DevOps skills in a way a simple CV cannot.
That is why I treat the project as a living microservices portfolio instead of a one-time portfolio page.
If you are building your own portfolio, I recommend treating it like a real product. A personal website can be much more than a profile page. It can become proof of how you think, how you build, and how you keep improving your engineering workflow.
If you found this useful, you can buy me a coffee! Thanks for the support!