This is the source code for franco-may.com, a personal blog and portfolio website built with Next.js and Mantine.
The live version of this code is running at: https://franco-may.com
Feel free to fork this repository and customize it to your liking! You can:
- Add your own blog posts in the
posts/directory (posts use HTML strings with metadata) - Modify the site configuration in
utils/constants.tsx - Update the theme and styling to match your preferences
- Add new features and components as needed
This project comes with the following features:
- PostCSS with mantine-postcss-preset
- TypeScript
- Storybook with dark mode support and Mantine theme integration
- Jest setup with React Testing Library
- ESLint setup with eslint-config-mantine
- Yarn package manager with node_modules linker
- Prettier code formatting with auto-format on save
- Dark/Light mode toggle with smooth transitions
- Blog system with dynamic routing, centralized post management, breadcrumb navigation, and HTML-based content rendering
- Enhanced RSS feed generation at
/rss.xmlwith Dublin Core metadata, Media RSS support, Atom timestamps, and featured images - Contact form with email submission via SMTP (nodemailer)
- Form validation using Zod schemas and react-hook-form
- Interactive archaeological sites map with MapLibre GL integration, vector tile serving, real-time location tracking, and detailed site information with custom icons
The application includes the following pages:
- Home (
/) - Main landing page with personal introduction and image - Blog (
/blog) - Blog listing page with articles organized by year, sorted chronologically with newest posts first - Blog Articles (
/blog/[slug]) - Individual blog articles with dynamic routing (e.g.,/blog/ai-and-the-myth-of-artificial-desire,/blog/why-is-there-something-rather-than-nothing) - Contact (
/contact) - Functional contact form with email submission, form validation, and rate limiting - Archaeological Sites (
/fornlamningar) - Interactive map showcasing archaeological sites in Sweden with MapLibre GL integration, vector tile serving, location tracking, and detailed site information
dev– start dev serverbuild– bundle application for productionanalyze– analyzes application bundle with @next/bundle-analyzer
typecheck– checks TypeScript typeslint– runs ESLintprettier:check– checks files with Prettierjest– runs jest testsjest:watch– starts jest watchtest– runsjest,prettier:check,lintandtypecheckscripts
storybook– starts storybook dev serverstorybook:build– build production storybook bundle tostorybook-staticprettier:write– formats all files with Prettier
This project is compatible with Next.js 15. Key compatibility notes:
- Dynamic Route Parameters: In Next.js 15, route parameters (
params) are now Promises that must be awaited. Seeapp/blog/[slug]/page.tsxfor an example implementation.
To enable the contact form functionality, you'll need to set up SMTP credentials. Copy the .env.example file to .env.local and configure your email settings:
cp .env.example .env.localFor Gmail users:
- Enable 2-factor authentication on your Google account
- Generate an App Password (not your regular password)
- Use that App Password as
SMTP_PASSin your.env.localfile
The archaeological sites map uses MapLibre GL with vector tiles. The map tiles are served from the application's API routes and don't require external API keys. The map includes:
- Vector tile serving via Next.js API routes (
/api/fornlamningar/tiles/{z}/{x}/{y}.pbf) - OpenStreetMap base tiles
- Archaeological sites data with clustering and relevance-based styling
- Real-time location tracking with permission handling
This project includes VS Code settings for automatic code formatting on save. Make sure to install the Prettier extension for the best development experience.