DEV Community

Cover image for The 48-Hour Button: Fighting Supabase, Google Auth, and "Scope Creep"
Varun Krishnan
Varun Krishnan

Posted on

The 48-Hour Button: Fighting Supabase, Google Auth, and "Scope Creep"

I just spent 48 hours building a feature the user will never notice.
It wasn't a complex algorithm. It wasn't a 3D animation.

It was a "Sign in with Google" button.

For the past two days, the Direct Google Sheets integration—my most requested feature—was dead on arrival.

Here is the technical breakdown of why "simple" integrations are rarely simple, and how I solved the Supabase Scope conflict.

The Invisible Villain:

Supabase vs. Google Scopes
The goal was simple:

User logs into SpeakSheet.
User clicks "Export to Google Sheets."
My app writes the data to their Drive.

I am using Supabase for authentication. It handles the login flow perfectly. But when I tried to push data to the Google Sheets API, I got the same error loop:
403: Insufficient Permission

I debugged for hours. I checked the Google Cloud Console. I checked the API keys. Everything looked green.

The Realization
The issue wasn't the API; it was the Auth Token.
By default, Supabase Auth requests basic scopes: email and profile. It does not request spreadsheets (write access).

The token I held verified who the user was, but it didn't have permission to touch their files.

The Fix: Decoupling the Auth
I tried to force the scope into the initial login, but it created a messy user experience (asking for full Drive access just to sign up?).

I realized I had to change the workflow.

The New Flow:

Login: User signs in via Supabase (Standard Email/Profile scope).
App Access: User builds their prompt and generates the schema.
Integration: When they click "Export to Google Sheets," I trigger a secondary re-authentication.
This specific step asks only for the Sheets permission. It separates "Identity" from "Capability." It’s cleaner, safer, and it finally works.

From "Text" to "Logic"
Once the gate was open, I had to ensure the payload was correct.

This is the difference between ChatGPT and SpeakSheet.
If you ask a standard LLM for a "Budget Tracker," it gives you a text explanation.
I need to give you working cells.

My system prompt enforces a strict JSON schema. It flags specific fields as Formula:

{"formulaLabel":"Sum", "formula":"("=SUM(C:C))"}

Before: The API treated formulas as text strings.
Now: The API recognizes the = operator and parses logic, including complex IF statements.

What’s Next? (The boring part)
The engine is running. The integration is live.
Now, I have to build the toll booth.

I am implementing the Pricing page next.
I have chosen LemonSqueezy as my merchant of record.

Why? Because Stripe is currently not onboarding new businesses in India.
The Upside: LemonSqueezy handles the tax compliance, which lets me focus on the code.

The MVP is 90% complete.
Next update: The Mobile Responsiveness fix.

Top comments (0)