No description
  • TypeScript 94.9%
  • MDX 2.3%
  • JavaScript 1.7%
  • CSS 0.7%
  • Dockerfile 0.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-07-30 15:04:49 +02:00
config feat(i18n): add locale ui translations 2026-07-29 15:53:48 +02:00
content Feat(content): migrate projects to UUID slugs 2026-07-24 17:06:18 +02:00
docs docs: add authored translation design 2026-07-29 15:51:53 +02:00
drizzle feat: centralized tag system with admin management 2026-05-03 13:48:47 +02:00
public Feat(content): migrate projects to UUID slugs 2026-07-24 17:06:18 +02:00
scripts Drop Spotify integration and fix admin auth 2026-07-22 15:21:30 +02:00
src fix: restore locale links and auth reset 2026-07-30 15:04:49 +02:00
.dockerignore feat: add Docker support and GitHub Actions CI/CD 2026-05-03 10:19:15 +02:00
.env.example Drop Spotify integration and fix admin auth 2026-07-22 15:21:30 +02:00
.gitattributes Drop Spotify integration and fix admin auth 2026-07-22 15:21:30 +02:00
.gitignore chore: add Spotify and Stats.fm API configuration 2026-05-03 17:48:34 +02:00
.nvmrc chore: upgrade to Node.js 24 2026-05-03 10:24:59 +02:00
AGENTS.md feat(i18n): add locale ui translations 2026-07-29 15:53:48 +02:00
CLAUDE.md Initial commit from Create Next App 2026-05-02 20:25:53 +02:00
docker-compose.yml Drop Spotify integration and fix admin auth 2026-07-22 15:21:30 +02:00
Dockerfile Drop Spotify integration and fix admin auth 2026-07-22 15:21:30 +02:00
drizzle.config.ts feat: SQLite admin auth — DB schema, sessions, password hashing, API routes 2026-05-03 09:40:17 +02:00
eslint.config.mjs fix: resolve all ESLint errors and warnings 2026-05-03 10:37:55 +02:00
LICENSE Add MIT License to the project 2026-05-03 00:09:48 +02:00
middleware.ts feat(i18n): add locale ui translations 2026-07-29 15:53:48 +02:00
next.config.ts Drop Spotify integration and fix admin auth 2026-07-22 15:21:30 +02:00
package-lock.json fix: restore locale links and auth reset 2026-07-30 15:04:49 +02:00
package.json fix: restore locale links and auth reset 2026-07-30 15:04:49 +02:00
postcss.config.mjs Initial commit from Create Next App 2026-05-02 20:25:53 +02:00
README.md updates of ideas, project TableOfContents, and rework of README to match 2026-07-24 17:59:43 +02:00
tsconfig.json Initial commit from Create Next App 2026-05-02 20:25:53 +02:00

Portfolio

A modern personal portfolio and blog built with Next.js 16, MDX content, and a custom admin/content workflow.

The site is designed for recruiters, companies, and other developers to browse public work while also giving me a fast way to create and edit content from the browser.

What’s in this project

Public site

  • Home page with featured projects, recent posts, and stats
  • Projects section with detailed project pages
  • Blog with MDX posts and related-post suggestions
  • Experience timeline and detail pages
  • About, contact, resume, uses, now, tags, testimonials, and other supporting pages
  • Search, comments, SEO metadata, OpenGraph images, and JSON-LD

Admin and content workflow

  • /admin for authentication and admin tools
  • /content for creating and editing content in one place
  • /content/media for the reusable media library
  • /settings for site settings and admin utilities
  • Markdown + HTML preview with script content blocked
  • Media uploads converted to WebP
  • Project slugs are UUID-based and managed automatically
  • Blog and experience slugs remain editable

Content model

  • Projects: content/projects/*.mdx
  • Blog posts: content/blog/*.mdx
  • Experience entries: content/experience/*.mdx
  • General pages: content/pages/*.mdx
  • Media uploads: public/uploads/
  • Project images: public/images/projects/

Tech stack

  • Framework: Next.js 16 App Router

  • Language: TypeScript

  • Styling: Tailwind CSS 4

  • Content: MDX, gray-matter, next-mdx-remote

  • Database: SQLite with Drizzle ORM

  • Authentication: Argon2 + session cookies, with optional OIDC/SSO

  • Search: Fuse.js

  • Media processing: Sharp

  • Comments: Giscus

  • Forms / email: Resend

Getting started

Requirements

  • Node.js 24 or newer
  • npm

Install

git clone https://github.com/FTMahringer/Portfolio.git
cd Portfolio
npm install

Configure environment

Create a local .env file from your example file and fill in the values you need:

cp .env.example .env

At minimum, set the admin credentials and API secret.

Initialize the database

npm run db:push
npm run db:seed

Start the dev server

npm run dev

Open:

  • Public site: http://localhost:3000
  • Admin dashboard: http://localhost:3000/admin
  • Content manager: http://localhost:3000/content

Editing content

Creating and editing

  • Use /content/new/[type] to create new content
  • Use /content/edit/[type]/[slug] to edit existing entries
  • Use the preview/write toggle to switch between source and rendered view

Projects

  • Project slugs are UUIDs and hidden in the editor UI
  • Change the project title as needed; the slug stays managed automatically
  • Inline images used in the MDX content are tracked for the project page gallery
  • Cover images are handled separately from inline content images

Blog and experience

  • Blog and experience entries keep editable slugs
  • Heading anchors are generated automatically for MDX content
  • Related content and tags are handled through frontmatter

Media library

  • Upload images through the media picker or /content/media
  • Uploaded images are stored in public/uploads/
  • Images are converted to WebP on upload

Available scripts

npm run dev
npm run build
npm run start
npm run lint
npm run validate:content
npm run db:generate
npm run db:migrate
npm run db:push
npm run db:studio
npm run db:seed

Script notes

  • npm run validate:content checks content files and frontmatter
  • npm run db:seed seeds the default admin user from environment variables
  • npm run db:push is the easiest way to initialize a fresh local database

Environment variables

Required

Variable Description
ADMIN_EMAIL Default admin email address
ADMIN_PASSWORD Default admin password
API_SECRET Secret used by admin/content API routes

Common optional variables

Variable Description
DATABASE_URL SQLite database path
NEXT_PUBLIC_BASE_URL Public site URL for canonical links and social metadata
RESEND_API_KEY Enables email submissions
CONTACT_EMAIL Destination inbox for contact form submissions
NEXT_PUBLIC_UMAMI_WEBSITE_ID Umami analytics website ID
NEXT_PUBLIC_UMAMI_URL Umami analytics server URL
NEXT_PUBLIC_PLAUSIBLE_DOMAIN Plausible analytics domain
OIDC_ISSUER OIDC issuer URL for SSO fallback
`OIDC_CLIENT
_ID` OIDC client ID fallback
OIDC_CLIENT_SECRET OIDC client secret fallback

Troubleshooting

Admin login does not work

  • Make sure ADMIN_EMAIL and ADMIN_PASSWORD are set before seeding
  • Run npm run db:seed again after changing those values

Content changes do not show up

  • Check that the content file is in the correct folder
  • Re-run npm run validate:content
  • Restart the dev server if needed

Database errors

  • Use npm run db:studio to inspect the SQLite database
  • For a clean local reset, delete the database file and run npm run db:push + npm run db:seed again

Contributing

This repository is actively evolving as the portfolio and admin workflow grow.

If you add new content features, remember to update the relevant docs and content validation rules so the editor and public site stay in sync.

License

MIT — see LICENSE.