Firebase Storage: Project cover images
Project cover images are uploaded via the app’s API (server-side) to avoid CORS. The browser sends the file to POST /api/projects/[projectKey]/upload-image; the server uploads to the bucket and returns a signed URL. No CORS configuration is required for uploads.
Images are stored at:
project-images/{projectKey}/{timestamp}-{filename}
CORS (required for uploads from browser)
If you see CORS errors in the console when uploading (e.g. from http://localhost:3000), the Storage bucket must allow your origin. Firebase Storage does not allow cross-origin requests by default.
One-time setup with gsutil
-
Install Google Cloud SDK (includes
gsutil): https://cloud.google.com/sdk/docs/install -
Authenticate and set project:
gcloud auth login
gcloud config set project gtc-tools-dev -
Find your Storage bucket name. The Firebase Console shows a URL like
gtc-tools-dev.firebasestorage.app, but the GCS bucket name is often different. List buckets:gsutil lsUse the bucket that matches your project (commonly
gs://gtc-tools-dev.appspot.com). You can also copy the bucket name from Firebase Console → Storage → Files (bucket is shown at the top). -
Apply CORS (replace
BUCKET_NAMEwith the bucket from step 3). The app usesgtc-tools-dev.appspot.comby default, so CORS must be set on that bucket:gsutil cors set apps/web/firebase-storage.cors.json gs://BUCKET_NAMEExample:
gsutil cors set apps/web/firebase-storage.cors.json gs://gtc-tools-dev.appspot.com -
Add production origin to
apps/web/firebase-storage.cors.jsonif you host on a different domain, then run thegsutil cors setcommand again.
After this, uploads and image loads from the configured origins will work.
Storage rules
Ensure your Firebase Storage rules allow authenticated users to read and write under project-images/. Example (Firebase Console → Storage → Rules):
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /project-images/{projectKey}/{allPaths=**} {
allow read: if true;
allow write: if request.auth != null;
}
}
}
- read: public so project cards can show images without auth.
- write: only authenticated users can upload (prevents anonymous uploads).
Adjust to match your security requirements (e.g. restrict read to authenticated users if needed).