Full-Stack Web Application
Dynamic Dual-Portfolio Website
Über dieses Projekt
Project Overview
This project is the very portfolio you are browsing now. It was conceived as a "hub-and-spoke" platform to professionally showcase two distinct skill sets—software development and photography—under a single, cohesive brand. The architecture is a modern monorepo containing a headless Strapi backend and a multi-domain Next.js frontend.
Core Features
- Multi-Domain Routing: The application intelligently serves different content based on the domain name (
codeby.joeldettinger.defor software,photosby.joeldettinger.defor photography) using Next.js Middleware. - Headless CMS Integration: All project details, skill listings, photo albums, and testimonials are dynamically fetched from a self-hosted Strapi CMS, allowing for easy content updates without code changes.
- Full Internationalization (i18n): The entire user interface, including all content from the CMS, is available in both English and German, with locale detection based on browser settings and a manual language switcher.
- Custom Strapi Controllers: The backend features custom controllers, such as for the testimonial submission form, which integrates Google reCAPTCHA for spam protection and custom logic for organizing file uploads into specific media library folders.
- Dynamic Theming: A "Paper-like" design with full support for system, light, and dark modes, built with Tailwind CSS and
next-themes.
Technical Challenges & Solutions
One of the main challenges was creating a seamless local development experience that could accurately simulate the multi-domain production environment. This was solved by implementing a DEV_FORCE_DOMAIN environment variable that instructs the Next.js Middleware to route localhost traffic as if it were coming from a specific subdomain.
Another challenge was handling file uploads from a public-facing form. This required careful configuration of Strapi's user roles, permissions for the upload plugin, and a custom controller to validate the request before passing the file to Strapi's upload service.