Files
voyage/apps/public-web/ARCHITECTURE.md

7.7 KiB
Raw Blame History

VOYAGE Blog & Admin Architecture Documentation

Purpose

This document describes the architecture of the VOYAGE public blog and its internal admin system.

It covers folder structure, routing, data flow, authentication, and the admin UI shell.

A new developer should be able to understand:

  • how blog posts are loaded and rendered
  • how routing works (public + admin)
  • how authentication is handled
  • where and how to extend the system

High-Level Overview

The VOYAGE public site is implemented using the Next.js App Router inside a monorepo, with authentication delegated to a Spring Boot backend.

Key technologies:

  • Next.js (App Router, Server Components)
  • Spring Boot (session-based auth)
  • Tailwind CSS (UI styling)
  • File-based content (TXT / MD / MDX)

Core principles:

  • Public content is always accessible
  • Admin tools are protected via backend session
  • No duplicate authentication logic
  • Clear separation between public site and admin system

Monorepo Context

This repository is a monorepo containing multiple applications.

Relevant apps:

  • apps/public-web → Public website, blog, and admin UI
  • apps/workspace-api → Spring Boot backend (auth, API, DB)

Other apps (not covered here):

  • workspace-ui

Folder Structure (Current)

apps/public-web/ │ ├── app/ │ ├── (site)/ → Public site route group │ │ ├── layout.tsx → Shared public layout (TopBar, globals) │ │ ├── page.tsx → Homepage │ │ ├── about/ │ │ │ └── page.tsx → Static About page │ │ ├── blog/ │ │ │ ├── layout.tsx → Blog-specific layout │ │ │ ├── page.tsx → Blog index (list of posts) │ │ │ └── [slug]/ │ │ │ └── page.tsx → Dynamic blog post page │ │ └── admin/ │ │ ├── layout.tsx → Admin auth guard (server-side) │ │ ├── page.tsx → Admin dashboard (sidebar + header) │ │ └── posts/ │ │ └── page.tsx → Admin posts manager │ │ │ ├── global.css → Tailwind + global styles │ └── layout.tsx → Root layout (imports global.css) │ ├── components/ │ └── shell/ │ └── TopBar.tsx → Shared public navigation bar │ ├── visuals/ │ └── ImageSphereSketch.tsx → Creative / visual components │ ├── content/ │ └── posts/ │ ├── YY-MM-DD-title.txt → Blog post source files (current) │ ├── YYYY-MM-DD-title.md → (optional / supported) │ └── YYYY-MM-DD-title.mdx → (optional / supported) │ ├── lib/ │ └── posts.ts → Blog data loading & parsing logic │ ├── public/ │ └── blog/ │ └── visuals/ │ ├── first.jpg │ ├── second.jpg │ └── ...

Routing Logic

Routing is defined entirely by the folder structure.

Public routes:

  • / → app/(site)/page.tsx
  • /about → app/(site)/about/page.tsx
  • /blog → app/(site)/blog/page.tsx
  • /blog/[slug] → app/(site)/blog/[slug]/page.tsx

Admin routes:

  • /admin → Admin dashboard (protected)
  • /admin/posts → Admin post manager (protected)

Dynamic route parameters:

  • [slug] is derived from the filename in content/posts

Blog Data Flow (Rendering a Post)

  1. User navigates to: /blog/some-post-slug

  2. Next.js resolves: app/(site)/blog/[slug]/page.tsx

  3. Page receives: params.slug

  4. The page calls: getPostBySlug(slug) from lib/posts.ts

  5. lib/posts.ts:

    • Reads a file from content/posts
    • Supports .txt, .md, .mdx
    • Strips date prefix from filename
    • Returns structured post data
  6. Page renders:

    • Shared public layout
    • Post metadata
    • Parsed content
  7. If the slug does not exist:

    • notFound() is triggered

Admin System Overview

The admin system is an internal tool, not a CMS yet.

Current capabilities:

  • Admin dashboard UI
  • Post listing / detection
  • Backend session verification
  • Logout handling

Admin UI principles:

  • Clean, minimal, internal-tool aesthetic
  • Sidebar + large system header
  • No duplicated navigation actions
  • Tailwind-based styling

Admin Authentication & Security

Authentication is not handled by Next.js.

Instead, it is delegated to the Spring Boot backend (workspace-api).

Key principles:

  • Single source of truth for auth (Spring)
  • Session-based authentication (JSESSIONID)
  • No JWT
  • No duplicate auth logic in frontend
  • Admin routes require a valid backend session

Admin Route Protection (Frontend)

Protection is implemented in:

app/(site)/admin/layout.tsx

Strategy:

  • Admin layout is an async Server Component
  • On every request:
    • Calls backend endpoint /api/me
    • Forwards incoming cookies manually
    • If response is 401 → redirect to /login
    • If response is 200 → render admin UI
    • Optional role check (ROLE_ADMIN)

Important technical detail:

  • Server-side fetch MUST forward cookies explicitly
  • Using headers().get("cookie") (async)
  • credentials: "include" is NOT sufficient in Server Components

Login Flow (End-to-End)

  1. User navigates to: http://localhost:3000/admin

  2. Admin layout fetches: GET http://localhost:8080/api/me

  3. If not authenticated:

    • Backend returns 401
    • Next.js redirects to /login (frontend)
  4. Frontend /login redirects to backend: GET http://localhost:8080/login-redirect?redirect=http://localhost:3000/admin

  5. Backend:

    • Stores redirect target in session
    • Redirects to /login (no query params)
  6. Spring Security default login page is shown

  7. User submits credentials

  8. On successful login:

  9. Admin UI loads successfully

Backend Endpoints Involved

/api/me

  • Returns current authenticated user
  • 200 → logged in
  • 401 → not authenticated
  • Never redirects

/login

  • Spring Security default login page
  • HTML form-based login

/login-redirect

  • Helper endpoint
  • Stores redirect target in session
  • Avoids unsupported query params on /login

/logout

  • Invalidates session
  • Clears JSESSIONID cookie

Admin Posts Manager

Route:

  • /admin/posts

Responsibilities:

  • Reads files from content/posts on the server
  • Detects available posts (.txt / .md / .mdx)
  • Derives slugs from filenames
  • Displays debug info (detected paths, files)
  • Links to public blog pages

This is intentionally read-only for now.

Why This Architecture

  • Clear separation of concerns
  • Public content stays simple and fast
  • Admin tools are protected and internal
  • No auth duplication
  • SSR-safe and production-ready
  • Scales cleanly to future CMS features

How to Extend (Future)

  • Admin post editor UI
  • Draft / preview mode
  • Role-based admin tools
  • Publishing workflow
  • CMS integration
  • Protected preview links

Current Status

  • App Router fully set up
  • Public blog routing stable
  • Content loading via filesystem stable
  • Tailwind styling active
  • Admin auth flow stable and tested
  • Admin dashboard + posts manager implemented
  • Ready for further UX polish and feature extensions