Version: 0.1.0 (MVP) Β |Β Status: Active Development Β |Β License: Private
A full-stack TypeScript/Next.js web application that serves as both an interactive personal portfolio and an educational design pattern playground. The system demonstrates all 23 Gang of Four (GoF) design patterns implemented within a production-grade architecture, targeting CS students, recruiters, and software engineering educators.
Welcome! This repository powers the live portfolio and interactive pattern playground.
- Live Demo: [Will be added soon]
- Core Features:
- Interactive portfolio showcasing Projects, Blog, Resume, and Podcasts.
- Command palette (Ctrl+K) for navigation and theme switching.
- 23 GoF Design Patterns implemented and observable in the UI.
- Multi-theme support (Dark/Light, Modern/Minimal/Future/Academic).
If you want to run this project locally, experiment with the design patterns, or contribute to the codebase, follow these quick steps:
# 1. Clone the repository & install dependencies
git clone <repository-url> && cd personal-profile-prototype
bun install
# 2. Configure environment & start Database
cp .env.example .env
bun run db:up
# 3. Apply migrations & seed data
bunx prisma migrate dev
bun run prisma:seed
# 4. Start development server
bun run devbun run dev # Start Webpack dev server
bun run dev:turbo # Start Turbopack dev server
bun run build # Type-check + Next.js production build
bun run start # Start production server
bun run lint # ESLint
bun run db:up # docker compose up -d (PostgreSQL)
bun run db:down # docker compose down
bun run db:logs # Follow PostgreSQL container logs
bun run prisma:generate # Generate Prisma client
bun run prisma:migrate:dev # Apply migrations (dev)
bun run prisma:seed # Seed database via Bun
bun run integration:auth-db # Auth + database integration test
bun run integration:http-crud # HTTP CRUD integration test
bun run integration:http-admin-users # Admin users integration testFor full deployment instructions, see the SDLC Documentation below.
This project was built following a strict SDLC process to serve as an educational reference. Below is the full engineering documentation.
Traditional developer portfolios are static, single-purpose pages that fail to demonstrate depth of software engineering knowledge. Simultaneously, CS curricula often teach design patterns in isolation β without grounding them in real, working systems. This project resolves both problems by merging portfolio functionality with a living, interactive pattern showcase.
| Objective | Description |
|---|---|
| Portfolio Showcase | Present projects, blog posts, resume, articles, and podcast content in a unified, dynamic interface |
| Pattern Playground | Implement all 23 GoF design patterns as first-class, observable features of the running application |
| Educational Reference | Provide a production-grade codebase that CS students and educators can study and extend |
| Future AI Integration | Architect the system to support LLM-powered content generation and intelligent assistants |
| Layer | Technology | Rationale |
|---|---|---|
| Frontend Framework | Next.js 16 + React 19 | App Router support, SSR/CSR flexibility, API routes co-location |
| Language | TypeScript 5.9 (strict) | Type safety essential for pattern demonstrations; generics power Strategy/Iterator/Composite |
| Styling | Tailwind CSS 4 + PostCSS | Utility-first enables rapid theme switching; supports Abstract Factory theme families |
| Runtime Scripting | Bun | Canonical package management and script execution for seeding, integration tests, and container builds |
| ORM | Prisma 7 | Type-safe database access; migration management for schema evolution |
| Database | PostgreSQL 16 | ACID compliance; relational model suits UserβPost ownership graph |
| Authentication | Auth.js / NextAuth v5 beta | Pluggable OAuth providers; JWT session strategy with role augmentation |
| Containerization | Docker + Docker Compose | Environment parity; isolates PostgreSQL; supports SSH-based production deployment |
| CI/CD | GitHub Actions | Builds a GHCR image and deploys it over SSH with production Docker Compose |
- All 23 GoF patterns implemented in
src/patterns/with 140+ test cases - Functional portfolio sections: Projects, Blog, Resume, Articles, Podcast, Contact, Dashboard
- Working authentication (Google OAuth + test credentials)
- Theme customization (dark/light, 4 style families, 2 font families, EN/TH i18n)
- Guided tour system with iterator-driven step navigation
- Command palette (Ctrl+K) with undo/redo history
- Docker-containerized development and production environments
- GitHub Actions deployment workflow for GCP and Azure hosts
- Performance benchmarks (FCP < 2.5s, LCP < 4.0s) β In Progress
- Full WCAG 2.1 AA accessibility audit β In Progress
| ID | Feature | Priority | Status |
|---|---|---|---|
| FR-1 | Portfolio Content Management (Composite tree, multi-layout) | Critical | β Implemented |
| FR-2 | Unified Feed with Filter Chain + Sort Strategy | High | β Implemented |
| FR-3 | Role-Based Authentication (Google OAuth + Credentials) | Critical | β Implemented |
| FR-4 | Runtime Theme & Localization System (Abstract Factory) | High | β Implemented |
| FR-5 | Guided Tour System (Iterator + State Machine) | Medium | β Implemented |
| FR-6 | Command Palette with Undo/Redo (Command + Memento) | Medium | β Implemented |
| FR-7 | Podcast Player (Finite State Machine) | Low | β Implemented |
| FR-8 | Contact Form with Mediator Validation | Medium | β Implemented |
| FR-9 | Admin Dashboard (Visitor analytics, Prototype cloning) | High | β Implemented |
| FR-10 | REST API for Posts CRUD | High | β Implemented |
| FR-11 | Full CRUD for Projects, Articles, Podcasts | Medium | Planned |
| FR-12 | AI/LLM Content Generation | Low | Planned |
| Requirement | Target | Status |
|---|---|---|
| First Contentful Paint (FCP) | < 2.5s | To be defined |
| Largest Contentful Paint (LCP) | < 4.0s | To be defined |
| Accessibility (WCAG) | 2.1 AA | To be defined |
| Browser Support | Chrome, Firefox, Safari, Edge (latest 2) | Partial |
| Mobile Responsiveness | 320px β 2560px | Partial |
| Uptime Target | β₯ 99.5% | To be defined |
| API Error Rate | < 0.1% | To be defined |
| TypeScript Strict Mode | 100% | β Enforced |
| Role | Capabilities |
|---|---|
| Guest | View public portfolio sections, browse content feed |
| Viewer | All guest permissions + filter/sort feed, access guided tour, use command palette |
| Admin | All viewer permissions + create/delete posts, clone project templates, view dashboard analytics |
The system follows a Pattern-Driven UI Monolith with a Layered Architecture within a single Next.js application:
block-beta
columns 1
block:client["Client (Browser)"]
columns 1
ui["οΈ UI Layer β React Components\nNavigationShell Β· Sections Β· Feed Β· System Controls"]
domain["βοΈ Domain Layer β Models & Services\nTheme Β· Command Β· Feed Β· Content Β· Tour"]
facade["οΈ Application Facade\nAppSystemFacade (Bootstrap)"]
end
arrow["HTTP / JSON"]
block:server["Server (Next.js)"]
columns 1
api[" Server Layer β Next.js API Routes\n/api/auth Β· /api/posts Β· Auth Middleware"]
dal[" Data Access Layer β Prisma ORM"]
db["οΈ Database β PostgreSQL 16\nusers Β· posts Β· future models"]
end
ui --> domain
domain --> facade
facade --> arrow
arrow --> api
api --> dal
dal --> db
All 23 Gang of Four patterns are implemented and observable in the running application.
| Pattern | Implementation | Location |
|---|---|---|
| Singleton | NotificationService, ToastEventEmitter, CommandHistory |
app/services/system/ |
| Factory Method | LocalizationFactory β creates EN/TH locale objects |
app/models/theme/ |
| Abstract Factory | StyleFactory β creates Modern/Minimal/Future/Academic theme families |
app/models/theme/ |
| Builder | ContentBuilder β fluent API for constructing nested content trees |
app/models/ |
| Prototype | ProjectTemplate + ProjectTemplateRegistry β admin template cloning |
app/models/template/ |
| Pattern | Implementation | Location |
|---|---|---|
| Adapter | adaptBlogToUnified, adaptProjectToUnified β normalize diverse content types |
app/services/content/ |
| Bridge | NotificationService + INotificationChannel β decouple notification logic from delivery |
app/services/system/ |
| Composite | LayoutNode / CompositeNode / LeafNode β recursive content tree |
app/interfaces/content-tree.ts |
| Decorator | ContentDecorator β dynamically adds badges/overlays to feed cards |
app/components/feed/ |
| Facade | AppSystemFacade β single entry point for app bootstrap and initialization |
app/services/system/ |
| Flyweight | ParticleFactory β shared intrinsic state for animated background particles |
app/components/system/ |
| Proxy | AccessControlProxy β gate premium/admin content behind session checks |
app/models/ |
| Pattern | Implementation | Location |
|---|---|---|
| Chain of Responsibility | FilterHandler pipeline β Type β Tag β Search filters |
app/services/feed/ |
| Command | ICommand + NavigateCommand, ToggleThemeCommand, etc. |
app/models/command/ |
| Iterator | TourIterator β sequential step traversal for guided tour |
app/models/tour/ |
| Observer | ToastEventEmitter β event-driven toast notification dispatch |
app/services/system/ |
| Strategy | FeedSortStrategy β DateSortStrategy, TitleSortStrategy, LengthSortStrategy |
app/models/feed/ |
| State | AudioPlayerContext with StoppedState, PlayingState, PausedState |
app/models/podcast/ |
| Template Method | Content export algorithm with pluggable format steps | src/patterns/ |
| Mediator | ContactFormMediator β orchestrates form validation and submission |
app/services/contact/ |
| Memento | FeedStateMemento + FeedStateCaretaker β snapshot/restore filter state |
app/models/feed/ |
| Interpreter | Grammar evaluator for expression parsing | src/patterns/ |
| Visitor | MetricsVisitor, TagsVisitor β analytics traversal of content trees |
app/components/dashboard/ |
erDiagram
USER {
string id PK "cuid"
string email UK
string name
string image
string role
string provider
string providerAccountId
datetime createdAt
datetime updatedAt
}
POST {
string id PK "cuid"
string title
string content
boolean published
string authorId FK
datetime createdAt
datetime updatedAt
}
USER ||--o{ POST : "authors"
| Entity | Fields | Notes |
|---|---|---|
User |
id (cuid PK), email (unique), name, image, role, provider, providerAccountId, createdAt, updatedAt |
Composite unique on [provider, providerAccountId] |
Post |
id (cuid PK), title, content, published, authorId (FK β User), createdAt, updatedAt |
Index on authorId |
Planned models: Project, Article, Podcast, Blog, Template, Tag, Category
flowchart TD
A([" Login"]) --> B{"Choose Provider"}
B -- "Google OAuth" --> C["NextAuth OAuth Callback"]
B -- "Credentials" --> D["Credential Validation"]
C --> E["Upsert User in PostgreSQL"]
D --> E
E --> F["Generate JWT\n(userId + role)"]
F --> G["Session Callback\naugments session object"]
G --> H{"Access Protected Route?"}
H -- "Yes" --> I["requireAdminSession()"]
H -- "No" --> K["Render Viewer UI"]
I -- "Admin role" --> J["Render Admin UI"]
I -- "Insufficient role" --> L(["401 Unauthorized"])
personal-profile-prototype/
βββ app/ # Next.js App Router root
β βββ api/ # Server-side API route handlers
β β βββ auth/ # NextAuth.js endpoints
β β βββ posts/ # Posts CRUD (GET, POST, DELETE)
β β βββ users/ # User management [planned]
β βββ components/ # Reusable React UI components
β β βββ content/ # Content node renderers
β β βββ dashboard/ # Metrics, tag cloud, analytics
β β βββ feed/ # Feed cards, filters, sort bar
β β βββ layout/ # Navigation shell, page structure
β β βββ section/ # Section primitive wrappers
β β βββ system/ # Theme controls, tour, command palette, particles
β βββ features/ # Feature-level compositions
β β βββ composition/ # Root app assembly (PersonalWebsiteApp)
β β βββ sections/ # Full section implementations
β βββ interfaces/ # TypeScript interface contracts
β β βββ content-tree.ts # IContentNode, IVisitor, IComponent
β β βββ feed.ts # IFeedItem, IFeedState, ISortStrategy
β βββ lib/ # Server-side utilities
β β βββ auth.ts # NextAuth configuration
β β βββ prisma.ts # Prisma singleton client
β β βββ require-admin-session.ts # Auth middleware helper
β βββ models/ # Domain model implementations
β β βββ command/ # ICommand + concrete commands
β β βββ feed/ # Sort strategies, Memento, FilterHandler
β β βββ podcast/ # AudioPlayerContext + State classes
β β βββ template/ # ProjectTemplate, registry (Prototype)
β β βββ theme/ # Style/Font/Locale factories
β β βββ tour/ # TourIterator, tour steps
β βββ services/ # Business logic & orchestration
β β βββ contact/ # ContactFormMediator
β β βββ content/ # Content adapters, decorators
β β βββ feed/ # Feed operations
β β βββ system/ # AppSystemFacade, NotificationService
β βββ data/ # Static/mock data
β β βββ content.ts # Portfolio content seed
β β βββ resume.ts # Resume data model
β βββ [tab]/ # Dynamic tab routing
β βββ globals.css # Global base styles
β βββ layout.tsx # Root layout (Geist fonts, Providers)
β βββ page.tsx # Root entry point
β βββ providers.tsx # React context providers (NextAuth SessionProvider)
βββ src/ # Standalone pattern library
β βββ patterns/ # All 23 GoF patterns (standalone TypeScript)
β β βββ 01_singleton_notifications.ts
β β βββ ...
β β βββ 24_visitor_operations.ts
β β βββ TESTS.ts # 30+ creational tests (Bun:test)
β β βββ STRUCTURAL_TESTS.ts # 50+ structural tests
β β βββ BEHAVIORAL_TESTS.ts # 60+ behavioral tests
β β βββ index.ts # Central pattern exports
β βββ main.ts # Pattern library entry
β βββ interface.ts # Shared type contracts
β βββ data.ts # Shared mock data
βββ prisma/
β βββ schema.prisma # Prisma data model
β βββ migrations/ # Versioned schema migrations
βββ scripts/
β βββ integration-auth-db.ts # Auth + DB integration test
β βββ integration-http-crud.ts # HTTP CRUD integration test
β βββ integration-http-admin-users.ts # Admin endpoint integration test
β βββ prisma-crud-example.ts # Prisma CRUD reference
β βββ deploy-gcp.sh # Manual GCP deploy script
β βββ setup-docker-dev.sh # Docker dev environment setup
βββ lib/
β βββ prisma.ts # Root Prisma singleton (for scripts)
βββ .github/workflows/
β βββ deploy.yml # Build GHCR image β SSH deploy to GCP and Azure hosts
βββ Dockerfile # Multi-stage production build
βββ docker-compose.yml # Dev: PostgreSQL + Next.js app
βββ docker-compose.prod.yml # Production compose configuration
βββ package.json # Dependencies + Bun scripts
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/api/auth/session |
Public | Check active session |
POST |
/api/auth/signin |
Public | NextAuth sign-in |
POST |
/api/auth/signout |
Session | Sign out |
GET |
/api/posts |
Session | List all posts |
POST |
/api/posts |
Admin | Create a new post |
GET |
/api/posts/[id] |
Session | Get single post |
DELETE |
/api/posts/[id] |
Admin | Delete a post |
| Construct | Convention | Example |
|---|---|---|
| React Components | PascalCase | UnifiedFeedSection, CommandPalette |
| Files | kebab-case | feed-item-card.tsx |
| Interfaces | PascalCase (prefixed I) |
ICommand, IVisitor |
| Services | PascalCase + Service suffix |
NotificationService |
| Constants | UPPER_SNAKE_CASE | MOCK_PROJECTS, LOCALES |
| Types | PascalCase | DecorationType, LayoutStyleType |
- React Context API is used for global state (theme, language, admin role) rather than a third-party store β keeping the pattern surface visible without framework magic.
- Singleton services are instantiated once at module load, ensuring pattern correctness is observable at runtime.
- Bun is the canonical package manager and script runner for dependency installation, seeding, integration tests, image builds, and container runtime commands. Node.js remains the Docker base image for Next.js compatibility.
- Static mock data (
app/data/) drives the portfolio sections in the MVP; the REST API layer is designed to replace this data source as database models are added.
| Layer | Framework | Status |
|---|---|---|
| Pattern Unit Tests | Bun (bun:test) |
β 140+ test cases across all 23 patterns |
| Integration β Auth + DB | Bun script (scripts/integration-auth-db.ts) |
β Available locally; not run by the current deployment workflow |
| Integration β HTTP CRUD | Bun script (scripts/integration-http-crud.ts) |
β Available locally; not run by the current deployment workflow |
| Integration β Admin Users | Bun script (scripts/integration-http-admin-users.ts) |
β Available locally; not run by the current deployment workflow |
| Unit Tests β React Components | Jest / React Testing Library | To be defined |
| E2E Tests | Playwright | To be defined |
# Creational patterns
bun test src/patterns/TESTS.ts
# Structural patterns
bun test src/patterns/STRUCTURAL_TESTS.ts
# Behavioral patterns
bun test src/patterns/BEHAVIORAL_TESTS.ts
# All patterns
bun test src/patterns/# Prerequisites: database running and migrations applied
bun run db:up
bunx prisma migrate deploy
# Auth + database
bun run integration:auth-db
# HTTP CRUD endpoints
bun run integration:http-crud
# Admin user management
bun run integration:http-admin-usersUnit Tests (Jest + RTL)
βββ ContentBuilder.test.ts
βββ FeedStateMemento.test.ts
βββ AudioPlayerStateMachine.test.ts
βββ NotificationService.test.ts
βββ Adapters (adaptBlogToUnified, etc.)
E2E Tests (Playwright)
βββ Portfolio viewing flow
βββ Feed filter β sort β display
βββ Theme switching (dark/light, styles)
βββ Authentication + admin feature gates
βββ Contact form submission
Target coverage: 80% for critical paths, 60% overall.
- Node.js 20.19+ (the Docker image uses
node:20.19-alpine) - Docker & Docker Compose
- Bun (canonical package manager and script runner)
- Google Cloud SDK (optional, for manual GCP tooling)
# 1. Clone the repository
git clone <repository-url>
cd personal-profile-prototype
# 2. Install dependencies
bun install
# 3. Configure environment
cp .env.example .env
# 4. Start PostgreSQL
bun run db:up # docker compose up -d
# 5. Apply database migrations
bunx prisma migrate dev
# 6. Seed the database
bun run prisma:seed
# 7. Start development server
bun run dev # Webpack dev server β http://localhost:3000
# or: bun run dev:turbo # Turbopack (faster, experimental)The Compose files use different variable names for local development and production deployment. Configure the appropriate environment file for the selected runtime and do not commit secret values.
# Local docker-compose.yml
DATABASE_URL=postgresql://user:password@localhost:5432/personal_profile_prototype
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=<random-256-bit-secret>
GITHUB_ID=<optional-github-client-id>
GITHUB_SECRET=<optional-github-client-secret>
GOOGLE_ID=<optional-google-client-id>
GOOGLE_SECRET=<optional-google-client-secret>
NODE_ENV=development
NEXT_PUBLIC_API_URL=http://localhost:3000docker-compose.prod.yml uses DATABASE_URL, NODE_ENV, and NEXT_PUBLIC_API_URL, and also expects production values for AUTH_SECRET, AUTH_URL, AUTH_TRUST_HOST, AUTH_GOOGLE_ID, AUTH_GOOGLE_SECRET, ADMIN_TEST_EMAIL, ADMIN_TEST_PASSWORD, VIEWER_TEST_PASSWORD, OWNER_EMAIL, and SERVER_NODE.
# Build image
docker build -t personal-profile:0.1.0 .
# Run with production env
docker run -p 3000:3000 --env-file .env.production personal-profile:0.1.0
# Or use production compose
docker compose -f docker-compose.prod.yml up -dThe Dockerfile uses a multi-stage build:
- Stage 1 (builder):
node:20.19-alpineβ bootstraps Bun, installs dependencies frombun.lock, generates the Prisma client, and builds Next.js - Stage 2 (runner):
node:20.19-alpineβ bootstraps Bun, copies the built application assets, runs as the non-rootnodeuser, and starts the app withbun run start
docker-compose.prod.yml pulls ghcr.io/taichi112/personal-profile-app:latest and runs the app alongside Nginx and Certbot.
flowchart TD
A(["Push to main"]) --> B["deploy.yml: check out repository"]
B --> C["Log in to GitHub Container Registry"]
C --> D["Build Docker image from Dockerfile"]
D --> E["Push ghcr.io/taichi112/personal-profile-app:latest"]
E --> F["deploy-gcp: SSH to GCP host"]
E --> G["deploy-azure: validate SSH key and connect to Azure host"]
F --> H["Reset checkout to origin/main"]
G --> I["Reset checkout to origin/main"]
H --> J["Pull app image and restart docker-compose.prod.yml"]
I --> K["Pull app image and restart docker-compose.prod.yml"]
J --> L(["GCP Docker Compose deployment running"])
K --> M(["Azure Docker Compose deployment running"])
| Environment | Platform | Trigger |
|---|---|---|
| Development | Local Docker Compose | Manual |
| Production β GCP host | Docker Compose over SSH | Push to main |
| Production β Azure host | Docker Compose over SSH | Push to main |
- Horizontal scaling: The current SSH-based Docker Compose deployment runs on individual hosts. Horizontal scaling would require an orchestration or load-balancing layer.
- Database scaling: Migrate from single PostgreSQL container to GCP Cloud SQL with read replicas as traffic grows.
- Content volume: The Composite tree and Adapter pattern ensure new content types can be added without modifying existing rendering logic.
| Area | Current | Planned |
|---|---|---|
| Client errors | console.log + Toast notifications |
Sentry / GCP Error Reporting |
| Server errors | Next.js default | Structured JSON logs β GCP Cloud Logging |
| Performance | Manual | Core Web Vitals via Vercel Analytics or GCP |
| Uptime | None | StatusPage.io / GCP Uptime Checks |
| Analytics | AnalyticsSystem singleton (client-side) |
Google Analytics / Plausible |
| Cadence | Task |
|---|---|
| Weekly | Review CI failures; check error logs for patterns |
| Monthly | bun audit + dependency security patches; analyze failed API requests |
| Quarterly | Major framework version upgrades; security audit; load testing; DR drill |
| Metric | Target |
|---|---|
| RTO (Recovery Time Objective) | 4 hours |
| RPO (Recovery Point Objective) | 1 hour |
| Backup Strategy | Daily automated PostgreSQL snapshots; weekly offsite |
| Rollback | Manual: deploy a known-good GHCR image tag and restart the production Docker Compose services |
- AI-Native Content Generation: Integrate an LLM API to auto-generate blog post drafts, project descriptions, and resume bullet points
- Database-backed portfolio: Migrate static
data/content.tsto Prisma-managedProject,Article,Podcast, andTemplatemodels - Full-text search: Add PostgreSQL full-text search or Algolia for the content feed
- Accessibility audit: Complete WCAG 2.1 AA remediation and add automated axe-core checks to CI
- Progressive Web App (PWA): Add service worker and offline support via
next-pwa - Kubernetes manifests: Add Helm chart for multi-region, production-scale deployment
Generated from codebase analysis Β· April 2026 Β· Personal Profile Prototype v0.1.0