Skip to content

docs: add implementation TODO tracker and update to Next.js 15 #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,8 @@ For detailed architecture, API specs, and data models, refer to `docs/SPEC.md`.
7. When merging, write commit summary from all commits in the pull request
8. Use a comprehensive summary (not a commit list) as the squash merge commit message, describing the overall work accomplished in the PR
- Prefer rebase over merge to keep history clean
- Always pull latest changes from `main` before starting new work
- Always pull latest changes from `main` before starting new work

## Best Practices

- Always check official documentation of frameworks, UI components, Cloudflare, CodeMirror before implementing changes. If they provide generator or command line, please follow the documentation instead of manually generate them.
58 changes: 43 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ Simply open the shared link - the decryption key is in the URL fragment and neve

## 🛠️ Technical Stack

- **Frontend**: Next.js 14+ with React
- **Framework**: Next.js 15 with React
- **Runtime**: Cloudflare Workers (Edge)
- **UI Components**: shadcn/ui
- **Code Editor**: CodeMirror 6
- **Encryption**: Web Crypto API (AES-GCM)
- **Storage**: Cloudflare R2
- **Deployment**: Cloudflare Workers
- **Storage**: Cloudflare R2 with native bindings

## 📊 Limits

Expand All @@ -63,8 +63,9 @@ Simply open the shared link - the decryption key is in the URL fragment and neve
### Prerequisites

- Node.js 18+
- npm or yarn
- Cloudflare account (for R2 storage)
- npm or yarn
- Cloudflare account (for Workers and R2)
- Wrangler CLI (`npm install -g wrangler`)

### Setup

Expand All @@ -76,29 +77,56 @@ cd ghostpaste
# Install dependencies
npm install

# Copy environment variables
cp .env.example .env.local
# Login to Cloudflare
wrangler login

# Configure your Cloudflare R2 credentials in .env.local
# Create R2 bucket
wrangler r2 bucket create ghostpaste-bucket

# Copy wrangler configuration
cp wrangler.toml.example wrangler.toml

# Run development server
npm run dev
```

### Environment Variables
### Configuration

Create a `wrangler.toml` file:

```toml
name = "ghostpaste"
compatibility_date = "2024-12-01"

[[r2_buckets]]
binding = "GHOSTPASTE_BUCKET"
bucket_name = "ghostpaste-bucket"

[vars]
NEXT_PUBLIC_APP_URL = "https://ghostpaste.dev"
```

For local development secrets, create `.dev.vars`:

```
# Any additional secrets go here
```

### Deployment

```bash
# Build for Cloudflare Workers
npm run build

```env
CLOUDFLARE_ACCOUNT_ID=your_account_id
CLOUDFLARE_R2_ACCESS_KEY_ID=your_access_key
CLOUDFLARE_R2_SECRET_ACCESS_KEY=your_secret_key
CLOUDFLARE_R2_BUCKET_NAME=ghostpaste-bucket
NEXT_PUBLIC_APP_URL=http://localhost:3000
# Deploy to production
npm run deploy
```

## 📖 Documentation

- [Technical Specification](docs/SPEC.md) - Detailed architecture and implementation details
- [AI Development Guide](CLAUDE.md) - Guidelines for AI-assisted development
- [Implementation TODO](docs/TODO.md) - Development roadmap and progress tracking

## 🤝 Contributing

Expand Down
91 changes: 62 additions & 29 deletions docs/SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,24 @@ GhostPaste is a zero-knowledge encrypted code sharing platform where users can c

## 🏗️ Architecture

### Deployment Model

GhostPaste runs entirely on Cloudflare's edge network:
- **Next.js** deployed via Cloudflare Workers using `@cloudflare/next-on-pages`
- **R2 Storage** accessed through native Workers bindings (no AWS SDK needed)
- **Zero cold starts** with Workers' always-warm edge runtime
- **Global distribution** across Cloudflare's network

### Tech Stack

| Component | Technology | Purpose |
| -------------- | --------------------------------------- | --------------------------------- |
| **Frontend** | Next.js 14+ (SPA mode) | React framework with app router |
| **Frontend** | Next.js 15 | React framework with app router |
| **UI Library** | [shadcn/ui](https://ui.shadcn.com) | Modern, accessible components |
| **Editor** | CodeMirror 6 | Syntax highlighting & editing |
| **Encryption** | Web Crypto API | AES-GCM client-side encryption |
| **Backend** | Next.js API + Cloudflare Workers | API endpoints & edge computing |
| **Storage** | Cloudflare R2 | Object storage for all data |
| **Runtime** | Cloudflare Workers | Edge computing platform |
| **Storage** | Cloudflare R2 | Object storage with native bindings |

### Storage Structure

Expand Down Expand Up @@ -135,6 +143,8 @@ For editable gists:

## 🔌 API Endpoints

All API routes run on Cloudflare Workers with Edge Runtime.

### Create Gist

```http
Expand Down Expand Up @@ -222,6 +232,8 @@ Error codes:
| Update rate | 60/hour/IP | Allow active editing |
| Minimum PIN length | 4 digits | Basic security |
| Maximum PIN length | 8 digits | Usability |
| Request size | 100 MB | Cloudflare Workers limit |
| CPU time | 50ms | Workers CPU limit |

---

Expand All @@ -235,16 +247,18 @@ Users can set expiration times:
- Default: No expiration

Implementation:
- Cloudflare Workers CRON job
- Separate Cloudflare Worker with scheduled trigger
- Checks `expires_at` field hourly
- Deletes expired gists + versions
- Batch deletes expired gists + versions
- Configured in wrangler.toml

### 2. One-Time View

Gists that delete after first decryption:
- Special flag in metadata
- `one_time_view: true` flag in metadata
- Client notifies server after successful decrypt
- Server immediately deletes
- Server immediately deletes all gist data
- Optional download before viewing

### 3. Version History

Expand Down Expand Up @@ -322,35 +336,54 @@ img-src 'self' data: https:;
### Development Setup

```bash
# Environment variables
CLOUDFLARE_ACCOUNT_ID=
CLOUDFLARE_R2_ACCESS_KEY_ID=
CLOUDFLARE_R2_SECRET_ACCESS_KEY=
CLOUDFLARE_R2_BUCKET_NAME=ghostpaste-bucket
NEXT_PUBLIC_APP_URL=https://ghostpaste.dev

# Commands
# Install dependencies
npm install

# Local development with Wrangler
npm run dev

# Build for Cloudflare Workers
npm run build

# Deploy to Cloudflare Workers
npm run deploy
```

### R2 Configuration
### Wrangler Configuration

```bash
# Create bucket
wrangler r2 bucket create ghostpaste-bucket

# Set CORS
wrangler r2 bucket cors put ghostpaste-bucket --rules '[
{
"allowedOrigins": ["https://ghostpaste.dev"],
"allowedMethods": ["GET", "PUT", "POST", "DELETE"],
"allowedHeaders": ["*"],
"maxAgeSeconds": 3600
}
]'
```toml
# wrangler.toml
name = "ghostpaste"
compatibility_date = "2024-12-01"

[[r2_buckets]]
binding = "GHOSTPASTE_BUCKET"
bucket_name = "ghostpaste-bucket"

[vars]
NEXT_PUBLIC_APP_URL = "https://ghostpaste.dev"

# Scheduled worker for expiry cleanup
[[triggers]]
crons = ["0 * * * *"] # Every hour
```

### R2 Access in Workers

```typescript
// Access R2 from Workers environment
export interface Env {
GHOSTPASTE_BUCKET: R2Bucket;
}

// Example usage in API route
export async function POST(request: Request, env: Env) {
// Direct R2 access without credentials
await env.GHOSTPASTE_BUCKET.put(
`metadata/${id}.json`,
JSON.stringify(metadata)
);
}
```

### Client-Side Encryption Example
Expand Down
Loading