-
Notifications
You must be signed in to change notification settings - Fork 15
Development Guide
Complete guide for local development and contributing to R2-Manager-Worker.
Ensure you have installed:
- Node.js 18+ and npm
- Wrangler CLI
- Git
git clone https://github.com/neverinfamous/R2-Manager-Worker.git
cd R2-Manager-Worker
npm installCreate a .env file for local development:
cp .env.example .envEdit .env:
VITE_WORKER_API=http://localhost:8787
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
- Authentication is disabled on localhost during development
- JWT validation is skipped for local requests
- No secrets required for local development (uses
--localflag) - To test with remote resources, use:
npx wrangler dev --remote
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
- 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
- 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
- Wrangler - Cloudflare Workers CLI
- ESLint - Code linting
- Vite - Frontend bundling
Start dev server:
npm run devBuild for production:
npm run buildPreview production build:
npm run previewRun linter:
npm run lintStart local Worker:
npx wrangler devStart with remote bindings:
npx wrangler dev --remoteView Worker logs:
npx wrangler tailDeploy to Cloudflare:
npm run build && npx wrangler deployThe project uses ES modules throughout:
{
"type": "module"
}Important:
- All files use ES6
import/exportsyntax - No CommonJS
require()statements - Ensures compatibility with Vite 7+
- Prevents subtle syntax issues
-
Create a feature branch:
git checkout -b feature/your-feature-name
-
Make your changes in
src/orworker/ -
Test locally with both dev servers running
-
Run linter:
npm run lint
-
Build for production:
npm run build
-
Test production build:
npm run preview npx wrangler dev --remote
-
Commit changes:
git add . git commit -m "Description of changes"
-
Push to GitHub:
git push origin feature/your-feature-name
-
Create Pull Request on GitHub
Follow these conventions:
TypeScript:
- Use TypeScript strict mode
- Define interfaces for all API responses
- Use explicit return types for functions
- Prefer
constoverlet
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
To test with Cloudflare Access:
Option 1: Deploy and Test
- Deploy to production:
npx wrangler deploy - Test on your deployed domain
- JWT validation works in production
Option 2: Use Remote Worker
- Set
.envto point to deployed Worker:VITE_WORKER_API=https://your-worker.workers.dev - Run frontend locally:
npm run dev - API calls go to production Worker with JWT validation
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
});View real-time logs:
npx wrangler tailAdd debug logging:
// In worker/index.ts
console.log('[Debug]', {
path: url.pathname,
method: request.method,
headers: Object.fromEntries(request.headers)
});View logs in dashboard:
- Go to Workers & Pages → Select your Worker
- Click Logs tab
- See real-time console output
Port already in use:
# Find and kill process using port 5173 or 8787
npx kill-port 5173
npx kill-port 8787Module not found:
# Clear node_modules and reinstall
rm -rf node_modules package-lock.json
npm installWrangler authentication:
# Re-authenticate with Cloudflare
npx wrangler loginList 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"- Edit
worker/schema.sql - 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.
- 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
}
});
}- Add API client method in
src/services/api.ts:
export async function yourNewEndpoint(param: string): Promise<Response> {
return apiRequest(`/your-endpoint/${param}`, {
method: 'GET'
});
}- Use in component:
import { yourNewEndpoint } from './services/api';
const data = await yourNewEndpoint('value');- Create component file:
// src/components/YourComponent.tsx
import React from 'react';
export function YourComponent() {
return (
<div className="your-component">
{/* Component content */}
</div>
);
}- Import and use:
import { YourComponent } from './components/YourComponent';
function App() {
return <YourComponent />;
}- 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
-
Streaming responses - Use
ReadableStreamfor large files - Caching - Implement cache headers for static content
- Pagination - Limit result sets and use cursors
- Rate limiting - Built-in delays prevent API throttling
- ✅ Code follows project style
- ✅ All tests pass (when tests exist)
- ✅ Linter passes:
npm run lint - ✅ Production build succeeds:
npm run build - ✅ Changes are documented
- ✅ Commit messages are clear
- Fork the repository
- Create a feature branch
- Make your changes
- Push to your fork
- Open a Pull Request with:
- Clear description of changes
- Screenshots (if UI changes)
- Related issue numbers
PRs will be reviewed for:
- Code quality and style
- TypeScript type safety
- Security implications
- Performance impact
- Documentation updates
R2 Bucket Manager includes a comprehensive theme system with light/dark mode support:
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
How It Works:
-
ThemeProviderwraps the entire application inmain.tsx - Theme preference is stored in
localStorage(key:r2-manager-theme) - System preference is detected via
prefers-color-schememedia query - Theme is applied via
data-themeattribute on<html>element - 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- Define in
themes.css:
:root[data-theme="light"] {
--my-color: #hexcode;
}
:root[data-theme="dark"] {
--my-color: #hexcode;
}- Use in
app.css:
.my-element {
background: var(--my-color);
}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')
}Manual Testing:
- Click theme toggle button in header
- Verify smooth transition between themes
- Check localStorage persistence (reload page)
- Test system theme detection (change OS theme)
Browser DevTools:
- Open DevTools → Application → Local Storage
- Check for
r2-manager-themekey - Change OS theme: DevTools → Rendering → Emulate CSS prefers-color-scheme
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:
- Update version in
package.json - Update
README.mdif needed - Create git tag:
git tag v1.x.x - Push tag:
git push origin v1.x.x - Deploy to production:
npx wrangler deploy
To add support for new file extensions in uploads, you need to modify three files:
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'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
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
| 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 |
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.
- Make changes to all three files
- Run linter:
npm run lint - Build:
npm run build - Test locally:
npm run dev(both servers) - Upload a test file with the new extension
- Verify icon displays correctly
- Deploy:
npx wrangler deploy
- React 19 Documentation
- Vite Documentation
- TypeScript Handbook
- Cloudflare Workers Docs
- Wrangler Commands
Questions? Check the Troubleshooting page or open an issue on GitHub.
- Home - Documentation overview
- Quick Start Guide - Get up and running in minutes
- Installation & Setup - Complete deployment guide
- Configuration Reference - Environment variables and settings
- Upgrade Guide - Database schema migrations
- Bucket Management - Create, rename, delete buckets
- Object Lifecycles - Automate expiration and IA transitions ⭐ NEW
- Local Uploads - Faster uploads via nearby edge storage ⭐ NEW
- Job History - Track bulk operations with audit trail ⭐ NEW
- Webhooks - Configure HTTP notifications for events ⭐ NEW
- AI Search - Semantic search with Cloudflare AI
- S3 Import - Migrate from AWS S3 to R2 ⭐ NEW
- Cross-Bucket Search - Search across all buckets with filters
- File Operations - Upload, download, move, copy, delete files
- Folder Management - Organize files hierarchically
- Signed URLs & Sharing - Generate secure shareable links
- Advanced Filtering - Filter by extension, size, and date
- Development Guide - Local setup and development workflow
- API Reference - Complete endpoint documentation
- Architecture Overview - Technical stack and design
- Authentication & Security - Zero Trust implementation
- JWT Validation - JWT token validation and verification
- Troubleshooting - Common issues and solutions
- FAQ - Frequently asked questions
- Roadmap - Planned features and enhancements