Skip to content

herokwon/blog

Repository files navigation

Introduction

Personal blog built with SvelteKit. Focused on fast, readable posts, clean navigation, and a minimal authoring workflow.


✨ Features

  • Post listing and detail pages
  • Tag and category
  • SEO-friendly metadata
  • Responsive layout
  • Milkdown-based editor integration
  • Cloudflare D1-based content storage and management
  • Admin authentication and access control — See Authentication

🛠️ Tech Stack

svelte typescript tailwindcss prettier eslint editorconfig vitest cloudflare d1 cloudflare r2 cloudflare workers


📍 Getting Started

Install dependencies:

pnpm install

Run the dev server:

pnpm dev

Build for production:

pnpm build

Preview the production build:

pnpm preview

🧪 Testing

Prerequisites:

Install dependencies and Playwright browsers:

pnpm install
pnpm exec playwright install chromium --with-deps

Run the full test suite (this project uses a small test runner wrapper that launches a single Playwright Chromium server and runs Vitest):

pnpm test

📖 Content

This blog uses Milkdown as the writting editor and stores post data in posts table from Cloudflare D1

Content flow

  1. Write and edit content in Milkdown.
  2. Convert editor output to Markdown format.
  3. Upload and manage content files in Cloudflare D1.
  4. Read content from posts table in the app and render post pages.

Key capabilities

  • Rich text authoring with Markdown workflow
  • Centralized content storage on D1
  • Easy post update and asset management
  • Scalable content delivery for blog pages

🚀 Deployment

This project targets Cloudflare Workers. Use the SvelteKit adapter configuration in svelte.config.ts and deploy with your preferred workflow.


🗄️ Database & Migrations

This project uses Cloudflare D1 for data storage. Recent migrations include:

Apply migrations using your D1 tooling or the Cloudflare D1 dashboard.


🔐 Authentication

New users and sessions tables were added for auth. Store password hashes with a secure algorithm (bcrypt/argon2). Regularly remove expired sessions, e.g.:

DELETE FROM sessions WHERE expires_at < strftime('%s','now');

Consider adding indexes on user_id and expires_at if session queries or cleanup run frequently.


📡 API

The OpenAPI spec was updated to v0.2.0 and response schemas were refactored. See openapi.yml for details.


📜 License

Distributed under the MIT license. See LICENSE for more information.