Skip to content

Repository files navigation

Note Blogs

Personal blog with admin CMS, built with Next.js 16, Drizzle ORM, and PostgreSQL. Supports Markdown writing, image upload via presigned URL, and deployment to AWS Lambda via Docker.

Features

  • Blog & Articles — article list, detail pages with Markdown rendering (GFM support)
  • CMS Admin — CRUD operations (create, edit, delete) with session authentication
  • Markdown Editor — GitHub Flavored Markdown support (tables, code blocks, etc.)
  • Media Upload — image upload via presigned URL to S3
  • Server Actions — form handling without separate API routes
  • Responsive Design — optimal display on desktop and mobile
  • Dark/Light Mode — theme toggle via shadcn/ui

Prerequisites

  • Node.js v22 or higher
  • npm v10 or higher
  • Docker (for deployment)
  • Terraform v1.0+ (for AWS infrastructure)
  • AWS CLI (for AWS deployment)
  • PostgreSQL database (Neon, RDS, or local)

Installation

1. Clone Repository

git clone https://github.com/username/aplikasi-catatan.git
cd aplikasi-catatan

2. Install Dependencies

npm install

3. Setup Environment Variables

Create .env.local file:

DATABASE_URL='postgresql://username:password@host:5432/dbname?sslmode=require'
ADMIN_PASSWORD='your-secure-admin-password'

4. Setup Database

# Push schema to database
npm run db:push

5. Run Development Server

npm run dev

Open http://localhost:3000

Usage

Development

npm run dev          # Run dev server
npm run lint         # Check code with ESLint
npm run build        # Build for production

Database Management

npm run db:push      # Push schema to database
npm run db:generate  # Generate migration files
npm run db:migrate   # Run migrations
npm run db:studio    # Open Drizzle Studio (GUI)

Docker

# Build image
docker build -t aplikasi-catatan .

# Run container
docker run -p 3000:3000 --env-file .env.local aplikasi-catatan

# Or with Docker Compose (app + PostgreSQL)
docker compose up --build

AWS Deployment

npm run infra:init   # Initialize Terraform
npm run infra:plan   # Preview infrastructure
npm run infra:apply  # Create AWS infrastructure
git push origin main # Trigger CI/CD

See DEPLOY.md for full deployment guide.

Pages

Path Function
/ Homepage — list of all articles
/blog/[id] Article detail (Markdown rendering)
/login Admin login
/admin CMS dashboard — article CRUD
/api/health Health check endpoint

Tech Stack

Category Technology
Framework Next.js 16 (App Router)
UI Library React 19
Language TypeScript 5
Styling Tailwind CSS v4
Component shadcn/ui (base-nova)
ORM Drizzle ORM
Database PostgreSQL (Neon / AWS RDS)
Deployment AWS Lambda, CloudFront, S3
CI/CD GitHub Actions
Infra as Code Terraform
Container Docker

Scripts

Command Function
npm run dev Run development server
npm run build Build for production
npm start Run production server
npm run lint ESLint check
npm run db:push Push schema to database
npm run db:generate Generate migration files
npm run db:migrate Run migrations
npm run db:studio Open Drizzle Studio
npm run infra:init Initialize Terraform
npm run infra:plan Preview infrastructure
npm run infra:apply Create AWS infrastructure
npm run infra:destroy Destroy AWS infrastructure

Project Structure

aplikasi-catatan/
├── src/
│   ├── app/              # Next.js App Router
│   │   ├── page.tsx      # Homepage
│   │   ├── login/        # Login page
│   │   ├── admin/        # Admin dashboard
│   │   ├── blog/         # Article detail
│   │   └── api/          # API routes
│   ├── components/       # React components
│   ├── db/               # Database schema & connection
│   └── lib/              # Utilities
├── terraform/            # AWS infrastructure (IaC)
├── lambda/               # AWS Lambda handler
├── scripts/              # Migration scripts
├── public/               # Static assets
├── Dockerfile            # Docker image (standalone)
├── Dockerfile.lambda     # Docker image (AWS Lambda)
└── docker-compose.yml    # Local development

Architecture

AWS Deployment Architecture

┌──────────────────────────────────────────────────────────────────────────────┐
│                         CI/CD Pipeline (GitHub Actions)                      │
│  [ Git Push ] → [ Build ] → [ Drizzle Migration ] → [ ECR ]                │
│                                       ↓                                      │
│                                 [ Lambda Deploy ]                            │
│                                       ↓                                      │
│                              [ CloudFront Invalidation ]                     │
└──────────────────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────────────────┐
│                            Runtime (AWS Cloud)                               │
│                                                                              │
│  [ Users ] → [ CloudFront CDN ] → [ API Gateway ] → [ Lambda (Next.js) ]   │
│                                                    ↓                         │
│                                               [ RDS PostgreSQL ]             │
│                                                                              │
│  [ Users ] → [ S3 Bucket ] ← [ Media Upload via Presigned URL ]             │
└──────────────────────────────────────────────────────────────────────────────┘

AWS Infrastructure Components

Component Purpose
CloudFront CDN for static assets and dynamic content caching
API Gateway (HTTP API) REST API endpoint routing to Lambda
Lambda Serverless Next.js application runtime
RDS PostgreSQL Managed database (16.1, db.t3.micro)
S3 Media storage for uploaded images
ECR Docker image repository
VPC Isolated network with public/private subnets
IAM Roles Fine-grained permissions for each service

Data Flow

  1. Read Request: User → CloudFront → API Gateway → Lambda → RDS
  2. Write Request: Admin → Lambda → RDS
  3. Media Upload: Admin → S3 (presigned URL) → Lambda stores reference in RDS
  4. Deployment: Git push → GitHub Actions → ECR → Lambda update → CloudFront invalidation

Security

  • HTTPS only via CloudFront and API Gateway
  • Environment variables for sensitive data (DATABASE_URL, ADMIN_PASSWORD, AWS credentials)
  • HMAC sessions for admin authentication
  • IAM roles with least-privilege permissions
  • VPC isolates Lambda and RDS from public internet
  • S3 bucket policy restricts access to Lambda only

See DEPLOY.md for detailed deployment instructions.

About

Production-grade serverless blog architecture built with Next.js 16, Drizzle ORM, and PostgreSQL, fully provisioned on AWS via Terraform & GitHub Actions.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages