diff --git a/apps/assets/.gitignore b/apps/assets/.gitignore new file mode 100644 index 0000000..49db43b --- /dev/null +++ b/apps/assets/.gitignore @@ -0,0 +1,21 @@ +# Build outputs +dist/ + +# Generated assets (built from packages) +public/*.js +public/*.js.map + +# Keep configuration files +!public/_headers +!public/_redirects + +# Dependencies +node_modules/ + +# TypeScript +*.tsbuildinfo + +# Environment +.env +.env.local +.env.*.local diff --git a/apps/assets/MIGRATION.md b/apps/assets/MIGRATION.md new file mode 100644 index 0000000..b1aec1b --- /dev/null +++ b/apps/assets/MIGRATION.md @@ -0,0 +1,140 @@ +# Migration to Cloudflare Workers Static Assets + +## What Changed + +Cloudflare has unified Workers and Pages into a single **Workers Static Assets** platform. Our implementation has been updated to use this new architecture. + +## Old vs New Architecture + +### Before (Incorrect) +``` +❌ Used wrangler.jsonc (wrong format) +❌ Had main = "." (invalid) +❌ Used _headers and _redirects files (Pages-only features) +❌ No Worker script +❌ Relied on Pages behavior for routing +``` + +### After (Correct) +``` +✅ Uses wrangler.toml (correct format) +✅ Has main = "src/index.ts" (Worker script) +✅ Worker handles all routing and headers +✅ Uses env.ASSETS binding to fetch static files +✅ Follows Workers Static Assets best practices +``` + +## Key Changes + +### 1. Added Worker Script (`src/index.ts`) + +The Worker script handles: +- **Route mappings**: `/scripts/widget.js` → `/widget.v1.js` +- **Aliases**: `/attribution.latest.js` → `/attribution.v1.js` +- **Cache headers**: Immutable for versioned, short cache for aliases +- **CORS**: Automatic CORS headers for all scripts + +### 2. Updated Configuration (`wrangler.toml`) + +```toml +# Before +main = "." # ❌ Invalid + +# After +main = "src/index.ts" # ✅ Points to Worker script + +[assets] +directory = "./public" +binding = "ASSETS" # ✅ Required for env.ASSETS.fetch() +``` + +### 3. Removed Obsolete Files + +- ❌ Deleted `_headers` (now handled in Worker) +- ❌ Deleted `_redirects` (now handled in Worker) +- ❌ Removed `wrangler.jsonc` (renamed to `.toml`) + +### 4. Added TypeScript Support + +```json +{ + "types": ["@cloudflare/workers-types"] +} +``` + +## How It Works Now + +### Request Flow + +1. Request arrives: `https://assets.refref.ai/scripts/attribution.js` +2. Worker checks route map: Maps to `/attribution.v1.js` +3. Worker fetches from storage: `env.ASSETS.fetch(request)` +4. Worker adds headers: + - `Cache-Control: public, max-age=3600` + - `Access-Control-Allow-Origin: *` +5. Response sent to client + +### Supported URLs + +All these work automatically: + +``` +✅ /attribution.v1.js (direct, immutable) +✅ /widget.v1.js (direct, immutable) +✅ /attribution.latest.js (alias to v1) +✅ /widget.latest.js (alias to v1) +✅ /attribution.js (alias to v1) +✅ /widget.js (alias to v1) +✅ /scripts/attribution.js (backward compatibility) +✅ /scripts/widget.js (backward compatibility) +``` + +## Benefits of New Architecture + +1. **Unified Platform**: No more confusion between Workers and Pages +2. **Code-based Routing**: Explicit, testable routing logic +3. **Dynamic Control**: Can add logic, A/B testing, feature flags, etc. +4. **Better Performance**: Cloudflare's asset storage + Worker caching +5. **Type Safety**: Full TypeScript support with Workers types + +## Deployment + +No changes to deployment commands: + +```bash +# Production +pnpm -F @refref/assets deploy:cloudflare + +# Dev/Preview +pnpm -F @refref/assets deploy:cloudflare:dev +``` + +The Worker + assets are deployed together as a single unit. + +## Testing Locally + +```bash +# Start local dev server +pnpm -F @refref/assets preview + +# Test routes +curl http://localhost:8787/attribution.v1.js +curl http://localhost:8787/scripts/widget.js +``` + +## Migration Checklist + +- [x] Created Worker script (`src/index.ts`) +- [x] Updated `wrangler.toml` configuration +- [x] Removed `_headers` and `_redirects` files +- [x] Added `@cloudflare/workers-types` dependency +- [x] Updated TypeScript configuration +- [x] Updated README documentation +- [x] Tested build process +- [x] Ready for deployment + +## References + +- [Cloudflare Workers Static Assets Docs](https://developers.cloudflare.com/workers/static-assets/) +- [Wrangler Configuration](https://developers.cloudflare.com/workers/wrangler/configuration/) +- [Assets Binding](https://developers.cloudflare.com/workers/static-assets/binding/) diff --git a/apps/assets/README.md b/apps/assets/README.md new file mode 100644 index 0000000..475d8c2 --- /dev/null +++ b/apps/assets/README.md @@ -0,0 +1,498 @@ +# RefRef Assets Service + +Static assets service for serving RefRef scripts (attribution tracking and referral widget) via CDN. + +## Overview + +This app bundles and prepares RefRef scripts for deployment using **Cloudflare Workers Static Assets**. It combines a minimal Worker script with static file hosting to provide custom routing, headers, and caching for optimal performance. + +### Architecture + +- **Worker Script** (`src/index.ts`): Handles routing, redirects, and custom headers +- **Static Assets** (`public/`): Versioned JavaScript bundles served from Cloudflare's network +- **Assets Binding**: Worker fetches files from Cloudflare's asset storage via `env.ASSETS.fetch()` + +This is Cloudflare's new unified approach that replaces the separate Pages and Workers platforms. + +## Production vs Development + +⚠️ **This service is for PRODUCTION deployments only.** + +### Development (apps/refer) +- Use the refer server for local development +- Scripts served dynamically at `http://localhost:3002/scripts/*` +- Hot-reloading and no build step needed +- See [apps/refer/README.md](../refer/README.md) for details + +### Production (apps/assets - this service) +- Deploy to Cloudflare Workers/Pages for CDN delivery +- Scripts served from edge locations worldwide +- Immutable caching for maximum performance +- Version management and cache control +- Lower bandwidth costs and server overhead + +**Key Benefit:** By separating static assets from your application server, you get: +- Faster load times (CDN edge caching) +- Reduced server load (no dynamic script serving) +- Better scalability (Cloudflare's global network) +- Cost efficiency (free tier for static assets) + +## Scripts Available + +- **attribution.v1.js** - Attribution tracking script +- **widget.v1.js** - Referral widget +- **attribution.latest.js** - Alias to latest attribution version +- **widget.latest.js** - Alias to latest widget version + +## Development + +### Prerequisites + +Make sure the required packages are built: + +```bash +# From monorepo root +pnpm -F @refref/attribution-script build +pnpm -F @refref/widget build +``` + +### Build Assets + +```bash +# Build assets (copies bundles to public/) +pnpm -F @refref/assets build + +# Clean generated files +pnpm -F @refref/assets clean +``` + +### Build Output + +The build script will: +1. Copy compiled bundles from packages to `public/` +2. Name them with version suffix (e.g., `attribution.v1.js`) +3. Generate checksums for verification +4. Display build statistics + +## Deployment + +### Quick Deploy with Wrangler CLI + +Deploy directly from your local machine or CI/CD: + +```bash +# Production deployment +pnpm -F @refref/assets deploy:cloudflare + +# Dev/Preview deployment +pnpm -F @refref/assets deploy:cloudflare:dev + +# Local preview with Wrangler +pnpm -F @refref/assets preview +``` + +**First-time setup:** +```bash +# Login to Cloudflare (one-time) +pnpm -F @refref/assets exec wrangler login + +# Select your Cloudflare account when prompted +# Then deploy +pnpm -F @refref/assets deploy:cloudflare +``` + +**If you get auth errors:** +```bash +# Re-authenticate if token expires +pnpm -F @refref/assets exec wrangler logout +pnpm -F @refref/assets exec wrangler login +``` + +**Deployment Process:** + +The deploy commands automatically: +1. Build the assets (runs `tsx scripts/build.ts`) +2. Copy bundles from packages to `public/` with versioning +3. Deploy `public/` directory to Cloudflare Workers +4. Production deploys to `refref-assets` worker +5. Dev deploys to `refref-assets-dev` worker + +**After Deployment:** + +Your scripts will be available at your workers.dev URL: +- Production: `https://refref-assets..workers.dev/attribution.v1.js` +- Dev: `https://refref-assets-dev..workers.dev/attribution.v1.js` + +Example (replace with your account subdomain): +``` +https://refref-assets.exa-fc4.workers.dev/attribution.v1.js +https://refref-assets.exa-fc4.workers.dev/widget.v1.js +``` + +Test your deployment: +```bash +# Check if scripts are accessible +curl -I https://refref-assets..workers.dev/attribution.v1.js +``` + +**Custom Domain Setup:** + +After your first deployment: +1. Go to Cloudflare Dashboard → Workers & Pages +2. Select your worker (`refref-assets`) +3. Go to Settings → Domains & Routes +4. Add custom domain: `assets.refref.ai` +5. Cloudflare will automatically provision SSL certificate + +Then update your webapp environment: +```bash +# In apps/webapp/.env (or production environment) +NEXT_PUBLIC_ASSETS_URL="https://assets.refref.ai" +``` + +### Cloudflare Pages Setup (Alternative) + +If you prefer using Cloudflare Pages dashboard instead of Wrangler: + +1. **Connect Repository** + - Go to Cloudflare Pages dashboard + - Create new project from GitHub repo + - Select `refref` repository + +2. **Build Configuration** + ``` + Build command: pnpm -F @refref/assets build + Build output dir: apps/assets/public + Root directory: (leave as repo root) + ``` + +3. **Environment Variables** + - None required (static files only) + +4. **Custom Domain** + - Add custom domain: `assets.refref.ai` + - Configure DNS as instructed by Cloudflare + +### CI/CD Deployment + +Add to your GitHub Actions or CI/CD pipeline: + +```yaml +# .github/workflows/deploy-assets.yml +name: Deploy Assets to Cloudflare + +on: + push: + branches: [main] + paths: + - 'apps/assets/**' + - 'packages/attribution-script/**' + - 'packages/widget/**' + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: '20' + + - name: Install pnpm + uses: pnpm/action-setup@v2 + with: + version: 10 + + - name: Install dependencies + run: pnpm install + + - name: Build packages + run: | + pnpm -F @refref/attribution-script build + pnpm -F @refref/widget build + + - name: Deploy to Cloudflare + run: pnpm -F @refref/assets deploy:cloudflare + env: + CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} +``` + +**Setup:** +1. Create a Cloudflare API Token with Workers Deploy permissions +2. Add as `CLOUDFLARE_API_TOKEN` in GitHub Secrets +3. Push changes to trigger deployment + +### Configuration Files + +**wrangler.toml** - Wrangler configuration for Workers Assets: +```toml +name = "refref-assets" +main = "src/index.ts" # Worker script +compatibility_date = "2024-01-01" + +[assets] +directory = "./public" # Static assets directory +binding = "ASSETS" # Binding name for env.ASSETS + +[env.dev] +name = "refref-assets-dev" # Dev environment +``` + +**src/index.ts** - Worker script that handles: +- **Routing**: Redirects aliases (`/attribution.latest.js` → `/attribution.v1.js`) +- **Backward compatibility**: Maps `/scripts/*` to root files +- **Cache headers**: Immutable caching for versioned files +- **CORS**: Allows cross-origin requests for scripts + +## Usage + +### In Production + +Use the CDN URLs in your production application: + +```html + + + + + + + + + + + +``` + +**In Next.js (apps/webapp):** + +```typescript +// Configured via NEXT_PUBLIC_ASSETS_URL environment variable +