A lightning-fast, open-source blog and admin management system built using SvelteKit, Cloudflare Pages, D1 SQL Database, and KV Store. This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).
💡 You can find detailed deployment guides, manuals, and a live demo running this repository's codebase at the official website: sveltekitblog.com!
- Zero Cost Infrastructure: Excluding domain registration, the entire infrastructure (Cloudflare Pages, D1 SQL Database, KV Store) is hosted on Cloudflare's Free Tier, incurring exactly $0 in ongoing server maintenance costs.
- Analytics & Monetization Integrated: The live demo is fully integrated with Google Search Console and Google Analytics 4 (GA4) (visible in the admin dashboard), with a Google AdSense application currently under review.
⚠️ Important: Due to the nature of Cloudflare D1, running and testing the database entirely in a local-only environment is not recommended. The system is designed to integrate and run actively on the live Cloudflare platform. Therefore, this guide focuses on creating resources and deploying directly to the remote Cloudflare environment.
- Project Overview
- Installing Dependencies
- Cloudflare Infrastructure & Initial Deployment (npm run setup)
- Environment Variables & Secret Synchronization (.dev.vars)
- Individual Build & Deployment Commands
- License
- Support
💡 Click the image above to watch the full feature demo video on YouTube.
This project is a monorepo that manages both the blog front-end and the admin dashboard within a single Git repository, fully integrated with Cloudflare's edge-native services.
- apps/blog: SvelteKit-powered blog front-end where anyone can read posts, register/login via email or OAuth, and write comments or guestbook entries.
- apps/admin: SvelteKit-powered admin dashboard for composing posts, viewing Google Analytics (GA4)/AdSense stats, and customizing layout/themes.
- packages/shared: Shared packages containing Drizzle ORM schemas, database structure definitions, utility functions, and internationalization (i18n) configs.
Run the following command in the root directory to link and install all dependencies in the monorepo:
npm install
npm audit fix
💡 Click the image above to watch the full setup and deployment run on YouTube.
This project uses Cloudflare D1 (SQL Database) and KV (Key-Value) namespaces for data persistence. On first use, run the one-click setup script to automatically provision resources in your remote Cloudflare account and deploy the project.
Tip: If you wish to restore configurations (
wrangler.backup.json, etc.) from a backup without resetting existing infrastructure data, run the script in restore mode vianpm run restore.
# Default Mode (Select default language and run a full auto, one-stop build/deployment)
npm run setup
# Interactive Mode (Step-by-step custom setup: choose project names, DB names, etc.)
npm run setup:select- Interactive Setup Mode: Immediately prompts you to select the default blog language (ko/en/ja), then asks whether you want to run the remaining configuration in Full Auto or Custom Interactive mode.
- Cloudflare Authentication: Logs into your Cloudflare account using Wrangler CLI (
wrangler login). This step is automatically skipped if an active session already exists. - Resource Provisioning: Provisions remote D1 databases (
blog-db-*,user-db-*) and a KV namespace (blog-images-kv-*) on Cloudflare. (In Auto mode, default resource names are assigned instantly.) - Remote Schema Migrations: Sets up database tables and seeds initial data according to your chosen default language. (During Auto setup, it is recognized as a fresh installation, and the translation dictionary interactive prompt is automatically skipped.)
- Secure Environment Setup & Deploy: Automatically uploads your local
.dev.varssecrets as Pages Secrets, builds the apps, and publishes them to Cloudflare Pages. (Since the Pages projects are pre-created remotely before building, secrets will sync on the first deployment without skipping.)
Secrets required for running the application (OAuth keys, API credentials, etc.) are provided as templates in each app's .dev.vars.example file. The .dev.vars files containing actual production keys are excluded from Git tracking. Therefore, you must copy the .dev.vars.example files to create .dev.vars in each app directory and enter your credentials before deployment.
- Copy
apps/blog/.dev.vars.exampletoapps/blog/.dev.vars. - Copy
apps/admin/.dev.vars.exampletoapps/admin/.dev.vars. - Open the newly created
.dev.varsfiles and fill in the required keys.
💡 Secret Synchronization Details: Since the
npm run setupscript pre-creates the Cloudflare Pages projects remotely before deployment, the secrets configured in your.dev.varsfiles will be successfully uploaded to Pages Secrets during the initial run. If you need to modify credentials or codebase later, run the respective deploy command (e.g.,npm run deploy:blog) to sync changes.
- 🔴 Must-have Key:
BETTER_AUTH_SECRET: A random secret key (minimum 32 characters recommended) for encrypting session tokens and cookies. Without this key, authentication features will not work.
- 🟢 Dummy Allowed Keys:
GITHUB_*,GOOGLE_*: OAuth keys for social login. If you only plan to use email/password authentication, you can leave these as dummy values (dummy_*) without impacting site launch.
# [Required] Secret key for encryption and signing
BETTER_AUTH_SECRET=your_random_secret_string (minimum 32 characters recommended)
# [Optional] Social login integration (keep dummy values if unused)
GITHUB_CLIENT_ID=dummy_github_id
GITHUB_CLIENT_SECRET=dummy_github_secret
GOOGLE_CLIENT_ID=dummy_google_id
GOOGLE_CLIENT_SECRET=dummy_google_secret
- 🔴 Must-have Key:
ADMIN_PASSWORD: The password required to log in to the admin dashboard. Do not leave this as a dummy value in production.
- 🟢 Dummy Allowed Keys:
GA4_*(Analytics),ADSENSE_*(AdSense): Google reporting keys. If you don't use these features yet, leaving them as dummy values (dummy_*) is completely fine; the dashboard widgets will simply display empty states.
💡 GA4_PRIVATE_KEY must be written in a single line enclosed in double quotes (
") with literal newlines (\n) as shown below.
# [Required] Password for admin dashboard access
ADMIN_PASSWORD=your_actual_admin_password
# [Optional] Google Analytics 4 integration (keep dummy values if unused)
GA4_PROPERTY_ID=dummy_ga4_property_id
GA4_CLIENT_EMAIL=dummy-email@iam.gserviceaccount.com
GA4_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\ndummy_private_key_string\n-----END PRIVATE KEY-----\n"
# [Optional] Google AdSense integration (keep dummy values if unused)
ADSENSE_ACCOUNT_ID=accounts/pub-dummy
ADSENSE_CLIENT_ID=dummy_adsense_client_id.apps.googleusercontent.com
ADSENSE_CLIENT_SECRET=dummy_adsense_secret
ADSENSE_REFRESH_TOKEN=dummy_refresh_token
- You do not need to configure allowed IPs manually.
- The deploy script runs
sync-secrets.jswhich automatically detects your current public IP address and injects it intoapps/admin/.dev.vars, uploading it automatically as a remote Pages Secret. - Note: Only the IP address registered during deployment will be allowed to access the admin panel. If your IP changes, you will need to redeploy or manually update the IP value in the database.
Once the infrastructure resources are provisioned via setup, use the following commands to rebuild and redeploy individual services:
- Deploy Blog Service:
npm run deploy:blog
- Deploy Admin Dashboard:
npm run deploy:admin
This project is open-source and distributed under the GNU Affero General Public License v3.0 (AGPL-3.0). For details, refer to the LICENSE file in the root directory. Under AGPL-3.0, if you modify this software or run it as a network service, you must make your modified source code available to your users.
This project is an open-source initiative licensed under AGPL-3.0 and is maintained for free. If this project has been helpful to you, or if you'd like to support its ongoing development, feel free to buy the developer a coffee! Thank you for your support!
