Skip to content

OscarPastry/Club-Blog

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

40 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🏯 Wabi Sabi Weekly β€” Japanese Club Blog

The official blog for the Japanese Club at VIT Chennai (ζ—₯本θͺžγ‚―ラブ).
A newspaper-inspired web application built with Next.js 16 and Supabase.


πŸ“– Table of Contents


Overview

Wabi Sabi Weekly is a blog platform built for VIT Chennai's Japanese Club. It features a vintage newspaper-style design with a creamy paper texture, serif typography (Playfair Display + Noto Serif JP), and Japanese-inspired aesthetics. Content is authored in Markdown via a password-protected editor and stored in a Supabase PostgreSQL database.


Features

Feature Description
πŸ“° Newspaper Layout Homepage with lead article + sidebar articles in a classic newspaper grid
✍️ Secret Editor Password-protected CMS at /secret-editor for creating, editing, and deleting posts
πŸ“ Markdown Support Write post content in Markdown β€” rendered to HTML via remark + remark-html
πŸ’¬ Comments Readers can leave comments on posts (with optional author names)
❀️ Likes & Views Automatic view counting and like functionality (likes capped at view count)
πŸ“‚ Archives Menu Slide-out hamburger menu listing all posts for easy navigation
🎌 Japanese Typography Noto Serif JP font + vertical text (tategaki) CSS utility
πŸš€ Vercel-Ready Designed for seamless deployment on Vercel

Tech Stack

Technology Purpose
Next.js 16 React framework (App Router)
React 19 UI library
Supabase PostgreSQL database & client SDK
Remark Markdown β†’ HTML processing
date-fns Date formatting utilities
gray-matter Front-matter parsing

Project Structure

Club-Blog/
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ layout.js                   # Root layout (fonts, metadata)
β”‚   β”œβ”€β”€ page.js                     # Homepage β€” lead + sidebar articles
β”‚   β”œβ”€β”€ globals.css                 # Global styles, CSS variables, utilities
β”‚   β”œβ”€β”€ Home.module.css             # Homepage-specific styles
β”‚   β”œβ”€β”€ page.module.css             # Additional page styles
β”‚   β”œβ”€β”€ components/
β”‚   β”‚   β”œβ”€β”€ Header.js               # Blog masthead ("Wabi Sabi Weekly")
β”‚   β”‚   β”œβ”€β”€ Header.module.css
β”‚   β”‚   β”œβ”€β”€ HamburgerMenu.js        # Slide-out archives navigation
β”‚   β”‚   β”œβ”€β”€ HamburgerMenu.module.css
β”‚   β”‚   β”œβ”€β”€ Engagement.js           # Views, likes, and comments widget
β”‚   β”‚   └── Engagement.module.css
β”‚   β”œβ”€β”€ posts/
β”‚   β”‚   └── [slug]/
β”‚   β”‚       └── page.js             # Individual post page (SSG with dynamic routes)
β”‚   β”œβ”€β”€ secret-editor/
β”‚   β”‚   └── page.js                 # Password-protected CMS editor
β”‚   └── api/
β”‚       β”œβ”€β”€ create-post/
β”‚       β”‚   └── route.js            # POST β€” create a new post
β”‚       β”œβ”€β”€ post/
β”‚       β”‚   └── route.js            # GET / PUT / DELETE β€” single post CRUD
β”‚       β”œβ”€β”€ posts-list/
β”‚       β”‚   └── route.js            # GET β€” list all posts
β”‚       └── engagement/
β”‚           └── route.js            # GET / POST β€” views, likes, comments
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ supabase.js                 # Supabase client initialization
β”‚   β”œβ”€β”€ posts.js                    # Post data fetching & markdown processing
β”‚   └── engagement.js               # Engagement logic (views, likes, comments)
β”œβ”€β”€ public/                         # Static assets (SVG icons)
β”œβ”€β”€ package.json
β”œβ”€β”€ next.config.mjs
β”œβ”€β”€ jsconfig.json
└── eslint.config.mjs

Getting Started

Prerequisites

  • Node.js β‰₯ 18.x
  • npm (comes with Node.js)
  • A Supabase project (create one free)

Installation

# Clone the repository
git clone https://github.com/OscarPastry/Club-Blog.git
cd Club-Blog

# Install dependencies
npm install

Environment Variables

Create a .env.local file in the project root:

# Supabase connection
NEXT_PUBLIC_SUPABASE_URL=https://your-project-id.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key-here

# Secret Editor password
NEXT_PUBLIC_EDITOR_PASSWORD=your-secret-password
Variable Description
NEXT_PUBLIC_SUPABASE_URL Your Supabase project URL (found in Project Settings β†’ API)
NEXT_PUBLIC_SUPABASE_ANON_KEY Your Supabase anonymous/public API key
NEXT_PUBLIC_EDITOR_PASSWORD Password to access the /secret-editor CMS page

⚠️ Note: NEXT_PUBLIC_EDITOR_PASSWORD is exposed to the client. This provides basic access controlβ€”not production-grade security. For production, consider server-side authentication.

Database Setup

Create the following tables in your Supabase project's SQL Editor:

-- Posts table
CREATE TABLE posts (
    id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    slug TEXT UNIQUE NOT NULL,
    title TEXT NOT NULL,
    date TEXT NOT NULL,
    author TEXT NOT NULL DEFAULT 'Editor',
    summary TEXT,
    content TEXT,
    views INTEGER DEFAULT 0,
    likes INTEGER DEFAULT 0,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Comments table
CREATE TABLE comments (
    id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    post_slug TEXT REFERENCES posts(slug) ON DELETE CASCADE,
    author TEXT DEFAULT 'Anonymous',
    text TEXT NOT NULL,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

Running Locally

# Development server (with hot reload)
npm run dev

# Production build
npm run build
npm start

The app will be available at http://localhost:3000.


Architecture

Pages & Routing

Route File Description
/ app/page.js Homepage with lead article and sidebar β€” server-rendered
/posts/[slug] app/posts/[slug]/page.js Individual post page with markdown content, engagement widget
/secret-editor app/secret-editor/page.js Password-protected editor for CRUD operations on posts

All pages use revalidate = 0 for fresh data on every request.

API Routes

Endpoint Method Description
/api/create-post POST Create a new post (auto-generates a unique slug from the title)
/api/post?id=<slug> GET Fetch a single post by slug
/api/post PUT Update an existing post
/api/post?id=<slug> DELETE Delete a post by slug
/api/posts-list GET List all posts sorted by date (newest first)
/api/engagement?slug=<slug> GET Get views, likes, and comments for a post
/api/engagement POST Perform an engagement action (view, like, comment, delete-comment)

Engagement Actions (POST /api/engagement)

// Increment view
{ "slug": "post-slug", "action": "view" }

// Like a post (capped at view count)
{ "slug": "post-slug", "action": "like" }

// Add a comment
{ "slug": "post-slug", "action": "comment", "payload": { "text": "...", "author": "Name" } }

// Delete a comment (editor use)
{ "slug": "post-slug", "action": "delete-comment", "payload": { "commentId": 123 } }

Library Modules

Module Purpose
lib/supabase.js Initializes and exports the Supabase client using environment variables
lib/posts.js getSortedPostsData(), getAllPostIds(), getPostData(slug) β€” fetches post data from Supabase and converts Markdown to HTML
lib/engagement.js getPostEngagement(), incrementView(), incrementLike(), addComment(), deleteComment() β€” manages engagement data in Supabase

Components

Component Type Description
Header Server Blog masthead displaying "Wabi Sabi Weekly", week number, theme, and Japanese text
HamburgerMenu Client Slide-out drawer with home link and full post archive list
Engagement Client Interactive widget showing views/likes counters, comment list, and comment submission form

Deployment

This project is optimized for Vercel:

  1. Push your repository to GitHub
  2. Import the project in Vercel Dashboard
  3. Add the environment variables (NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY, NEXT_PUBLIC_EDITOR_PASSWORD) in Project Settings β†’ Environment Variables
  4. Deploy β€” Vercel will auto-detect Next.js and configure the build

Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/my-feature
  3. Commit your changes: git commit -m "Add my feature"
  4. Push to the branch: git push origin feature/my-feature
  5. Open a Pull Request

License

This project is private to the Japanese Club at VIT Chennai.
For inquiries, contact the club's technical team.

About

Blog site for my club in college

Resources

Stars

Watchers

Forks

Contributors