Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 08:25:30 +08:00
commit cc481ebf7e
18 changed files with 3271 additions and 0 deletions

63
templates/11ty/config.yml Normal file
View File

@@ -0,0 +1,63 @@
# Sveltia CMS Configuration for 11ty (Eleventy)
# Place this file in: admin/config.yml
backend:
name: github
repo: owner/repo # Change to your GitHub repository
branch: main
base_url: https://your-worker.workers.dev # Your Cloudflare Workers OAuth proxy URL
# Media storage
media_folder: src/assets/images
public_folder: /assets/images
# Optional: Image optimization
media_libraries:
default:
config:
max_file_size: 5242880
slugify_filename: true
transformations:
raster_image:
format: webp
quality: 85
width: 2048
height: 2048
# Collections
collections:
# Blog Posts
- name: blog
label: Blog Posts
folder: src/posts
create: true
slug: '{{slug}}'
fields:
- label: Title
name: title
widget: string
- label: Description
name: description
widget: text
required: false
- label: Date
name: date
widget: datetime
date_format: 'YYYY-MM-DD'
time_format: false
- label: Tags
name: tags
widget: list
required: false
- label: Featured Image
name: image
widget: image
required: false
- label: Body
name: body
widget: markdown

12
templates/11ty/index.html Normal file
View File

@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Content Manager</title>
</head>
<body>
<!-- Sveltia CMS -->
<script src="https://unpkg.com/@sveltia/cms@0.113.3/dist/sveltia-cms.js" type="module"></script>
</body>
</html>

View File

@@ -0,0 +1,347 @@
# Cloudflare Workers OAuth Proxy Setup
Complete guide to deploying Sveltia CMS authentication using Cloudflare Workers.
---
## Overview
This OAuth proxy enables Sveltia CMS to authenticate with GitHub or GitLab without requiring a backend server. The Worker handles the OAuth flow securely.
**Official Repository**: https://github.com/sveltia/sveltia-cms-auth
---
## Prerequisites
- Cloudflare account (free tier works)
- GitHub or GitLab account
- Wrangler CLI installed (`npm install -g wrangler`)
- Git repository with Sveltia CMS
---
## Step 1: Deploy the Worker
### Option A: Use Official Repository (Recommended)
```bash
# Clone the official auth worker
git clone https://github.com/sveltia/sveltia-cms-auth
cd sveltia-cms-auth
# Install dependencies
npm install
# Login to Cloudflare (if not already logged in)
npx wrangler login
# Deploy to Workers
npx wrangler deploy
```
**Output**:
```
⛅️ wrangler 3.x.x
-------------------
Uploaded sveltia-cms-auth (x.x KiB)
Published sveltia-cms-auth (x.xx sec)
https://sveltia-cms-auth.<your-subdomain>.workers.dev
```
**Save this URL** - you'll need it later!
---
### Option B: One-Click Deploy
1. Visit https://github.com/sveltia/sveltia-cms-auth
2. Click the "Deploy to Cloudflare Workers" button
3. Follow the deployment wizard
4. Note the deployed Worker URL
---
### Option C: Use This Template
If you want to customize the Worker:
1. Copy template to your project:
```bash
mkdir -p workers/sveltia-auth
cp templates/cloudflare-workers/* workers/sveltia-auth/
```
2. Update `wrangler.jsonc` with your account ID
3. Deploy:
```bash
cd workers/sveltia-auth
npx wrangler deploy
```
---
## Step 2: Register OAuth App on GitHub
1. **Go to GitHub Settings:**
https://github.com/settings/developers
2. **Click "New OAuth App"**
3. **Fill in details:**
- **Application name**: `Your Site CMS` (or any name)
- **Homepage URL**: `https://yourdomain.com` (your actual site)
- **Authorization callback URL**: `https://sveltia-cms-auth.<your-subdomain>.workers.dev/callback`
- ⚠️ **Critical**: This must be the Worker URL + `/callback`
- ❌ **NOT**: `https://yourdomain.com/callback`
- ✅ **Example**: `https://sveltia-cms-auth.my-account.workers.dev/callback`
4. **Click "Register application"**
5. **Save these values:**
- **Client ID**: `Ov23li...` (visible immediately)
- **Client Secret**: Click "Generate a new client secret" and copy it (shown once!)
---
## Step 3: Configure Worker Environment Variables
Set the secrets using Wrangler CLI:
```bash
cd sveltia-cms-auth # or your Worker directory
# Set GitHub Client ID
npx wrangler secret put GITHUB_CLIENT_ID
# Paste your Client ID when prompted
# Set GitHub Client Secret
npx wrangler secret put GITHUB_CLIENT_SECRET
# Paste your Client Secret when prompted
```
**Optional**: Restrict to specific domains:
```bash
npx wrangler secret put ALLOWED_DOMAINS
# Enter domains when prompted, e.g.: yourdomain.com,*.yourdomain.com
```
**Wildcards**:
- `yourdomain.com` - Exact match only
- `*.yourdomain.com` - All subdomains (www.yourdomain.com, blog.yourdomain.com)
- `yourdomain.com,*.yourdomain.com` - Both root and subdomains
---
## Step 4: Update Sveltia CMS Config
Add the `base_url` to your CMS configuration:
```yaml
# static/admin/config.yml (Hugo)
# or admin/config.yml (Jekyll/11ty)
# or public/admin/config.yml (Astro/Next.js)
backend:
name: github
repo: owner/repo # Your GitHub repository
branch: main # Your default branch
base_url: https://sveltia-cms-auth.<your-subdomain>.workers.dev # ← Add this line
```
**Example**:
```yaml
backend:
name: github
repo: jezweb/my-blog
branch: main
base_url: https://sveltia-cms-auth.my-account.workers.dev
```
---
## Step 5: Test Authentication
1. **Start your local dev server:**
```bash
hugo server # or jekyll serve, or npm run dev
```
2. **Open admin in browser:**
```
http://localhost:1313/admin/ # Hugo
http://localhost:4000/admin/ # Jekyll
http://localhost:8080/admin/ # 11ty
http://localhost:4321/admin/ # Astro
```
3. **Click "Login with GitHub"**
4. **Authorize the app** when GitHub asks
5. **You should be redirected back** to the CMS with content loaded
---
## Step 6: Deploy Your Site
1. **Commit changes:**
```bash
git add static/admin/config.yml # or your admin path
git commit -m "Add Cloudflare Workers OAuth for Sveltia CMS"
git push
```
2. **Deploy to your hosting:**
- Cloudflare Pages: Automatic on push
- Vercel: Automatic on push
- Netlify: Automatic on push
- GitHub Pages: GitHub Actions workflow
3. **Test on production:**
```
https://yourdomain.com/admin/
```
---
## GitLab Setup (Alternative)
If using GitLab instead of GitHub:
### 1. Create GitLab Application
1. Go to https://gitlab.com/-/profile/applications
2. Click "Add new application"
3. Fill in:
- **Name**: `Your Site CMS`
- **Redirect URI**: `https://sveltia-cms-auth.<your-subdomain>.workers.dev/callback`
- **Scopes**: Check `api` and `write_repository`
4. Click "Save application"
5. Copy Application ID and Secret
### 2. Set Worker Secrets
```bash
npx wrangler secret put GITLAB_APPLICATION_ID
# Paste Application ID
npx wrangler secret put GITLAB_SECRET
# Paste Secret
```
### 3. Update CMS Config
```yaml
backend:
name: gitlab
repo: group/project
branch: main
base_url: https://sveltia-cms-auth.<your-subdomain>.workers.dev
```
---
## Troubleshooting
### Authentication Fails
**Problem**: "Error: Failed to authenticate"
**Solutions**:
1. Check callback URL matches exactly (Worker URL + `/callback`)
2. Verify secrets are set: `npx wrangler secret list`
3. Test Worker directly: `curl https://your-worker.workers.dev/health`
4. Check browser console for CORS errors
---
### Redirect to Wrong Domain
**Problem**: Redirects to `api.netlify.com/auth`
**Solutions**:
1. Ensure `base_url` is in config.yml
2. Hard refresh browser (Ctrl+Shift+R)
3. Clear browser cache
---
### CORS Errors
**Problem**: "Cross-Origin-Opener-Policy blocked"
**Solutions**:
1. Add COOP header to site (see SKILL.md Error #8)
2. Set `Cross-Origin-Opener-Policy: same-origin-allow-popups`
3. For Cloudflare Pages, add `_headers` file:
```
/*
Cross-Origin-Opener-Policy: same-origin-allow-popups
```
---
### Worker Not Found (404)
**Problem**: Worker URL returns 404
**Solutions**:
1. Verify deployment: `npx wrangler deployments list`
2. Check Worker name in `wrangler.jsonc`
3. Wait 1-2 minutes after deployment (DNS propagation)
---
## Security Best Practices
1. **Never commit secrets** - Use `npx wrangler secret put`
2. **Restrict domains** - Set `ALLOWED_DOMAINS` for production
3. **Use HTTPS only** - Sveltia CMS requires secure context
4. **Rotate secrets periodically** - Update GitHub OAuth secrets every 6-12 months
5. **Monitor access logs** - Check Cloudflare Workers dashboard for unusual activity
---
## Custom Domain (Optional)
To use a custom domain for your OAuth Worker:
1. **Add Worker route in Cloudflare:**
- Dashboard > Workers > Your Worker > Triggers
- Add custom domain: `auth.yourdomain.com`
2. **Update GitHub OAuth callback:**
- Change to: `https://auth.yourdomain.com/callback`
3. **Update CMS config:**
```yaml
backend:
base_url: https://auth.yourdomain.com
```
---
## Cost
**Cloudflare Workers Free Tier**:
- 100,000 requests/day
- 10ms CPU time per request
- More than enough for CMS authentication
**Typical usage**: 50-100 requests/month for small teams
---
## Additional Resources
- **Official Auth Worker**: https://github.com/sveltia/sveltia-cms-auth
- **Sveltia CMS Docs**: https://github.com/sveltia/sveltia-cms
- **Wrangler Docs**: https://developers.cloudflare.com/workers/wrangler/
- **OAuth 2.0 Spec**: https://oauth.net/2/
---
**Last Updated**: 2025-10-24

View File

@@ -0,0 +1,26 @@
{
"name": "sveltia-cms-auth",
"main": "src/index.ts",
"compatibility_date": "2025-10-24",
"account_id": "", // Add your Cloudflare account ID here
// Environment variables (set via: npx wrangler secret put VARIABLE_NAME)
// Required:
// - GITHUB_CLIENT_ID: Your GitHub OAuth App Client ID
// - GITHUB_CLIENT_SECRET: Your GitHub OAuth App Client Secret
//
// Optional:
// - GITLAB_APPLICATION_ID: Your GitLab Application ID
// - GITLAB_SECRET: Your GitLab Application Secret
// - ALLOWED_DOMAINS: Comma-separated list of allowed domains (e.g., "yourdomain.com,*.yourdomain.com")
"vars": {
// Public variables (safe to commit)
"ENVIRONMENT": "production"
},
// For development
"dev": {
"port": 8787
}
}

View File

@@ -0,0 +1,52 @@
# Blog Post Collection Template
# Copy this collection definition to your admin/config.yml
- name: posts
label: Blog Posts
folder: content/posts # Adjust for your framework (e.g., _posts for Jekyll)
create: true
slug: '{{year}}-{{month}}-{{day}}-{{slug}}'
format: yaml # or md, toml, json
fields:
- label: Title
name: title
widget: string
hint: Post title
- label: Date
name: date
widget: datetime
date_format: 'YYYY-MM-DD'
time_format: 'HH:mm:ss'
format: 'YYYY-MM-DDTHH:mm:ssZ'
- label: Draft
name: draft
widget: boolean
default: true
hint: Set to false to publish
- label: Featured Image
name: image
widget: image
required: false
- label: Excerpt / Description
name: description
widget: text
required: false
hint: Short description for SEO
- label: Tags
name: tags
widget: list
required: false
- label: Categories
name: categories
widget: list
required: false
- label: Body
name: body
widget: markdown

View File

@@ -0,0 +1,45 @@
# Documentation Page Collection Template
# Copy this collection definition to your admin/config.yml
- name: docs
label: Documentation
folder: content/docs # Adjust for your framework
create: true
slug: '{{slug}}'
format: yaml
fields:
- label: Title
name: title
widget: string
- label: Description
name: description
widget: text
required: false
hint: Page description for SEO
- label: Order / Weight
name: weight
widget: number
value_type: int
required: false
hint: Sort order (lower numbers appear first)
- label: Category
name: category
widget: select
options:
- Getting Started
- Guides
- API Reference
- Advanced
required: false
- label: Draft
name: draft
widget: boolean
default: false
- label: Body
name: body
widget: markdown

View File

@@ -0,0 +1,78 @@
# Landing Page Collection Template (Structured Content)
# Copy this collection definition to your admin/config.yml
- name: pages
label: Landing Pages
folder: content/pages
create: true
slug: '{{slug}}'
format: json # JSON for structured data
fields:
- label: Title
name: title
widget: string
- label: SEO
name: seo
widget: object
fields:
- label: Meta Title
name: metaTitle
widget: string
required: false
- label: Meta Description
name: metaDescription
widget: text
required: false
- label: OG Image
name: ogImage
widget: image
required: false
- label: Hero Section
name: hero
widget: object
fields:
- label: Headline
name: headline
widget: string
- label: Subheadline
name: subheadline
widget: text
- label: Hero Image
name: image
widget: image
required: false
- label: CTA Button
name: cta
widget: object
fields:
- label: Text
name: text
widget: string
- label: URL
name: url
widget: string
- label: Features
name: features
widget: list
required: false
fields:
- label: Title
name: title
widget: string
- label: Description
name: description
widget: text
- label: Icon
name: icon
widget: image
required: false

113
templates/hugo/config.yml Normal file
View File

@@ -0,0 +1,113 @@
# Sveltia CMS Configuration for Hugo
# Place this file in: static/admin/config.yml
backend:
name: github
repo: owner/repo # Change to your GitHub repository (e.g., jezweb/my-blog)
branch: main # Change if your default branch is different
base_url: https://your-worker.workers.dev # Your Cloudflare Workers OAuth proxy URL
# Media storage
media_folder: static/images/uploads # Where uploaded files are saved
public_folder: /images/uploads # URL path for content files
# Optional: Image optimization
media_libraries:
default:
config:
max_file_size: 5242880 # 5 MB in bytes
slugify_filename: true
transformations:
raster_image:
format: webp # Convert to WebP
quality: 85
width: 2048
height: 2048
svg:
optimize: true
# Collections (content types)
collections:
# Blog Posts
- name: posts
label: Blog Posts
folder: content/posts
create: true
slug: '{{year}}-{{month}}-{{day}}-{{slug}}'
format: yaml # Hugo supports yaml, toml, json
fields:
- label: Title
name: title
widget: string
hint: Post title (required)
- label: Date
name: date
widget: datetime
date_format: 'YYYY-MM-DD'
time_format: 'HH:mm:ss'
format: 'YYYY-MM-DDTHH:mm:ssZ'
hint: Publication date
- label: Draft
name: draft
widget: boolean
default: true
hint: Set to false to publish
- label: Featured Image
name: image
widget: image
required: false
hint: Main post image
- label: Excerpt
name: description
widget: text
required: false
hint: Short description for SEO and previews
- label: Tags
name: tags
widget: list
required: false
hint: Post tags (comma-separated)
- label: Categories
name: categories
widget: list
required: false
hint: Post categories
- label: Body
name: body
widget: markdown
hint: Post content
# Documentation Pages (optional)
- name: docs
label: Documentation
folder: content/docs
create: true
slug: '{{slug}}'
format: yaml
fields:
- label: Title
name: title
widget: string
- label: Description
name: description
widget: text
required: false
- label: Weight
name: weight
widget: number
value_type: int
hint: Sort order (lower numbers appear first)
required: false
- label: Body
name: body
widget: markdown

12
templates/hugo/index.html Normal file
View File

@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Content Manager</title>
</head>
<body>
<!-- Sveltia CMS -->
<script src="https://unpkg.com/@sveltia/cms@0.113.3/dist/sveltia-cms.js" type="module"></script>
</body>
</html>

View File

@@ -0,0 +1,82 @@
# Sveltia CMS Configuration for Jekyll
# Place this file in: admin/config.yml
backend:
name: github
repo: owner/repo # Change to your GitHub repository
branch: main # or 'gh-pages' if using GitHub Pages source branch
base_url: https://your-worker.workers.dev # Your Cloudflare Workers OAuth proxy URL
# Media storage
media_folder: assets/images/uploads
public_folder: /assets/images/uploads
# Optional: Image optimization
media_libraries:
default:
config:
max_file_size: 5242880 # 5 MB
slugify_filename: true
transformations:
raster_image:
format: webp
quality: 85
width: 2048
height: 2048
# Collections
collections:
# Blog Posts
- name: posts
label: Blog Posts
folder: _posts
create: true
slug: '{{year}}-{{month}}-{{day}}-{{slug}}'
fields:
- label: Layout
name: layout
widget: hidden
default: post
- label: Title
name: title
widget: string
- label: Date
name: date
widget: datetime
date_format: 'YYYY-MM-DD'
time_format: 'HH:mm:ss'
format: 'YYYY-MM-DD HH:mm:ss ZZ'
- label: Categories
name: categories
widget: list
required: false
- label: Tags
name: tags
widget: list
required: false
- label: Featured Image
name: image
widget: image
required: false
- label: Body
name: body
widget: markdown
# Pages
- name: pages
label: Pages
files:
- name: about
label: About Page
file: about.md
fields:
- { label: Layout, name: layout, widget: hidden, default: page }
- { label: Title, name: title, widget: string }
- { label: Permalink, name: permalink, widget: hidden, default: /about/ }
- { label: Body, name: body, widget: markdown }

View File

@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Content Manager</title>
</head>
<body>
<!-- Sveltia CMS -->
<script src="https://unpkg.com/@sveltia/cms@0.113.3/dist/sveltia-cms.js" type="module"></script>
</body>
</html>