A modern, cost-optimized blog platform built with Next.js, featuring:
- 3-level category hierarchy
- RAG-powered chatbot using OpenAI
- Full-featured admin panel
- "Deep Sea" themed UI
- Zero-cost convergence architecture
- ✅ 3-level category tree (collapsible)
- ✅ Category filtering pages (
/category/[slug]) - ✅ Blog post listing with ISR caching
- ✅ Table of Contents with scroll spy navigation
- ✅ Breadcrumb navigation (clickable hierarchy)
- ✅ 3-column responsive layout
- ✅ RAG chatbot for Q&A about blog content
- ✅ Dark/Light mode support
- ✅ Responsive "Deep Sea" theme
- ✅ Dashboard with statistics
- ✅ Post management (create, read, edit, delete)
- ✅ Create:
/admin/posts/new - ✅ Edit:
/admin/posts/[slug]/edit(slug-based URL) - ✅ Auto-regenerate embeddings on content change
- ✅ Slug immutability (cannot be changed after creation)
- ✅ Create:
- ✅ Markdown editor (react-md-editor)
- ✅ Category management (3-level hierarchy)
- ✅ Media library (image upload to Supabase Storage)
- ✅ RAG settings configuration
- ✅ Protected routes with middleware
- Framework: Next.js 14 (App Router)
- Database: Supabase (PostgreSQL + pgvector)
- AI: OpenAI (text-embedding-3-small + gpt-4o-mini)
- Deployment: Vercel (Serverless)
- Storage: Supabase Storage
- Auth: Supabase Auth
muse-log/
├── src/
│ ├── app/
│ │ ├── admin/ # Admin panel pages
│ │ │ ├── layout.tsx # Admin layout
│ │ │ ├── page.tsx # Dashboard
│ │ │ ├── posts/
│ │ │ │ ├── new/ # Create post
│ │ │ │ └── [slug]/
│ │ │ │ ├── edit/ # Edit post (Server + Client)
│ │ │ │ │ ├── page.tsx
│ │ │ │ │ └── EditPostForm.tsx
│ │ │ │ └── delete/ # Delete post
│ │ │ ├── categories/ # Category management
│ │ │ ├── media/ # Media library
│ │ │ ├── rag/ # RAG settings
│ │ │ └── settings/ # Blog settings
│ │ ├── api/ # API routes
│ │ │ ├── posts/ # Posts CRUD + embedding
│ │ │ ├── categories/ # Categories CRUD
│ │ │ ├── media/ # Media upload/delete
│ │ │ ├── chat/ # RAG chatbot
│ │ │ └── admin/stats/ # Dashboard stats
│ │ ├── category/[slug]/ # Category filter pages
│ │ ├── posts/[slug]/ # Individual post pages
│ │ ├── login/ # Login page
│ │ └── page.tsx # Public homepage
│ ├── components/
│ │ ├── admin/ # Admin components
│ │ │ ├── AdminNav.tsx
│ │ │ └── ...
│ │ ├── Breadcrumb.tsx # Hierarchical navigation
│ │ ├── CategoryInfo.tsx # Category sidebar
│ │ ├── Header.tsx
│ │ ├── Footer.tsx
│ │ ├── PostCard.tsx # Post preview card
│ │ ├── Sidebar.tsx # Category tree
│ │ ├── TableOfContents.tsx # Scroll spy TOC
│ │ └── ...
│ ├── hooks/
│ │ ├── useLocalStorage.ts # SSR-safe localStorage hook
│ │ └── useScrollSpy.ts # Scroll spy for TOC
│ ├── lib/
│ │ ├── constants.ts # Cache durations, storage keys
│ │ ├── supabase.ts # Client-side Supabase
│ │ ├── supabase-server.ts # Server-side Supabase
│ │ └── utils/
│ │ └── category.ts # Category tree utilities
│ ├── types/
│ │ ├── category.ts # Category, Breadcrumb, TOC types
│ │ └── database.ts # Database types
│ └── middleware.ts # Auth middleware
├── supabase/
│ └── migrations/
│ └── 001_initial_schema.sql # Database schema
├── description.md # Architecture documentation
└── CLAUDE.md # Multi-agent system constitution
- Node.js 18+
- Supabase account
- OpenAI API key
# Clone repository
git clone <your-repo-url>
cd muse-log
# Install dependencies
npm installCreate .env.local:
# Supabase
NEXT_PUBLIC_SUPABASE_URL=https://your-project-id.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
# Admin
NEXT_PUBLIC_ADMIN_EMAIL=your-admin-email@example.com
# OpenAI
OPENAI_API_KEY=sk-proj-your-key- Create a new Supabase project
- Run the migration:
# Copy the contents of supabase/migrations/001_initial_schema.sql
# Paste into Supabase SQL Editor and run- Configure admin email in Supabase:
- Go to Settings > API > Custom PostgreSQL configuration
- Add:
app.admin_email = 'your-admin-email@example.com'
npm run devVisit:
- Public blog:
http://localhost:3000 - Admin panel:
http://localhost:3000/admin - Login:
http://localhost:3000/login
See description.md for detailed explanation of:
- Posts, Categories, Media, Post Embeddings tables
- 3-level category hierarchy
- RLS (Row Level Security) policies
Post and category pages use a responsive 3-column layout:
┌──────────────┬───────────────────────┬──────────────┐
│ Sidebar │ Main Content │ Right Panel │
│ (Category │ (55% width) │ (TOC or │
│ Tree) │ │ Category Info)│
│ Collapsible │ Post/Category List │ Collapsible │
└──────────────┴───────────────────────┴──────────────┘
- Left Sidebar: Category tree with expand/collapse
- Main Content: Post content or category post list
- Right Sidebar:
- Post page: Table of Contents with scroll spy
- Category page: Category description and subcategories
Breadcrumb Navigation:
- Shows hierarchical path (Home > IT > Backend > Node.js)
- All parent categories are clickable links
- Current page shown without link
- Fully accessible with ARIA labels
Table of Contents:
- Auto-extracts H2 and H3 headings from markdown
- Scroll spy highlights active section
- Smooth scroll to section on click
- Collapse state persisted in localStorage
- Posts list: ISR with 1-hour revalidation
- Individual posts: ISR with 24-hour revalidation
- Categories: ISR with 24-hour revalidation (includes static generation at build time)
- Category tree: Client-side cache (1 hour in localStorage)
- Images: Immutable cache (1 year)
- Posts are embedded using
text-embedding-3-smallon create/update - User questions are embedded
- pgvector searches for similar posts (top 3)
- GPT-4o-mini generates answers using post content as context
Cost: ~$0.0007 per chat conversation (very affordable!)
This project follows a zero-cost convergence principle:
lim(cost) → $2/month as traffic → moderate
- Static-first rendering (ISR)
- Minimal OpenAI API calls
- Supabase free tier (500MB DB, 1GB Storage)
- Vercel free tier
- No paid SaaS dependencies
- RLS policies protect all database tables
- Middleware protects
/adminroutes - Admin email verification
- Supabase Auth for session management
The "Deep Sea" theme uses CSS variables:
/* Light Mode */
--color-primary: #0c8bc9 (Ocean Blue)
--bg-primary: #f8fafc
--text-primary: #1e293b
/* Dark Mode */
--color-primary: #14a2e0
--bg-primary: #020715 (Deep Sea)
--text-primary: #e2e8f0Edit src/app/globals.css to customize.
Default 3-level structure:
IT (Level 1)
├── Backend (Level 2)
│ ├── Node.js (Level 3)
│ └── Python (Level 3)
└── Frontend (Level 2)
├── React (Level 3)
└── Vue (Level 3)
Manage via Admin Panel → Categories.
- Architecture: See
description.md - Multi-Agent System: See
CLAUDE.md - API Reference: See inline comments in
/src/app/api/*
- Push to GitHub
- Import project to Vercel
- Add environment variables
- Deploy
- Set up Supabase custom config (admin email)
- Create admin user in Supabase Auth
- Test login at
/login - Access admin at
/admin
- Go to
/admin/posts/new - Write title, content (Markdown), excerpt
- Select category
- Check "Publish immediately" or save as draft
- Embedding is auto-generated for published posts
- Go to
/admin/posts - Click on a post to edit (or navigate to
/admin/posts/[slug]/edit) - Update title, content, category, or excerpt
- Note: Slug cannot be changed (to preserve URL integrity)
- Save changes
- If content/title changed and post is published:
- Embedding is automatically regenerated
- Changes reflect in RAG chatbot within minutes
- Go to
/admin/posts - Click delete button on a post
- Confirms deletion
- Post embeddings automatically deleted (CASCADE)
- Go to
/admin/categories - Create categories at appropriate levels (1, 2, or 3)
- Categories display as tree in sidebar
- Go to
/admin/media - Click "Upload Image"
- Copy URL to use in posts
This is a personal project, but suggestions are welcome!
MIT
Built with:
- Next.js
- Supabase
- OpenAI
- react-md-editor
Note: This project was built following the CLAUDE.md multi-agent system constitution to ensure quality, security, and cost optimization.