Welcome to my personal blog and portfolio website! This repository contains a modern Next.js application where I share my thoughts, projects, and insights.
- Next.js 16 with App Router and React Compiler
- React 19
- TypeScript with strict configuration
- Tailwind CSS v4 for styling
- MDX for content (Content Collections)
- Drizzle ORM with Zod schemas
- next-intl for internationalization (6 locales)
- oRPC for the type-safe API layer
- Base UI for accessible UI components
- Responsive design
- Light/Dark mode
- Image zoom in blog posts
- Shiki for code syntax highlighting
- Motion for animations
- Table of contents for blog posts
- Keyboard-driven command menu
- Guestbook
- Admin dashboard with live stats
- Account settings
- Comment system
- Like functionality
- Post view counter
- Blog post search
- RSS feed
- Sitemap
- Lighthouse score of nearly 100
- SEO optimized with meta tags and JSON-LD
- Dynamic open graph images using
next/og
- Vitest for unit testing
- Playwright for E2E testing
- Oxlint configuration
- Oxfmt code formatting
- Knip for unused code detection
- CSpell for spell checking
- i18n-check for translation validation
- Lefthook
- Conventional commit
- GitHub Actions CI
- Better Auth
- Redis caching with Upstash
- Upstash for API rate limiting
- t3-env for environment variables
- Umami Analytics
- Cloudflare R2 for image storage
- Resend for transactional emails
- Node.js >= 24
- pnpm >= 12.7
- Docker
- Visual Studio Code with recommended extensions
- Optionally React Developer Tools
nelsonlai.dev/
├── .github/ # CI workflows and shared actions
├── .vscode/ # Editor settings and recommended extensions
├── public/ # Static assets (images, fonts, videos)
├── src/
│ ├── app/ # Next.js app router pages
│ ├── assets/ # Shared assets
│ ├── components/ # React components
│ ├── constants/ # Application constants
│ ├── content/ # MDX blog posts and content
│ ├── contexts/ # React contexts
│ ├── db/ # Database schema and migrations
│ ├── emails/ # Email templates
│ ├── hooks/ # Custom React hooks
│ ├── i18n/ # Internationalization
│ ├── lib/ # Utility libraries
│ ├── mdx-plugins/ # Custom Rehype and Remark plugins
│ ├── orpc/ # oRPC API routes
│ ├── styles/ # Global styles
│ ├── tests/ # Unit and E2E tests
│ └── utils/ # Utility functions
├── docker-compose.yml
└── package.json
To run this project locally, you need to set up the development environment.
- Clone the repository:
git clone https://github.com/nelsonlaidev/nelsonlai.dev- Navigate to the project directory:
cd nelsonlai.dev- Install dependencies using pnpm:
pnpm install- Create
.env.localusing the variables documented in.env.schema. For the local Docker services, start with:
DATABASE_URL=postgres://postgres:postgres@localhost:5432/nelsonlaidev
UPSTASH_REDIS_REST_URL=http://localhost:8079
UPSTASH_REDIS_REST_TOKEN=local-uprest-token-7f3c9a2e6b1d4f80
IP_ADDRESS_SALT=
BETTER_AUTH_SECRET=Generate separate random values of at least 32 characters for IP_ADDRESS_SALT and BETTER_AUTH_SECRET (for example, with openssl rand -hex 32). Keep an existing IP_ADDRESS_SALT stable to preserve anonymous identifiers. Optional integrations can be left unset.
Varlock validates configuration against .env.schema, loads .env.local automatically, and generates env.d.ts. Next.js uses the official Varlock integration. Database scripts, test runners, and Knip load configuration through varlock/auto-load in their Node.js entry points; external CLIs such as React Email use varlock run. Application code reads typed values directly from varlock/env.
Validate your environment before continuing:
pnpm env:check- Run required services using Docker:
docker compose up -d- Run the database migrations:
pnpm db:migrate- Seed the database:
pnpm db:seed- Run the app:
pnpm dev # Run the development server
# or
pnpm email:dev # Run the email preview server separatelyThe services will be available at the following URLs:
| Service | URL |
|---|---|
| App | localhost:3000 |
| React Email | localhost:3001 |
| Database | localhost:5432 |
| Redis | localhost:6379 |
| Redis serverless | localhost:8079 |
# Development
pnpm dev # Start development server
pnpm email:dev # Run email preview server
# Build & Production
pnpm build # Build for production
pnpm start # Start production server
pnpm analyze # Analyze bundle size
pnpm build:mdx # Build MDX collections
pnpm typegen # Generate types
# Quality & Testing
pnpm env:check # Validate environment variables
pnpm check # Run all quality checks (lint, typecheck, format, etc.)
pnpm lint # Run Oxlint
pnpm lint:fix # Auto-fix lint issues
pnpm lint:spell # Run spell check
pnpm typecheck # Run TypeScript type checking
pnpm format # Format code with Oxfmt
pnpm format:check # Check formatting
pnpm knip # Find unused dependencies/exports
pnpm check:i18n # Validate translations
pnpm test:unit # Run unit tests
pnpm test:unit:coverage # Run unit tests with coverage
pnpm test:e2e # Run Playwright E2E tests
pnpm test:e2e:install # Install Playwright browsers
# Database
pnpm db:generate # Generate database migrations
pnpm db:migrate # Run database migrations
pnpm db:seed # Seed the database
pnpm db:push # Push schema changes directly to DB
pnpm db:reset # Reset database
pnpm db:studio # Open Drizzle Studio
# Emails & Cleanup
pnpm email:export # Export email templates
pnpm clean # Clean build artifactsThis project has been made possible thanks to the wonderful open-source community. Special thanks to:
- Timothy for the Tailwind nextjs starter blog template.
- Eihab for the UI design inspiration (Figma)
This project also uses/adapts the following open-source projects:
- Comment System - from fuma-comment
- Rehype Plugins - from fumadocs
- UI components - from shadcn/ui
- Admin UI - from shadcn-admin
The following projects were referenced for inspiration:
- fumadocs
- leerob.io
- nerdfish.be
- nextra.site
- theodorusclarence.com
- ped.ro
- delba.dev
- joshwcomeau.com
- blog.maximeheckel.com
- zenorocha.com
- jahir.dev
- anishde.dev
- nikolovlazar.com
- samuelkraft.com
- bentogrids.com
- ui.aceternity.com
- hover.dev
- vocs.dev
If you find this project helpful, consider supporting me by sponsoring the project.
This project is open source and available under the MIT License.
Made with ❤️ in Hong Kong

