@fydemy/cms 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,20 @@
1
+ # CMS Authentication (Required)
2
+ CMS_ADMIN_USERNAME=admin
3
+ CMS_ADMIN_PASSWORD=your_secure_password_here
4
+ CMS_SESSION_SECRET=your-secret-key-must-be-at-least-32-characters-long
5
+
6
+ # ===== STORAGE OPTIONS (Choose one) =====
7
+
8
+ # Option 1: GitHub Storage (Production)
9
+ # Uncomment these if you want to use GitHub for storage
10
+ # GITHUB_TOKEN=ghp_your_github_token_here
11
+ # GITHUB_REPO=username/repository
12
+ # GITHUB_BRANCH=main
13
+
14
+ # Option 2: Cloudflare R2 Storage (Production)
15
+ # Uncomment these if you want to use Cloudflare R2 for storage
16
+ # CLOUDFLARE_ACCOUNT_ID=your-cloudflare-account-id
17
+ # CLOUDFLARE_ACCESS_KEY_ID=your-r2-access-key-id
18
+ # CLOUDFLARE_SECRET_ACCESS_KEY=your-r2-secret-access-key
19
+ # NEXT_PUBLIC_R2_PUBLIC_URL=https://your-bucket.r2.dev
20
+ # R2_BUCKET_NAME=my-cms-bucket
@@ -0,0 +1,41 @@
1
+ name: CD
2
+
3
+ on:
4
+ release:
5
+ types: [created]
6
+
7
+ jobs:
8
+ publish:
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ contents: read
12
+ id-token: write
13
+
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - uses: pnpm/action-setup@v3
18
+ with:
19
+ version: 9
20
+
21
+ - name: Use Node.js 20
22
+ uses: actions/setup-node@v4
23
+ with:
24
+ node-version: "20.x"
25
+ registry-url: "https://registry.npmjs.org"
26
+ cache: "pnpm"
27
+
28
+ - name: Install dependencies
29
+ run: pnpm install --frozen-lockfile
30
+
31
+ - name: Build
32
+ run: pnpm build
33
+ working-directory: packages/core
34
+
35
+ - name: Create .npmrc
36
+ run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc
37
+ working-directory: packages/core
38
+
39
+ - name: Publish to NPM
40
+ run: pnpm publish --access public --no-git-checks
41
+ working-directory: packages/core
@@ -0,0 +1,43 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-latest
12
+
13
+ strategy:
14
+ matrix:
15
+ node-version: [18.x, 20.x]
16
+
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - uses: pnpm/action-setup@v3
21
+ with:
22
+ version: 9
23
+
24
+ - name: Use Node.js ${{ matrix.node-version }}
25
+ uses: actions/setup-node@v4
26
+ with:
27
+ node-version: ${{ matrix.node-version }}
28
+ cache: "pnpm"
29
+
30
+ - name: Install dependencies
31
+ run: pnpm install --frozen-lockfile
32
+
33
+ - name: Type Check
34
+ run: pnpm type-check
35
+ working-directory: packages/core
36
+
37
+ - name: Run Tests
38
+ run: pnpm test
39
+ working-directory: packages/core
40
+
41
+ - name: Build
42
+ run: pnpm build
43
+ working-directory: packages/core
@@ -0,0 +1,92 @@
1
+ # Cloudflare R2 Storage Integration
2
+
3
+ ## Summary
4
+
5
+ The CMS has been updated to strictly support **Cloudflare R2** storage (removing references to S3 and Vercel Blob). The environment variables have been updated to match your requested format.
6
+
7
+ ## Environment Variables
8
+
9
+ When setting up Cloudflare R2 storage, use these environment variables:
10
+
11
+ ```env
12
+ # Cloudflare R2 Storage
13
+ CLOUDFLARE_ACCOUNT_ID=your-account-id
14
+ CLOUDFLARE_ACCESS_KEY_ID=your-access-key-id
15
+ CLOUDFLARE_SECRET_ACCESS_KEY=your-secret-access-key
16
+ NEXT_PUBLIC_R2_PUBLIC_URL=https://your-public-url.r2.dev
17
+ R2_BUCKET_NAME=my-bucket
18
+ ```
19
+
20
+ ## How to Get These Values
21
+
22
+ ### 1. CLOUDFLARE_ACCOUNT_ID
23
+
24
+ - Log in to your Cloudflare dashboard
25
+ - Your Account ID is visible in the URL or in the right sidebar
26
+
27
+ ### 2. CLOUDFLARE_ACCESS_KEY_ID & CLOUDFLARE_SECRET_ACCESS_KEY
28
+
29
+ - Go to R2 in your Cloudflare dashboard
30
+ - Click "Manage R2 API Tokens"
31
+ - Create a new API token with read/write permissions
32
+ - Save both the Access Key ID and Secret Access Key
33
+
34
+ ### 3. NEXT_PUBLIC_R2_PUBLIC_URL
35
+
36
+ - In your R2 bucket settings, go to "Settings"
37
+ - Under "Public Access", enable public access if needed
38
+ - Copy the public bucket URL (e.g., `https://pub-xxxxx.r2.dev`)
39
+ - Or set up a custom domain for your R2 bucket
40
+
41
+ ### 4. R2_BUCKET_NAME
42
+
43
+ - The name of your R2 bucket (e.g., `my-cms-content`)
44
+
45
+ ## Changes Made
46
+
47
+ ### 1. `/packages/core/src/init/setup.ts`
48
+
49
+ - Updated storage provider selection to only show "GitHub" or "Cloudflare R2"
50
+ - Changed environment variable names from generic `STORAGE_*` to Cloudflare-specific names
51
+ - Removed references to S3 and Vercel Blob
52
+
53
+ ### 2. `/packages/core/src/content/storage.ts`
54
+
55
+ - Added `CloudflareR2Storage` class that implements the `StorageProvider` interface
56
+ - Uses AWS S3 SDK (already installed) to communicate with Cloudflare R2
57
+ - Implements all required methods:
58
+ - `readFile()` - Read markdown files from R2
59
+ - `writeFile()` - Write markdown files to R2
60
+ - `deleteFile()` - Delete files from R2
61
+ - `listFiles()` - List files and directories in R2
62
+ - `exists()` - Check if a file exists
63
+ - `uploadFile()` - Upload binary files (images, PDFs, etc.)
64
+ - Updated `getStorageProvider()` to detect and use Cloudflare R2 when credentials are present
65
+
66
+ ## Storage Provider Priority
67
+
68
+ The system will automatically select the storage provider in this order:
69
+
70
+ 1. **Cloudflare R2** - If `CLOUDFLARE_ACCOUNT_ID`, `CLOUDFLARE_ACCESS_KEY_ID`, and `CLOUDFLARE_SECRET_ACCESS_KEY` are set
71
+ 2. **GitHub** - If `NODE_ENV=production` and `GITHUB_TOKEN` is set
72
+ 3. **Local Storage** - Default for development
73
+
74
+ ## File Structure in R2
75
+
76
+ - Content files: `content/your-file.md`
77
+ - Uploaded files: `uploads/filename.ext`
78
+
79
+ ## Public URL Format
80
+
81
+ Uploaded files will be accessible at:
82
+
83
+ ```
84
+ {NEXT_PUBLIC_R2_PUBLIC_URL}/uploads/filename.ext
85
+ ```
86
+
87
+ ## Notes
88
+
89
+ - The AWS S3 SDK (`@aws-sdk/client-s3`) is already installed as a dependency
90
+ - Cloudflare R2 is S3-compatible, so we use the S3 client with R2 endpoints
91
+ - The implementation automatically sets the region to "auto" for R2
92
+ - Content-Type headers are automatically set for uploaded files
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Fydemy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/QUICKSTART.md ADDED
@@ -0,0 +1,80 @@
1
+ # @fydemy/cms - Quick Start
2
+
3
+ ## What You Have
4
+
5
+ A complete, minimal CMS package for Next.js:
6
+
7
+ ```
8
+ 📦 @fydemy/cms (packages/core)
9
+ - File-based markdown storage
10
+ - GitHub integration for production
11
+ - Simple auth (env username/password)
12
+ - TypeScript support
13
+
14
+ 🚀 Demo App (apps/dev)
15
+ - Example Next.js application
16
+ - Admin dashboard at /admin
17
+ - Login page, editor, file manager
18
+ ```
19
+
20
+ ## Run the Demo
21
+
22
+ 1. **Copy environment file:**
23
+
24
+ ```bash
25
+ cd apps/dev
26
+ cp .env.local.example .env.local
27
+ ```
28
+
29
+ 2. **Edit `.env.local`** with your credentials:
30
+
31
+ ```env
32
+ CMS_ADMIN_USERNAME=admin
33
+ CMS_ADMIN_PASSWORD=your_password
34
+ CMS_SESSION_SECRET=your-32-char-secret
35
+ ```
36
+
37
+ 3. **Start development server:**
38
+
39
+ ```bash
40
+ cd ../..
41
+ pnpm dev
42
+ ```
43
+
44
+ 4. **Open browser:**
45
+ - Home: http://localhost:3000
46
+ - Admin: http://localhost:3000/admin
47
+ - Login with your credentials
48
+
49
+ ## Use in Your Own Project
50
+
51
+ See [README.md](../README.md) for installation and setup instructions.
52
+
53
+ ## Features
54
+
55
+ - ✅ Create, edit, delete markdown files
56
+ - ✅ Frontmatter support (JSON)
57
+ - ✅ Session-based authentication
58
+ - ✅ Local storage (dev) + GitHub (production)
59
+ - ✅ TypeScript types included
60
+ - ✅ Vercel-compatible
61
+
62
+ ## API Example
63
+
64
+ ```typescript
65
+ import { getMarkdownContent } from "@fydemy/cms";
66
+
67
+ // Read content
68
+ const post = await getMarkdownContent("example.md");
69
+ console.log(post.data.title); // "Example Post"
70
+ console.log(post.content); // markdown content
71
+ ```
72
+
73
+ ## Next Steps
74
+
75
+ 1. Test the admin dashboard locally
76
+ 2. Deploy to Vercel with GitHub token
77
+ 3. Use the utilities in your pages
78
+ 4. Customize the admin UI as needed
79
+
80
+ Built with TypeScript, minimal dependencies, zero database! 🎉
package/README.md ADDED
@@ -0,0 +1,293 @@
1
+ # @fydemy/cms
2
+
3
+ [![npm version](https://badge.fury.io/js/@fydemy%2Fcms.svg)](https://www.npmjs.com/package/@fydemy/cms)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.3-blue.svg)](https://www.typescriptlang.org/)
6
+ [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D18.0.0-brightgreen.svg)](https://nodejs.org/)
7
+
8
+ A minimal, secure, file-based CMS for Next.js without database requirements. Store content as markdown files with GitHub integration for production deployments.
9
+
10
+ ## Features
11
+
12
+ - 📝 **File-based Storage** - Markdown files with frontmatter in `/public/content`
13
+ - 🔐 **Secure Authentication** - Timing-safe password comparison, rate limiting, input validation
14
+ - 🚀 **Vercel Compatible** - Deploy without any database setup
15
+ - 🐙 **GitHub Integration** - Automatic file commits in production
16
+ - 📦 **Zero Config** - Minimal setup required
17
+ - 🎯 **TypeScript First** - Full type safety with comprehensive type definitions
18
+ - ⚡ **Lightweight** - Small bundle size (~30KB), minimal dependencies
19
+ - 🛡️ **Security Hardened** - Built with security best practices
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ npm install @fydemy/cms
25
+ # or
26
+ pnpm add @fydemy/cms
27
+ # or
28
+ yarn add @fydemy/cms
29
+ ```
30
+
31
+ ## Quick Start
32
+
33
+ ### 1. Initialize the CMS
34
+
35
+ Run the initialization command in your Next.js App Router project:
36
+
37
+ ```bash
38
+ npx fydemy-cms init
39
+ ```
40
+
41
+ This command will automatically:
42
+
43
+ - Create the content directory
44
+ - Scaffold Admin UI pages (`/app/admin`)
45
+ - Create API routes (`/app/api/cms`)
46
+ - Create a `.env.local.example` file
47
+ - Provide instructions for updating `middleware.ts`
48
+
49
+ ### 2. Configure Environment
50
+
51
+ Copy `.env.local.example` to `.env.local` and set your credentials:
52
+
53
+ ```bash
54
+ cp .env.local.example .env.local
55
+ ```
56
+
57
+ Update variables in `.env.local`:
58
+
59
+ ```env
60
+ # Required for authentication
61
+ CMS_ADMIN_USERNAME=admin
62
+ CMS_ADMIN_PASSWORD=your_secure_password
63
+ CMS_SESSION_SECRET=your-secret-key-must-be-at-least-32-characters-long
64
+
65
+ # Optional: For production (GitHub integration)
66
+ GITHUB_TOKEN=ghp_your_github_token
67
+ GITHUB_REPO=username/repository
68
+ GITHUB_BRANCH=main
69
+ ```
70
+
71
+ > **Security Note**: Use strong passwords and keep `CMS_SESSION_SECRET` at least 32 characters long.
72
+
73
+ ### 3. Read Content in Your App
74
+
75
+ ```typescript
76
+ import { getMarkdownContent } from "@fydemy/cms";
77
+
78
+ export default async function BlogPost({
79
+ params,
80
+ }: {
81
+ params: { slug: string };
82
+ }) {
83
+ const post = await getMarkdownContent(`${params.slug}.md`);
84
+
85
+ return (
86
+ <article>
87
+ <h1>{post.data.title}</h1>
88
+ <p>{post.data.description}</p>
89
+ <div>{post.content}</div>
90
+ </article>
91
+ );
92
+ }
93
+ ```
94
+
95
+ ## Security Features
96
+
97
+ ### Built-in Security
98
+
99
+ - **Timing-Safe Authentication**: Uses `crypto.timingSafeEqual` to prevent timing attacks
100
+ - **Rate Limiting**: 5 login attempts per 15 minutes per IP address
101
+ - **Input Validation**: All inputs validated and sanitized
102
+ - **Path Validation**: Prevents directory traversal attacks
103
+ - **File Size Limits**: Default 10MB maximum file size
104
+ - **Secure Sessions**: httpOnly, sameSite, and secure cookies in production
105
+ - **No Username Enumeration**: Generic error messages
106
+
107
+ ### Security Best Practices
108
+
109
+ 1. **Strong Credentials**: Use strong, unique passwords for `CMS_ADMIN_PASSWORD`
110
+ 2. **Secret Management**: Keep `CMS_SESSION_SECRET` at least 32 characters
111
+ 3. **GitHub Token Security**: Use minimal permissions (only `repo` scope)
112
+ 4. **HTTPS Only**: Always use HTTPS in production
113
+ 5. **Regular Updates**: Keep dependencies up to date
114
+ 6. **Environment Variables**: Never commit `.env` files
115
+
116
+ For more security information, see [SECURITY.md](./SECURITY.md).
117
+
118
+ ## API Reference
119
+
120
+ ### Content Management
121
+
122
+ ```typescript
123
+ // Read markdown file
124
+ const content = await getMarkdownContent("blog/post.md");
125
+ // Returns: { data: {...}, content: "..." }
126
+
127
+ // Write markdown file
128
+ await saveMarkdownContent(
129
+ "blog/post.md",
130
+ { title: "My Post", date: "2024-01-01" },
131
+ "# Hello World"
132
+ );
133
+
134
+ // Delete file
135
+ await deleteMarkdownContent("blog/post.md");
136
+
137
+ // List files
138
+ const files = await listMarkdownFiles("blog");
139
+ // Returns: ['blog/post1.md', 'blog/post2.md']
140
+
141
+ // Check if file exists
142
+ const exists = await markdownFileExists("blog/post.md");
143
+ ```
144
+
145
+ ### Parsing Utilities
146
+
147
+ ```typescript
148
+ import { parseMarkdown, stringifyMarkdown } from "@fydemy/cms";
149
+
150
+ // Parse markdown string
151
+ const { data, content } = parseMarkdown(rawMarkdown);
152
+
153
+ // Convert to markdown
154
+ const markdown = stringifyMarkdown({ title: "Post" }, "Content here");
155
+ ```
156
+
157
+ ### Authentication
158
+
159
+ ```typescript
160
+ import { validateCredentials, createSession } from "@fydemy/cms";
161
+
162
+ // Validate credentials
163
+ const isValid = validateCredentials("admin", "password");
164
+
165
+ // Create session (returns JWT)
166
+ const token = await createSession("admin");
167
+ ```
168
+
169
+ ### Validation Utilities
170
+
171
+ ```typescript
172
+ import {
173
+ validateFilePath,
174
+ validateUsername,
175
+ validatePassword,
176
+ sanitizeFrontmatter,
177
+ } from "@fydemy/cms";
178
+
179
+ // Validate file path (prevents directory traversal)
180
+ const safePath = validateFilePath("blog/post.md");
181
+
182
+ // Validate username
183
+ validateUsername("admin"); // throws if invalid
184
+
185
+ // Sanitize frontmatter data
186
+ const safe = sanitizeFrontmatter({ title: "Test", script: "<script>" });
187
+ ```
188
+
189
+ ## Storage
190
+
191
+ ### Development
192
+
193
+ Files are stored locally in `/public/content` directory.
194
+
195
+ ### Production
196
+
197
+ When `NODE_ENV=production` and `GITHUB_TOKEN` is set, all file operations are performed via GitHub API, creating commits directly to your repository.
198
+
199
+ ## Environment Variables
200
+
201
+ | Variable | Required | Description |
202
+ | -------------------- | ---------- | ------------------------------- |
203
+ | `CMS_ADMIN_USERNAME` | Yes | Admin username |
204
+ | `CMS_ADMIN_PASSWORD` | Yes | Admin password |
205
+ | `CMS_SESSION_SECRET` | Yes | JWT secret (min 32 chars) |
206
+ | `GITHUB_TOKEN` | Production | GitHub personal access token |
207
+ | `GITHUB_REPO` | Production | Repository (format: owner/repo) |
208
+ | `GITHUB_BRANCH` | Production | Branch name (default: main) |
209
+
210
+ ## GitHub Setup
211
+
212
+ 1. Create a GitHub Personal Access Token with `repo` permissions
213
+ 2. Add the token to your environment variables
214
+ 3. Deploy to Vercel and configure the environment variables
215
+
216
+ ## FAQ
217
+
218
+ ### Is this suitable for production?
219
+
220
+ Yes! The package includes security hardening, rate limiting, and has been tested for production use. Make sure to follow security best practices.
221
+
222
+ ### Can I use this with other frameworks?
223
+
224
+ This package is designed for Next.js App Router (13+). For other frameworks, you can use the core utilities but will need to implement your own API routes.
225
+
226
+ ### How do I customize the file size limit?
227
+
228
+ ```typescript
229
+ import { MAX_FILE_SIZE } from "@fydemy/cms";
230
+ // Default is 10MB, you can check this constant
231
+ ```
232
+
233
+ To change it, you'll need to implement your own validation layer.
234
+
235
+ ### Does it support images?
236
+
237
+ Yes! The package includes file upload functionality. Images can be uploaded and stored in `/public/uploads` (local) or via GitHub API (production).
238
+
239
+ ### How do I backup my content?
240
+
241
+ Since content is stored in your GitHub repository (in production), it's automatically backed up with full version history. In development, the `/public/content` directory can be committed to git.
242
+
243
+ ### What about rate limiting in production?
244
+
245
+ The built-in rate limiter is memory-based and resets on server restart. For production with multiple instances, consider implementing Redis-based rate limiting.
246
+
247
+ ### Can I add more admin users?
248
+
249
+ Currently, the package supports a single admin user via environment variables. For multi-user support, you'd need to implement a custom authentication layer.
250
+
251
+ ## Example Admin UI
252
+
253
+ Check the `/apps/dev` directory in this repository for a complete example with:
254
+
255
+ - Login page
256
+ - Admin dashboard
257
+ - File editor
258
+ - File management
259
+
260
+ ## Troubleshooting
261
+
262
+ ### "CMS_SESSION_SECRET must be at least 32 characters"
263
+
264
+ Make sure your session secret is long enough. Generate a secure random string:
265
+
266
+ ```bash
267
+ node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
268
+ ```
269
+
270
+ ### Rate limiting not working across restarts
271
+
272
+ The rate limiter is in-memory. For persistent rate limiting, implement Redis storage.
273
+
274
+ ### GitHub API rate limits
275
+
276
+ GitHub API has rate limits. For high-traffic sites, consider caching content or using a CDN.
277
+
278
+ ## License
279
+
280
+ MIT
281
+
282
+ ## Contributing
283
+
284
+ Contributions welcome! This is a minimal CMS focused on simplicity and maintainability.
285
+
286
+ Please report security vulnerabilities privately to fydemy@gmail.com or via GitHub security advisories.
287
+
288
+ ## Links
289
+
290
+ - [GitHub Repository](https://github.com/fydemy/cms)
291
+ - [npm Package](https://www.npmjs.com/package/@fydemy/cms)
292
+ - [Report Issues](https://github.com/fydemy/cms/issues)
293
+ - [Security Policy](https://github.com/fydemy/cms/blob/main/SECURITY.md)
package/SECURITY.md ADDED
@@ -0,0 +1,79 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ We release patches for security vulnerabilities for the following versions:
6
+
7
+ | Version | Supported |
8
+ | ------- | ------------------ |
9
+ | 1.x.x | :white_check_mark: |
10
+ | < 1.0 | :x: |
11
+
12
+ ## Reporting a Vulnerability
13
+
14
+ **Please do not report security vulnerabilities through public GitHub issues.**
15
+
16
+ If you discover a security vulnerability in @fydemy/cms, please report it by emailing fydemy@gmail.com (or create a private security advisory on GitHub).
17
+
18
+ Please include the following information:
19
+
20
+ - Type of vulnerability
21
+ - Full paths of source file(s) related to the vulnerability
22
+ - Location of the affected source code (tag/branch/commit or direct URL)
23
+ - Step-by-step instructions to reproduce the issue
24
+ - Proof-of-concept or exploit code (if possible)
25
+ - Impact of the issue, including how an attacker might exploit it
26
+
27
+ We will acknowledge your email within 48 hours and send a more detailed response within 7 days indicating the next steps in handling your report.
28
+
29
+ ## Security Best Practices
30
+
31
+ When using @fydemy/cms, follow these security best practices:
32
+
33
+ ### Environment Variables
34
+
35
+ - Use strong, random values for `CMS_SESSION_SECRET` (minimum 32 characters)
36
+ - Use strong passwords for `CMS_ADMIN_PASSWORD`
37
+ - Never commit `.env` files to version control
38
+ - Rotate credentials regularly
39
+
40
+ ### GitHub Token
41
+
42
+ - Use GitHub Personal Access Tokens with minimal required permissions (only `repo` scope)
43
+ - Use fine-grained personal access tokens when possible
44
+ - Store tokens securely in your deployment platform's secret management
45
+
46
+ ### Network Security
47
+
48
+ - Always use HTTPS in production
49
+ - Configure your Next.js app behind a reverse proxy or CDN
50
+ - Enable security headers (CSP, HSTS, X-Frame-Options, etc.)
51
+
52
+ ### Rate Limiting
53
+
54
+ - The built-in rate limiter is memory-based and resets on server restart
55
+ - For production, consider implementing Redis-based rate limiting
56
+ - Monitor failed login attempts
57
+
58
+ ### File Uploads
59
+
60
+ - The default file size limit is 10MB
61
+ - Validate file types on the client and server
62
+ - Consider implementing virus scanning for uploaded files
63
+ - Use Content Security Policy headers to prevent XSS from uploaded content
64
+
65
+ ### Session Security
66
+
67
+ - Session cookies are httpOnly, sameSite=lax, and secure in production
68
+ - Sessions expire after 7 days
69
+ - Consider shorter session duration for sensitive applications
70
+
71
+ ## Disclosure Policy
72
+
73
+ When we receive a security bug report, we will:
74
+
75
+ 1. Confirm the problem and determine affected versions
76
+ 2. Audit code to find similar problems
77
+ 3. Prepare fixes for all supported versions
78
+ 4. Release new versions as soon as possible
79
+ 5. Credit the reporter (unless they prefer to remain anonymous)
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "@fydemy/cms",
3
+ "version": "0.0.0",
4
+ "description": "Simple file-based CMS for Next.js",
5
+ "scripts": {
6
+ "dev": "pnpm --filter dev dev",
7
+ "build": "pnpm --filter @fydemy/cms build",
8
+ "build:all": "pnpm -r build"
9
+ },
10
+ "keywords": [
11
+ "cms",
12
+ "nextjs",
13
+ "markdown",
14
+ "vercel"
15
+ ],
16
+ "author": "",
17
+ "license": "MIT",
18
+ "devDependencies": {
19
+ "typescript": "^5.3.3"
20
+ }
21
+ }