Skip to content

Development Guide

Temp edited this page Oct 23, 2025 · 14 revisions

Development Guide

Complete guide for local development and contributing to R2-Manager-Worker.

Local Development Setup

Prerequisites

Ensure you have installed:

Clone and Install

git clone https://github.com/neverinfamous/R2-Manager-Worker.git
cd R2-Manager-Worker
npm install

Environment Configuration

Create a .env file for local development:

cp .env.example .env

Edit .env:

VITE_WORKER_API=http://localhost:8787

Start Development Servers

You need two terminal windows running simultaneously:

Terminal 1: Vite Dev Server (Frontend)

npm run dev
  • Frontend available at: http://localhost:5173
  • Hot module replacement (HMR) enabled
  • React Fast Refresh for instant updates

Terminal 2: Wrangler Worker (Backend)

npx wrangler dev
  • Worker API available at: http://localhost:8787
  • Automatic reload on file changes
  • Local bindings for R2 and D1

Important Notes

  • Authentication is disabled on localhost during development
  • JWT validation is skipped for local requests
  • No secrets required for local development (uses --local flag)
  • To test with remote resources, use: npx wrangler dev --remote

Project Structure

R2-Manager-Worker/
├── src/                      # Frontend source code
│   ├── app.tsx              # Main application component
│   ├── filegrid.tsx         # File browser with grid/list views
│   ├── main.tsx             # React entry point
│   ├── app.css              # Global styles with CSS variables
│   ├── components/
│   │   └── ThemeToggle.tsx  # Theme toggle button component
│   ├── contexts/
│   │   └── ThemeContext.tsx # Theme state management
│   ├── hooks/
│   │   └── useTheme.ts      # Theme hook for components
│   ├── services/
│   │   ├── api.ts           # HTTP client & API calls
│   │   └── auth.ts          # Authentication utilities
│   └── styles/
│       ├── themes.css       # CSS variable definitions
│       └── ThemeToggle.css  # Theme toggle button styles
│
├── worker/                   # Backend Worker code
│   ├── index.ts             # Worker runtime & API endpoints
│   └── schema.sql           # D1 database schema
│
├── public/                   # Static assets
│   ├── favicon.ico
│   ├── logo.png
│   └── manifest files
│
├── dist/                     # Production build output
│
├── wrangler.toml.example    # Wrangler config template
├── .env.example             # Environment variables template
├── package.json             # Project dependencies
├── vite.config.ts           # Vite configuration
├── tsconfig.json            # TypeScript configuration
└── eslint.config.js         # ESLint configuration

Technology Stack

Frontend

  • React 19.2.0 - UI framework with latest features
  • TypeScript 5.9.3 - Type-safe JavaScript
  • Vite 7.1.11 - Fast build tool and dev server
  • CSS - No framework, vanilla CSS for simplicity

Backend

  • Cloudflare Workers - Serverless edge runtime
  • TypeScript - Worker code is also type-safe
  • R2 - Object storage (S3-compatible)
  • D1 - SQLite database at the edge
  • JSZip - ZIP file creation for bulk downloads

Build Tools

  • Wrangler - Cloudflare Workers CLI
  • ESLint - Code linting
  • Vite - Frontend bundling

Available Scripts

Frontend Development

Start dev server:

npm run dev

Build for production:

npm run build

Preview production build:

npm run preview

Run linter:

npm run lint

Backend Development

Start local Worker:

npx wrangler dev

Start with remote bindings:

npx wrangler dev --remote

View Worker logs:

npx wrangler tail

Deployment

Deploy to Cloudflare:

npm run build && npx wrangler deploy

ES Modules Configuration

The project uses ES modules throughout:

{
  "type": "module"
}

Important:

  • All files use ES6 import/export syntax
  • No CommonJS require() statements
  • Ensures compatibility with Vite 7+
  • Prevents subtle syntax issues

Development Workflow

Making Changes

  1. Create a feature branch:

    git checkout -b feature/your-feature-name
  2. Make your changes in src/ or worker/

  3. Test locally with both dev servers running

  4. Run linter:

    npm run lint
  5. Build for production:

    npm run build
  6. Test production build:

    npm run preview
    npx wrangler dev --remote
  7. Commit changes:

    git add .
    git commit -m "Description of changes"
  8. Push to GitHub:

    git push origin feature/your-feature-name
  9. Create Pull Request on GitHub

Code Style

Follow these conventions:

TypeScript:

  • Use TypeScript strict mode
  • Define interfaces for all API responses
  • Use explicit return types for functions
  • Prefer const over let

React:

  • Functional components only (no class components)
  • Use hooks for state and side effects
  • Keep components small and focused
  • Extract reusable logic into custom hooks

CSS:

  • Use BEM naming convention
  • Mobile-first responsive design
  • Avoid inline styles when possible

Comments:

  • Use JSDoc comments for functions
  • Explain complex logic
  • Don't comment obvious code

Testing Authentication Locally

To test with Cloudflare Access:

Option 1: Deploy and Test

  1. Deploy to production: npx wrangler deploy
  2. Test on your deployed domain
  3. JWT validation works in production

Option 2: Use Remote Worker

  1. Set .env to point to deployed Worker:
    VITE_WORKER_API=https://your-worker.workers.dev
    
  2. Run frontend locally: npm run dev
  3. API calls go to production Worker with JWT validation

Debugging

Frontend Debugging

Browser DevTools:

  • Open DevTools (F12)
  • Console tab - View logs and errors
  • Network tab - Inspect API requests
  • Application tab - Check cookies and storage
  • React DevTools - Install browser extension

Enable verbose logging:

// In src/services/api.ts
console.log('API Request:', {
  method,
  url,
  body
});

Worker Debugging

View real-time logs:

npx wrangler tail

Add debug logging:

// In worker/index.ts
console.log('[Debug]', {
  path: url.pathname,
  method: request.method,
  headers: Object.fromEntries(request.headers)
});

View logs in dashboard:

  1. Go to Workers & Pages → Select your Worker
  2. Click Logs tab
  3. See real-time console output

Common Issues

Port already in use:

# Find and kill process using port 5173 or 8787
npx kill-port 5173
npx kill-port 8787

Module not found:

# Clear node_modules and reinstall
rm -rf node_modules package-lock.json
npm install

Wrangler authentication:

# Re-authenticate with Cloudflare
npx wrangler login

Database Development

View Database

List tables:

npx wrangler d1 execute your-database-name --remote \
  --command="SELECT name FROM sqlite_master WHERE type='table'"

Query data:

npx wrangler d1 execute your-database-name --remote \
  --command="SELECT * FROM bucket_owners"

Update Schema

  1. Edit worker/schema.sql
  2. Apply changes:
    npx wrangler d1 execute your-database-name --remote \
      --file=worker/schema.sql

Note: D1 doesn't support migrations yet. Be careful with schema changes in production.

Adding New Features

Adding a New API Endpoint

  1. Add route handler in worker/index.ts:
if (url.pathname.startsWith('/api/your-endpoint')) {
  // Handle request
  return new Response(JSON.stringify({ success: true }), {
    headers: {
      'Content-Type': 'application/json',
      ...corsHeaders
    }
  });
}
  1. Add API client method in src/services/api.ts:
export async function yourNewEndpoint(param: string): Promise<Response> {
  return apiRequest(`/your-endpoint/${param}`, {
    method: 'GET'
  });
}
  1. Use in component:
import { yourNewEndpoint } from './services/api';

const data = await yourNewEndpoint('value');

Adding a New UI Component

  1. Create component file:
// src/components/YourComponent.tsx
import React from 'react';

export function YourComponent() {
  return (
    <div className="your-component">
      {/* Component content */}
    </div>
  );
}
  1. Import and use:
import { YourComponent } from './components/YourComponent';

function App() {
  return <YourComponent />;
}

Performance Optimization

Frontend

  • Code splitting - Vite automatically splits chunks
  • Lazy loading - Use React.lazy() for large components
  • Memoization - Use React.memo() to prevent re-renders
  • Debouncing - Debounce search and filter inputs

Worker

  • Streaming responses - Use ReadableStream for large files
  • Caching - Implement cache headers for static content
  • Pagination - Limit result sets and use cursors
  • Rate limiting - Built-in delays prevent API throttling

Contributing Guidelines

Before Submitting

  1. ✅ Code follows project style
  2. ✅ All tests pass (when tests exist)
  3. ✅ Linter passes: npm run lint
  4. ✅ Production build succeeds: npm run build
  5. ✅ Changes are documented
  6. ✅ Commit messages are clear

Pull Request Process

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Push to your fork
  5. Open a Pull Request with:
    • Clear description of changes
    • Screenshots (if UI changes)
    • Related issue numbers

Code Review

PRs will be reviewed for:

  • Code quality and style
  • TypeScript type safety
  • Security implications
  • Performance impact
  • Documentation updates

Theme System Architecture

R2 Bucket Manager includes a comprehensive theme system with light/dark mode support:

Architecture Overview

Components:

  • ThemeContext.tsx - React Context for theme state management
  • useTheme.ts - Custom hook for accessing theme context
  • ThemeToggle.tsx - UI component for theme switching
  • themes.css - CSS custom properties for all colors
  • app.css - Styles using CSS variables

Theme Implementation

How It Works:

  1. ThemeProvider wraps the entire application in main.tsx
  2. Theme preference is stored in localStorage (key: r2-manager-theme)
  3. System preference is detected via prefers-color-scheme media query
  4. Theme is applied via data-theme attribute on <html> element
  5. All colors reference CSS custom properties (var(--color-name))

Theme Modes:

  • system - Follows OS/browser preference (default)
  • light - Force light mode
  • dark - Force dark mode

Color Variables:

/* Light Theme */
--bg-primary: #ffffff
--text-primary: #111827
--accent-blue: #2563eb

/* Dark Theme */
--bg-primary: #111827
--text-primary: rgba(255, 255, 255, 0.87)
--accent-blue: #2563eb

Adding New Colors

  1. Define in themes.css:
:root[data-theme="light"] {
  --my-color: #hexcode;
}

:root[data-theme="dark"] {
  --my-color: #hexcode;
}
  1. Use in app.css:
.my-element {
  background: var(--my-color);
}

Theme Toggle Usage

In Components:

import { useTheme } from '../hooks/useTheme'

function MyComponent() {
  const { theme, resolvedTheme, setTheme } = useTheme()
  
  // theme: 'light' | 'dark' | 'system'
  // resolvedTheme: 'light' | 'dark'
  // setTheme: (theme: ThemeMode) => void
}

Cycle Through Themes:

const cycleTheme = () => {
  if (theme === 'system') setTheme('light')
  else if (theme === 'light') setTheme('dark')
  else setTheme('system')
}

Testing Themes

Manual Testing:

  1. Click theme toggle button in header
  2. Verify smooth transition between themes
  3. Check localStorage persistence (reload page)
  4. Test system theme detection (change OS theme)

Browser DevTools:

  1. Open DevTools → Application → Local Storage
  2. Check for r2-manager-theme key
  3. Change OS theme: DevTools → Rendering → Emulate CSS prefers-color-scheme

Color Contrast Guidelines

All colors meet WCAG 2.1 AA standards:

  • Normal text: 4.5:1 contrast ratio minimum
  • Large text: 3:1 contrast ratio minimum
  • Interactive elements: 3:1 contrast ratio minimum

Use online tools to verify:

Release Process

  1. Update version in package.json
  2. Update README.md if needed
  3. Create git tag: git tag v1.x.x
  4. Push tag: git push origin v1.x.x
  5. Deploy to production: npx wrangler deploy

Adding File Type Support

To add support for new file extensions in uploads, you need to modify three files:

1. Update src/services/api.ts - File Type Configuration

Define the file type category and MIME types:

// Add new category to FILE_TYPES object
myCategory: {
  maxSize: 50 * 1024 * 1024, // 50MB limit
  description: 'My Category Files',
  accept: [
    'application/my-type',
    'text/plain' // fallback for files without MIME type
  ]
}

Then add extension mappings in getConfigByExtension():

'ext1': 'myCategory',
'ext2': 'myCategory',
'ext3': 'myCategory'

2. Update src/filegrid.tsx - File Icons

Add a custom icon function to display the file type visually:

// Add before the generic document icon at the end
if (ext === 'ext1' || ext === 'ext2' || ext === 'ext3') {
  return (
    <svg xmlns="http://www.w3.org/2000/svg" className="file-type-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5">
      {/* Your SVG icon here */}
    </svg>
  )
}

Icon Guidelines:

  • Use 24x24 viewBox
  • Stroke-based design with strokeWidth="1.5"
  • No fill on main elements (let CSS handle color)
  • Keep design simple and recognizable at small sizes

3. Update src/app.tsx - Upload Instructions

Add your new category to the upload instructions list:

<li>My Category (EXT1, EXT2, EXT3) - up to 50MB</li>

Keep entries:

  • Alphabetical by category name
  • Uppercase extension names
  • Specific size limits per category

File Type Categories

Category Size Limit Purpose Examples
image 15MB Images jpg, png, gif, webp
video 500MB Videos mp4, mov, webm
document 50MB Docs & spreadsheets pdf, docx, xlsx, csv
archive 500MB Compressed files zip, rar, 7z, tar, gz
code 10MB Source code js, ts, py, go, rust
config 10MB Config files toml, jsonc, env, lock
devenv 1MB Dev environment dockerfile, gitignore
dataformat 50MB Data formats feather, avro, ndjson
docs 10MB Documentation nfo

Security Considerations

Never add these unsafe file types:

  • .exe, .dll, .bat, .cmd - Windows executables
  • .sh, .bash, .zsh - Shell scripts
  • .ps1 - PowerShell scripts
  • .jar, .class - Java executables
  • .wasm - WebAssembly
  • .msi - Windows installers

These can bypass Cloudflare Access or pose security risks.

Testing New Extensions

  1. Make changes to all three files
  2. Run linter: npm run lint
  3. Build: npm run build
  4. Test locally: npm run dev (both servers)
  5. Upload a test file with the new extension
  6. Verify icon displays correctly
  7. Deploy: npx wrangler deploy

Additional Resources


Questions? Check the Troubleshooting page or open an issue on GitHub.

R2 Bucket Manager Wiki

Getting Started

Core Features

Development

Security & Authentication

Support & Resources

External Links

Clone this wiki locally