Conversation
- Convert Next.js to static export (output: "export") - Move sanitization logic to worker/ with Hono - Frontend now calls /api/sanitize endpoint client-side - Remove SSR dependencies (got, js-yaml from frontend) - Update Dockerfile for static site serving
- POST /api/bot/telegram for Telegram webhook integration - POST /api/bot/matrix for Matrix bot integration - Both extract text, sanitize URLs, and return formatted responses
- Pulsing skeleton for loading state - Smooth transition on copy feedback
- POST /api/ai-sanitize endpoint using Cloudflare Workers AI - Uses function calling to ensure structured response - Returns sanitized URL with confidence score - Suggests sanitization rules for contribution - Frontend offers AI option when rule matching fails
- POST /api/browser-sanitize endpoint using CF browser rendering - Renders pages with/without params to find minimum required set - Compares title, OpenGraph data, and body length for similarity - Returns verified sanitized URL and suggested rule - Frontend offers browser render as alternative to AI
- Submit rule button after AI/browser sanitization success - Prefills GitHub issue with URL, sanitized URL, and YAML rule - Uses rule-request label for easy filtering
- Remove original URL from GitHub issue submission, only include domain - Use screenshot-based page similarity comparison for accurate matching - Update page rendering to capture screenshots instead of DOM analysis - Add Cloudflare Puppeteer dependency for browser rendering
- Add multi-turn vision comparison using llama-3.2-11b-vision-instruct - First turn: describe screenshot A - Second turn: compare description with screenshot B - Keep quick heuristic check (title/OG metadata) as fast path - Extract title and OG metadata during page render for heuristics
- Replace React/Next.js with Svelte 5 and SvelteKit - Use static adapter for output to /out directory - Migrate all pages: index, sanitize, 404 - Migrate all components: Layout, Footer, H1, H2, LinkBox, ActionBtn - Keep exact same UI design and Tailwind styles - Update ESLint and Prettier configs for Svelte - Fix GitHub issue URL to point to /Rules repo
0ef11a8 to
cd89684
Compare
There was a problem hiding this comment.
Pull request overview
This PR performs a major framework migration from Next.js/React to SvelteKit/Svelte while also introducing a new Cloudflare Workers-based backend API. The changes include restructuring the application architecture, moving sanitization logic to edge workers, and adding AI-powered and browser-based URL sanitization features.
Key changes include:
- Migration from Next.js SSR to SvelteKit with static site generation
- New Cloudflare Workers API with AI and browser rendering capabilities
- Complete rewrite of frontend components from React to Svelte
- Addition of end-to-end tests using Playwright
Reviewed changes
Copilot reviewed 44 out of 50 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| worker/src/index.ts | Main Cloudflare Worker implementing API endpoints for sanitization, Telegram/Matrix bots, AI analysis, and browser-based verification |
| worker/src/sanitizer.ts | Core URL sanitization logic moved to the worker with link expansion and parameter filtering |
| worker/src/types.ts | TypeScript type definitions for rules and worker environment |
| worker/wrangler.toml | Cloudflare Workers configuration with KV, AI, and Browser bindings |
| src/routes/*.svelte | SvelteKit pages replacing Next.js pages (home, sanitize, error) |
| src/lib/components/*.svelte | Reusable Svelte components replacing React components |
| package.json | Updated dependencies from Next.js ecosystem to SvelteKit/Vite |
| e2e/*.spec.ts | New Playwright end-to-end tests for the application |
| svelte.config.js | SvelteKit configuration for static site generation |
| Dockerfile | Updated to serve static files instead of Next.js server |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
worker/src/index.ts
Outdated
| return result.toUpperCase().includes("SAME"); | ||
| } | ||
|
|
||
| async function arePagesSimlar( |
There was a problem hiding this comment.
There is a spelling error in the function name. The function is named "arePagesSimlar" but should be "arePagesSimilar" (missing the second 'i').
worker/src/index.ts
Outdated
| const baseUrl = `${parsedUrl.origin}${parsedUrl.pathname}`; | ||
| const noParamsPage = await renderPage(c.env.BROWSER, baseUrl); | ||
|
|
||
| if (await arePagesSimlar(c.env.AI, originalPage, noParamsPage)) { |
There was a problem hiding this comment.
The misspelled function name "arePagesSimlar" is being called here. This should be "arePagesSimilar" to match the correct spelling.
worker/src/index.ts
Outdated
| urlWithoutThisParam.toString(), | ||
| ); | ||
|
|
||
| if (!(await arePagesSimlar(c.env.AI, originalPage, pageWithoutThisParam))) { |
There was a problem hiding this comment.
The misspelled function name "arePagesSimlar" is being called here as well. This should be "arePagesSimilar" to match the correct spelling.
Dockerfile
Outdated
| ENV PORT=3000 | ||
|
|
||
| CMD ["node", "server.js"] | ||
| CMD ["npx", "serve", "out", "-l", "3000"] |
There was a problem hiding this comment.
The CMD uses npx serve to start the production container, which downloads and executes the serve package (and its dependencies) from npm at runtime without pinning a specific version or verifying integrity. This creates a supply chain risk where a compromised npm package or registry could run arbitrary code inside your production container and serve tampered assets. Prefer installing a pinned version of serve (or another static file server) at build time and invoking the local binary instead of npx-installing it on each container start.
- Add Playwright configuration for e2e testing - Add home page tests (title, heading, form, footer) - Add sanitize page tests with mocked API responses - Add navigation tests (footer links, 404 page) - Extend GitHub Actions workflow with e2e test job - Test both success and failure API scenarios
cd89684 to
d9d1ae1
Compare
- Remove /sanitize page and query params to prevent URL exposure in browser history - Show sanitization results inline on the same page - Add "Sanitize another link" button to reset state - Improve ARIA labels in footer for better accessibility and testing - Update ESLint config with ignoreLinks for navigation rule - Simplify Cloudflare notice to only link privacy policy - Consolidate e2e tests into home.spec.ts
- Remove Docker workflow and Dockerfile - Add Cloudflare Pages deployment workflow (main branch only) - Requires CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID secrets
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 45 out of 51 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Add deploy-worker.yml for Cloudflare Workers deployment - Only triggers on changes to worker/ directory on main branch - Update README with comprehensive worker development documentation - Document local development workflow with VITE_API_URL
ff7bb33 to
3cad2f3
Compare
| name: Deploy to Cloudflare Workers | ||
| runs-on: ubuntu-latest | ||
| defaults: | ||
| run: | ||
| working-directory: worker | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v6 | ||
|
|
||
| - name: Setup Node.js 24 | ||
| uses: actions/setup-node@v6 | ||
| with: | ||
| node-version: 24 | ||
|
|
||
| - name: Install dependencies | ||
| run: npm ci | ||
|
|
||
| - name: Deploy Worker | ||
| uses: cloudflare/wrangler-action@v3 | ||
| with: | ||
| apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} | ||
| accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} | ||
| workingDirectory: worker | ||
| command: deploy |
Check warning
Code scanning / CodeQL
Workflow does not contain permissions Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 3 months ago
To fix the problem, explicitly define minimal GITHUB_TOKEN permissions for this workflow or job so it no longer relies on repository/organization defaults. Since the job only needs to check out the repository and then use a separate Cloudflare API token, it only needs read access to repository contents.
The best way to fix this without changing functionality is to add a permissions block at the root of the workflow (so it applies to all jobs) with contents: read. Concretely, in .github/workflows/deploy-worker.yml, insert:
permissions:
contents: readbetween the on: block and the concurrency: block (after current line 8). This will ensure the GITHUB_TOKEN is restricted to read-only access to repository contents while leaving the rest of the workflow unchanged.
| @@ -6,6 +6,9 @@ | ||
| paths: | ||
| - "worker/**" | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.ref }} | ||
| cancel-in-progress: true |
f82fc44 to
a3400e3
Compare
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
tail-wtf | c645eec | Dec 27 2025, 01:28 PM |
b522d2a to
ef72068
Compare
No description provided.