Firebase + Cloudflare setup
This is a one-time developer setup for the new TrinoTime Cloud environment. Do not reuse the original TrinoTime Firebase project or credentials.
Keep server credentials out of GitHub
The Firebase web-app values are designed to be used by browsers. The service-account private key is different: store it only as a Cloudflare Secret. Never paste the private key into a JavaScript file, README, or GitHub commit.
Create the new Firebase project
Create a fresh Firebase project, register a Web App, then enable Email/Password in Authentication. Create a Cloud Firestore database for this new SaaS project. Choose the database region carefully based on your intended customers.
Authorize your Cloudflare hostname
In Firebase Authentication settings, add your current hostname such as trinotime.trinoadmin.workers.dev to Authorized domains. Add the final production domain later.
Add Firebase web variables to Cloudflare
Open the TrinoTime Worker settings and add these variables from your Firebase Web App configuration:
FIREBASE_API_KEY FIREBASE_AUTH_DOMAIN FIREBASE_PROJECT_ID FIREBASE_APP_ID FIREBASE_STORAGE_BUCKET (required for direct Brand Studio upload) FIREBASE_MESSAGING_SENDER_ID (optional)
Add the service-account credentials as secrets
From Firebase / Google Cloud, generate a service-account JSON key for this new project. Store the following in Cloudflare. Treat the private key as a Secret.
FIREBASE_CLIENT_EMAIL FIREBASE_PRIVATE_KEY
If Cloudflare stores the key with literal \n characters, the Worker normalizes them at runtime. For v1.1.3 direct logo/favicon upload, this service account must also be allowed to create objects in the configured Storage bucket.
Optional Brand Studio custom domains
Business custom domains use manual DNS mode by default. To enable automatic Cloudflare for SaaS custom-hostname provisioning and status checks, add:
CLOUDFLARE_SAAS_API_TOKEN (Secret) CLOUDFLARE_SAAS_ZONE_ID (Variable) CUSTOM_DOMAIN_CNAME_TARGET (Variable)
Keep the API token narrowly scoped to the TrinoTime zone. Configure the zone/fallback origin so customer hostnames route to this Worker.
Publish the included Firestore rules
Open Firestore → Rules in the new Firebase project and publish the contents of firestore.rules from this repository. The current rules keep privileged operational, payroll, billing, Brand Studio hostname-registry and Storage paths fail-closed to direct browser access; the Cloudflare Worker performs authorized server-side writes.
Configure Lemon Squeezy subscriptions
For paid plans, store the Lemon Squeezy API key and webhook signing secret as Cloudflare Secrets. Add the Test Mode product and variant IDs as Variables:
LEMONSQUEEZY_API_KEY LEMONSQUEEZY_WEBHOOK_SECRET LEMONSQUEEZY_PRODUCT_STARTER=1338765 LEMONSQUEEZY_VARIANT_STARTER=2091581 LEMONSQUEEZY_PRODUCT_PRO=1338796 LEMONSQUEEZY_VARIANT_PRO=2091638 LEMONSQUEEZY_PRODUCT_BUSINESS=1338803 LEMONSQUEEZY_VARIANT_BUSINESS=2091652
Create the Test Mode webhook endpoint at /api/billing/lemonsqueezy/webhook. Keep Lemon Squeezy's own product trial disabled because TrinoTime controls the 30-day workspace trial.
Redeploy, then create your owner account
Push the new release to GitHub. Cloudflare will deploy it. Open /app/, create your account, verify the email, and create the first workspace.
Enable the Platform Owner console
In Firebase Authentication → Users, copy the UID of your owner account. Add it to Cloudflare as:
PLATFORM_OWNER_UID=your_firebase_uid
Redeploy. Only that exact UID can use /platform/. Being a Company Owner or Admin is not enough.
Expected result
Account → verified email → server-provisioned workspace → Owner membership → default General team → 30-day trial → secure invitations → Owner/Admin Billing recovery and Lemon Squeezy subscription flow. A user can load only tenants represented by authoritative membership records.