A high-performance, professional CMS and Blog engine built with the Next.js App Router, featuring a robust moderation system, server-side SEO optimization, and a premium "Liquid Glass" design aesthetic.
- Framework: Next.js 16 (App Router) - Leveraged for Server-Side Rendering (SSR) and optimized hydration.
- Language: TypeScript - Ensures type safety across the full stack, from Prisma schemas to frontend props.
- Database: Neon DB (PostgreSQL) - Serverless Postgres used for reliable data persistence and low-latency scaling.
- ORM: Prisma - Provides a type-safe interface for database queries and schema migrations.
- Styling: Tailwind CSS - Used for rapid, responsive UI development with a custom design system.
- UI Components: Shadcn UI - Built on Radix UI for accessible, high-quality interactive components.
- Validation: Zod - Handles schema validation for API requests and client-side forms.
├── app/ # Next.js App Router
│ ├── (auth)/ # Admin Authentication routes
│ ├── (dashboard)/ # Admin Panel routes (Dashboard, Posts, Comments)
│ ├── api/ # Backend API routes for CRUD & view counting
│ ├── blog/ # Public Blog Detail routes (SSR)
│ ├── globals.css # Global styles & Tailwind variables
│ ├── layout.tsx # Root layout with Metadata API
│ ├── page.tsx # Home page with ISR (revalidate: 60)
│ ├── robots.ts # Dynamic Robots.txt configuration
│ └── sitemap.ts # Dynamic XML Sitemap generator
├── components/ # UI Component Library
│ ├── admin/ # Admin-specific logic (Delete buttons, etc.)
│ ├── blog/ # Blog-specific logic (Detail page, List client)
│ ├── ui/ # Reusable Shadcn UI primitives
│ ├── admin-sidebar.tsx # Main dashboard navigation
│ └── blog-card.tsx # Reusable card for article previews
├── lib/ # Shared core utilities
│ ├── prisma.ts # Prisma Client (Singleton pattern)
│ └── utils.ts # Tailwind CSS class merging logic
├── prisma/ # Database Layer
│ ├── schema.prisma # Relational schema definition
│ └── seed.ts # 20-post automated seeding script
├── types/ # Global TypeScript definitions
│ └── index.ts # Shared interfaces (e.g., BlogWithImages)
├── middleware.ts # Server-side auth protection middleware
└── proxy.ts # Edge-compatible auth proxy logicThe system utilizes a relational PostgreSQL schema managed via Prisma. Key relationships are designed for high-performance retrieval and data integrity.
| Table | Description | Key Fields |
|---|---|---|
| Blog | Stores article content and metadata. | id, title, slug (unique), summary, content, viewCount, published. |
| BlogImage | Stores secondary gallery images. | id, url, blogId (Foreign Key to Blog). |
| Comment | Stores user interactions. | id, senderName, content, isApproved, blogId. |
| Admin | Manages dashboard credentials. | id, username, password (hashed). |
Entity Relationship Overview:
- A Blog has a one-to-many relationship with BlogImage (up to 6 images).
- A Blog has a one-to-many relationship with Comment.
- Comments are hidden by default (
isApproved: false) until moderated.
Database Diagram - Link Here
- Dynamic URL Slugs: Instead of IDs, articles use readable slugs (e.g.,
/blog/mastering-typescript) to improve search engine rankings. - Server-Side Metadata: Implemented
generateMetadatainapp/blog/[slug]/page.tsxto dynamically inject OpenGraph titles and descriptions for every post.
- Incremental Static Regeneration (ISR): The home page utilizes
revalidate = 60, ensuring the site remains lightning-fast while automatically updating content every minute without manual rebuilds. - Database Indexing: Explicitly added indexes to the
titleandcreatedAtcolumns in theBlogmodel to ensure millisecond-fast performance for search queries and sorting. - View Counting System: Implemented an atomic view increment system using a server-side
PATCHmethod. It includes auseRefguard on the client to prevent duplicate counts during a single session or React StrictMode re-renders.
- Type Safety: Unified the data flow using a custom
BlogWithImagesinterface intypes/index.ts, ensuring end-to-end type safety from Prisma to the Admin Dashboard. - Strict Zod Validation: The comment system includes a custom regex validation (
/^[ก-๙0-9\s]+$/) ensuring that only Thai characters and numbers are submitted. - Secure Authentication: Admin access is protected by JWT (Jose) stored in
HttpOnlysecure cookies.
- Unified Admin Architecture: Leveraged the Shadcn Sidebar component to establish a scalable navigation hub, allowing for the addition of new modules (e.g., Users, Settings, Analytics) without refactoring the core dashboard layout.
- Design Token Strategy: Utilized Tailwind CSS variables and Shadcn UI theming to ensure the entire system is "brand-agnostic," enabling rapid visual rebranding across multiple projects by modifying a single theme file.
- Metadata & SEO Framework: Implemented centralized Sitemap and Robots logic using Next.js Metadata API, creating a reusable pattern for ensuring search engine discoverability across dynamic URL slugs.
- Robust Build Stability: Wrapped search-dependent listing components in
<Suspense>boundaries to handle client-side hydration for search parameters, ensuring the build remains stable and the UI remains responsive during data fetching.
Accessing the Dashboard:
- Navigate to
/admin/login. - Enter the admin credentials (default seeded:
admin/admin123). - Upon successful login, you will be redirected to the Dashboard Overview.
Moderation Flow:
- Manage Posts: Create, edit, or delete articles. You can toggle the
Publishedstatus to control visibility on the public site. - Comment Inbox: View a list of pending comments. Approve them to make them visible on the blog post, or reject them to delete them permanently.
-
Clone the repository:
git clone https://github.com/Lwant-02/Simple-Blog.git cd simple-blog -
Install dependencies:
npm install
-
Environment Configuration: Create a
.envfile in the root and add your database and JWT secrets:DATABASE_URL="postgresql://user:pass@host/db" JWT_SECRET="your_secret_key" BASE_URL="https://your-blog-domain.com"
Dashboard Login:
- URL:
/admin/login - Username:
admin - Password:
admin123
- Dynamic Sitemap: Automatically generated via
sitemap.ts, indexing all public articles. - Robots Management: Configured in
robots.tsto guide crawlers while protecting private admin routes. - Metadata: Comprehensive keyword lists and OpenGraph tags for maximum visibility.
-
Database Setup:
npx prisma generate npx prisma db push npx prisma db seed
-
Run the development server:
npm run dev
- Image Constraints: The system assumes a maximum of 6 secondary images per blog post to maintain UI performance and layout balance.
- Image Hosting: Currently, images are provided via external URLs (Unsplash used for seeding).
- Thai-Only Comments: The validation strictly enforces Thai characters; English or other languages will trigger a validation error by design.
Current Status: 100% of core requirements (CRUD, SEO, Moderation, Validation, Performance, View Tracking) are implemented.
If given more time, I would continue with:
- Rich Text Editor: Integrate TipTap or Quill for a full WYSIWYG authoring experience.
- Cloud Media Storage: Implement direct image uploads to Cloudinary or AWS S3.
- Draft Preview System: Add a "Live Preview" mode to see how articles look before they are published.