Skip to content

feat(optimization): migrate to Supabase Edge Functions & Storage#554

Open
Schlomoh wants to merge 10 commits into
mainfrom
feat/optimization-supabase-rearchitecture
Open

feat(optimization): migrate to Supabase Edge Functions & Storage#554
Schlomoh wants to merge 10 commits into
mainfrom
feat/optimization-supabase-rearchitecture

Conversation

@Schlomoh
Copy link
Copy Markdown
Member

@Schlomoh Schlomoh commented May 30, 2026

This pull request introduces several significant improvements to the optimization workflow in the Vectreal platform, focusing on transitioning asset storage from Google Cloud Storage (GCP) to Supabase Storage, enhancing the optimization drawer UI with detailed metrics and file size comparisons, and modularizing optimization utilities for better maintainability and clarity.

Key changes include:

Migration from GCP to Supabase Storage

  • Updated .env.development.example to remove GCP storage credentials and variables, replacing them with Supabase equivalents and clarifying that Supabase Storage is now used for asset storage in all environments. [1] [2] [3]
  • Updated documentation in CLAUDE.md to reflect the storage migration and new Supabase workflow, including commands for serving Supabase edge functions and clarifying the role of the terraform directory. [1] [2]

Optimization Drawer UI & Metrics Enhancements

  • Refactored the optimization drawer (optimization-drawer.tsx) to display detailed before-and-after metrics, including triangles, texture size, and file size, with animated transitions and clear percentage/file size reduction labels. Added a dedicated FileSizeComparison component for visualizing file size changes. [1] [2] [3] [4] [5] [6] [7]

Modularization and Utility Improvements

  • Introduced new utility modules for optimization:
    • geometry-worker.ts: Runs geometry optimizations in a Web Worker to keep the UI responsive.
    • optimization-quota.ts: Handles quota checks and consumption for optimization runs, including guest limits and error handling.
    • scene-size.ts: Provides hooks for calculating scene and texture sizes post-optimization.
    • Centralized exports in utils/index.ts for easier imports.

Project Structure and Configuration

  • Added symlinks in .claude/skills/ to reference skills managed in .agents/skills/, ensuring proper skill resolution. [1] [2] [3]

These changes collectively modernize the asset storage approach, improve the user experience around model optimization, and enhance the maintainability of the optimization codebase.- feat(core): expose optional encoder injection in TextureCompressOptions

  • feat(platform): add Supabase Edge Function for texture optimization
  • feat(platform): route texture optimization through Supabase Edge Function
  • feat(optimization): run geometry steps in Web Worker, expose loadFromGlbBuffer
  • feat(storage): migrate asset storage from GCS to Supabase Storage
  • chore(cleanup): remove GCP Cloud Function, update env docs and CLAUDE.md
  • chore(cleanup): remove gcloud-storage startup validation

Schlomoh and others added 9 commits May 30, 2026 00:30
Adds an optional encoder field to TextureCompressOptions, allowing
callers to supply a custom image processor instead of relying on the
sharp native binary. When encoder is provided it is passed directly to
@gltf-transform/functions; otherwise sharp is dynamically imported as
before, preserving full backward compatibility.

This unlocks use of @vctrl/core in Deno/edge environments (e.g. Supabase
Edge Functions) where native binaries are unavailable.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces the GCP Cloud Functions v2 optimize-textures worker with a
Supabase Edge Function that runs locally via `supabase functions serve`
with zero GCP credentials required.

- index.ts: HTTP handler preserving the exact Cloud Function contract
- encoder.ts: imagescript-based encoder (pure TS/WASM, no native binaries)
  with a sharp-compatible shim for use with @vctrl/core
- types.ts: single source of truth for request contracts and parsing

Contributors can test locally with:
  supabase functions serve optimize-textures
  curl -X POST http://localhost:54321/functions/v1/optimize-textures ...

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tion

Replaces the GCP Cloud Function proxy and local Sharp fallback with a
call to the optimize-textures Supabase Edge Function. The function URL
is derived from the existing SUPABASE_URL env var so no new variables
are required.

The OPTIMIZE_TEXTURES_WORKER_URL and OPTIMIZE_TEXTURES_WORKER_TOKEN env
vars are no longer read. Quota enforcement and request validation are
unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…GlbBuffer

Non-texture optimizations (simplify/dedup/quantize/normals) now run in an
off-main-thread Web Worker so the UI stays responsive during CPU-intensive
operations. Results are transferred back via zero-copy ArrayBuffer handoff
and reloaded into the optimizer via a new loadFromGlbBuffer hook method.
Texture compression continues through the Supabase Edge Function as before.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace @google-cloud/storage with Supabase Storage (service role client)
for all asset upload, download, and delete operations. Enable the storage
service in supabase/config.toml and add a migration that creates the
private assets bucket with RLS policies mirroring the assets table access
rules. Remove the @google-cloud/storage dependency from package.json.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Delete the legacy apps/vectreal-platform/functions/optimize-textures/ Cloud
Function source that is superseded by the Supabase Edge Function. Remove
the Terraform resources (optimization-functions.tf), variables, output, and
artifact zip for the Cloud Function. Update .env.development.example to drop
GCP storage vars and add SUPABASE_SERVICE_ROLE_KEY entries. Fix two type
errors in optimization.worker.ts (postMessage transfer + OperationProgress
field name).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove the validateLocalGoogleCloudStorageConfiguration() call from
entry.server.tsx and delete gcloud-storage.server.ts — the last GCP
dependency blocking local dev without GCP credentials.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Updated `useCalcOptimizationInfo` to use state instead of ref for initial report, ensuring re-renders on capture.
- Enhanced `useOptimizeModel` to support loading GLTF models directly from raw bytes with asset maps.
- Introduced `createBrowserTextureEncoder` for client-side texture compression using OffscreenCanvas, removing server dependency.
- Simplified texture optimization logic by removing server-side optimization functions and delegating to the new browser encoder.
- Removed unused validation utilities and adjusted server communication to streamline request handling.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@Schlomoh
Copy link
Copy Markdown
Member Author

Code review

Found 3 issues:

  1. USDZ files crash the optimizerloadBinaryModel calls optimizer.loadFromGlbBuffer(new Uint8Array(await file.arrayBuffer())) for all binary formats, but USDZ files are ZIP archives, not GLB. ModelOptimizer.loadFromBuffer() validates the glTF magic bytes and throws "Invalid glTF 2.0 binary. Expected 'glTF' magic bytes, got..." for USDZ. USDZ support is explicitly advertised (use-load-model.ts L51, L146–155) but will silently error whenever a USDZ is uploaded with optimization enabled.

if (optimizer) {
const buffer = new Uint8Array(await file.arrayBuffer())
await optimizer.loadFromGlbBuffer(buffer)
}

  1. CLAUDE.md commands section references the deleted optimize-textures Edge Function — the PR deletes apps/vectreal-platform/functions/optimize-textures/ entirely, but the supabase functions serve comment in CLAUDE.md still says # serve optimize-textures at :54321/functions/v1/. The command will not work; the function no longer exists.

# Supabase (local) — includes DB, Auth, Storage, and Edge Function runtime
pnpm supabase start
pnpm supabase functions serve # serve optimize-textures at :54321/functions/v1/
pnpm nx run vectreal-platform:supabase-db-reset

  1. loadFromServer throws the original plain Error instead of the structured StructuredLoadErrornormalizeServerLoadError(error, sceneId) creates a StructuredLoadError and emits it via the event system, but then throw error re-throws the original plain Error. Callers like use-preview-scene.ts catch the thrown error and call isStructuredLoadError(error), which will always return false since a plain Error is received. The not_found/quota_exceeded code-based error differentiation in the preview UI is therefore dead code.

return sceneLoadResult
} catch (error) {
console.error('Server scene loading failed:', error)
dispatch({ type: 'set-file-loading', payload: false })
eventSystem.emit(
'server-load-error',
normalizeServerLoadError(error, sceneId)
)
throw error
}

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants