DEV Community

Varun Krishnan
Varun Krishnan

Posted on

Day 2: Building SpeakSheet – Hit My First Rate Limit and Learned Why JSON Schemas Are Evil

Day 2 of building _SpeakSheet _in public – an AI tool that generates Excel spreadsheets from natural language prompts.

Today was a mix of small UX wins and frustrating technical challenges. Here's what happened.

Shipped: One-Click File Uploads
The Problem:
Users had to select a file AND click an "Upload" button before the backend would process it.

The Fix:
Made the upload trigger automatically when a file is selected.

The Code (simplified):

  const handleFileSelect = async (selectedFile) => {
    if (!selectedFile) return;
    console.log
    if (validateFile(selectedFile)) {
      setFile(selectedFile);
      toast.success(`File "${selectedFile.name}" selected`);

      try {
        setUploading(true);

        // Use selectedFile directly, not file state
        const { publicUrl } = await uploadToSupabase(selectedFile, user.id);

        setFile(publicUrl);
        toast.success("File uploaded successfully!");
      } catch (error) {
        console.error("File upload failed:", error);
        toast.error("File upload failed");
      } finally {
        setUploading(false);
      }
    }
  };
Enter fullscreen mode Exit fullscreen mode

The Lesson:
Sometimes the best features are the ones you remove. One less click = better UX.

🐛 Challenge #1: Supabase Storage Structure
The Problem:
Files weren't saving to Supabase storage, but no errors were showing in the console.

The Debug Process:

Checked file size limits ✅
Checked bucket permissions ✅
Checked network requests ✅
Re-read the Supabase docs... and found it.

The Issue:
A JSON schema error in my storage bucket configuration.
Error because of this line data[0].schema

The fix:One missing pair of square brackets.

The lesson: JSON schema errors fail silently and waste time. Always validate your config.

Challenge #2: Gemini API Rate Limits
Halfway through testing, I started getting this error:

text

Error: 429 - Resource has been exhausted (e.g. check quota).
First reaction: "Did I break something?"

Enter fullscreen mode Exit fullscreen mode

Reality: I'm hitting rate limits already.

Quick fix:

Swapped to a backup API key
Kept building
Long-term fix (needed):

Add request queueing
Show "High demand, please wait..." to users
Consider upgrading API tier or adding fallback models
The silver lining:
Hitting rate limits this early means I'm actually stress-testing the product. Better to discover this now than during launch.

🧠 What I Learned Today

  • UX wins come from removing steps

  • Fewer clicks > fancy features
    Test with production-level load early

  • Hitting rate limits in dev > hitting them in production
    JSON schema errors are silent killers

  • Always validate your configs
    Rate limits are validation
    Means you're using the product enough to stress-test it

Top comments (0)