Start here: Vibe coding that doesn’t break
This is a true beginner tutorial. You will copy prompts, click buttons, and ship a tiny app without needing to “know programming” first.
The one default path (no choosing)
- Build: Next.js app inside Firebase Studio
- Publish (default): Firebase Studio → Publish → App Hosting
- Publish (Plan B fallback): Firebase CLI → App Hosting (see Appendix)
- Data: Firebase Auth + Firestore
- AI: Gemini API via a backend endpoint
What you’ll have at the end
- A working public URL you can open on your phone
- Login + saved items + AI summarizer
- Secure Firestore rules (users can’t see each other’s data)
- A reusable 2-account privacy test for every app you build
Quick orientation (10 minutes)
- Open studio.firebase.google.com in your browser.
- Sign in with your Google account.
- Create a workspace (choose a web template if offered).
- Find a Preview panel and start it.
How to use this page
- Each lesson has step checkboxes. They save locally in your browser (so you can return later).
- Prompts are copy-ready. Paste them into your vibe coding AI chat inside Firebase Studio.
- If a button name differs, use Ctrl/Cmd+F and search for words like Publish, Deploy, or Hosting.
Glossary (read once)
Every important term is defined once here. In lessons, terms link back to this section.
What you will build
A tiny micro-SaaS called SummaryBox:
- Users create an account and log in.
- They paste text and click “Summarize”.
- The app calls the Gemini API and returns a short summary.
- The app saves the original text + summary to Firestore.
Lesson 1 — Create & publish your first app
Goal: create a basic web app in Firebase Studio and publish it online (get a public URL).
Publishing backend code (later for AI) usually requires Blaze plan. This doesn’t mean “expensive”—it means “pay only for what you use.” Set a budget alert.
Open Firebase Console → Create project → finish setup.
If you can’t find the button: search the page for “Create project”.
In Firebase Studio, create a web app workspace (choose Next.js if offered).
If you see multiple templates, choose the simplest “web app” option.
I am a complete beginner. Create a minimal Next.js web app with: - Home page that shows the title “SummaryBox” - A link button that goes to /login (even if it’s empty for now) Keep it simple. Before coding: list the files you will change. After coding: tell me exactly which button to click to run the app in Preview.
Start Preview and confirm you can see “SummaryBox”.
If Preview is missing: ask Studio AI “Where is the Preview panel?”
In Firebase Studio, click Publish (or Deploy), choose App Hosting, connect your Firebase project, and finish.
If you don’t see “Publish”: search the UI for “Deploy”, “Hosting”, or open the Firebase panel inside Studio.
Create a checkpoint:
- If Git is available: commit (“Lesson 1: published skeleton”).
- If not: export/download the project as a ZIP.
Lesson 2 — Add login (Firebase Authentication)
Goal: users can create an account and log in. The app shows the main screen only after login.
Firebase Console → Build → Authentication → Sign-in method → enable Email/Password.
If you can’t find it: search the page for “Sign-in method”.
Add Firebase Authentication (Email/Password) to this Next.js app. Requirements (beginner-friendly): - Create /login page with email + password inputs. - Add two buttons: “Sign up” and “Sign in”. - Create /app page that is protected: - If NOT logged in: redirect to /login. - If logged in: show “Welcome” and the user’s email. - Add a “Sign out” button on /app. - Keep changes small. Before coding, list exactly which files you will change. Try to keep it under 6 files.
- Open /login
- Create an account (Sign up)
- Log in (Sign in)
- Confirm /app shows your email
- Sign out, confirm you return to /login
Publish so login works on your public URL.
Commit/export ZIP (“Login version”).
Lesson 3 — Save data (Firestore database)
Goal: logged-in users can save items and see their past items.
Firebase Console → Build → Firestore Database → Create database.
Add Firestore storage for this app. Requirements: - In /app, add a textarea called “Original text” and a button “Save”. - When user clicks Save, store a document in Firestore collection “items” with fields: userId, userEmail, originalText, createdAt - Below the form, show the user's last 10 saved items (most recent first). - Make sure the code includes the userId on every saved item. - Keep the change small (under 8 files). List the files first.
Log in, save two items, refresh the page.
You should see: saved items still appear after refresh.
Publish so saved items work on the public link.
Commit/export ZIP (“Database version”).
Lesson 4 — Add AI summarization (Gemini API)
Goal: user pastes text → clicks Summarize → gets a short summary → app saves it.
- Your Gemini API key is like a password. If it leaks, someone can spend your money.
- Never paste the key into frontend code.
- Never name it with NEXT_PUBLIC_ (that exposes it to the browser).
- Store it as an environment variable and use it only inside backend code (API endpoints).
Open Google AI Studio → create an API key → copy it.
Store it privately. Treat it like a password.
Add an env var named GEMINI_API_KEY in your deployment settings.
If you’re using App Hosting, set secrets/env vars there. If Studio UI is unclear, use the Appendix notes.
Add an AI summarizer using the Gemini API.
Requirements:
- Create a backend endpoint /api/summarize.
- It accepts JSON: { text: string }.
- It uses GEMINI_API_KEY from environment variables (NOT from frontend).
- It returns JSON: { summary: string }.
- In /app, add a button “Summarize” that calls /api/summarize using the text in the textarea.
- After summarizing, save the summary into the existing Firestore document (add field: summaryText).
- Add friendly errors: if AI fails, show “Could not summarize. Try again.”
- Keep it small: list files first, aim under 10 files.
Paste a paragraph, click Summarize.
You should see: a short summary. Refresh and confirm it remains saved.
Publish so summarization works on the public link.
Commit/export ZIP (“AI version”).
Lesson 5 — Secure rules + 2-account privacy test + ship safely
Goal: lock down Firestore so users cannot see each other’s data, then verify it.
Part A — Replace “test mode” with real Firestore rules
Firebase Console → Firestore Database → Rules.
Replace your current rules with the template below, then click Publish.
If you can’t find Publish: look for “Save” or “Publish” at the top-right of the rules editor.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function signedIn() {
return request.auth != null;
}
function isOwner(data) {
return signedIn() && data.userId == request.auth.uid;
}
// Private user items (the main data)
match /items/{itemId} {
// Create: must be signed in and must write their own userId
allow create: if signedIn()
&& request.resource.data.userId == request.auth.uid;
// Read/update/delete: only if the stored item belongs to you
allow read, update, delete: if isOwner(resource.data);
}
// Rate limit / usage counters (optional)
match /usage/{usageId} {
allow create: if signedIn()
&& request.resource.data.userId == request.auth.uid;
allow read, update, delete: if isOwner(resource.data);
}
// Error logs: block all client access (server code can still write using admin credentials)
match /errors/{errorId} {
allow read, write: if false;
}
}
}
Part B — The 2-account privacy test (this catches hidden insecurity)
- Sign up with Email A
- Save 1 item
- Summarize it
- Sign out
- Sign up with Email B
- Confirm B cannot see A’s items
Expected result: B’s list should be empty (or only B’s items).
If Account B can see Account A’s data (fix now)
- Open Firestore and check if every item document contains a userId field.
- Confirm rules include resource.data.userId == request.auth.uid for reads.
- Ask your AI in Studio: “Here are my Firestore rules and item documents. Why can B see A?”
Part C — Release gates (non-negotiable)
Before every publish, all gates must be “Yes”.
After all gates pass, publish again.
Appendix — Deploy Plan B + Rules + Privacy tests + Key safety
Deploy Plan B: Firebase CLI → App Hosting
Use this if you cannot publish from Studio. It is longer, but reliable. Key terms: Terminal, CLI, App Hosting.
- Firebase project with Blaze billing enabled
- Node.js (LTS) installed on your computer
- Firebase CLI installed
- Export/download your Firebase Studio project to your computer.
- Open a Terminal in the folder that contains package.json.
- Install Firebase CLI:
npm install -g firebase-tools
- Log in:
firebase login
- Initialize App Hosting in your project folder:
firebase init apphosting
When prompted: select your Firebase project, confirm the app root directory (the folder with package.json), and create/select an App Hosting backend.
- Deploy:
firebase deploy
Firestore rules explained (simple)
The rules you used do two core things:
- Create: you can only create items where userId equals your logged-in id.
- Read/Update/Delete: you can only access items where the stored userId matches you.
Privacy tests to reuse forever
1) 2-account test (human test)
- Create Account A → save 1 item.
- Log out.
- Create Account B → confirm B cannot see A’s item.
2) Optional “link guessing” test
If your UI ever exposes item IDs, try to access an item as Account B. It should fail. This catches “IDOR” style bugs (insecure direct object reference).
Key safety (expanded)
- Never commit keys into your repo (don’t paste into code files).
- Never put keys in frontend code.
- Never prefix secret keys with NEXT_PUBLIC_.
- Use GEMINI_API_KEY as a server-only environment variable.
Beginner mindset: “Where should secrets live?”
A secret (API key) should be stored where the browser cannot read it. That means: deployment settings (env vars / secrets), and used only in backend endpoints.
Printable checklist (use every time)
One feature loop
- Write a 10-line spec (what the user does + what they get).
- Ask AI to change as few files as possible (small diff).
- Run in Preview and click through the feature.
- Try bad inputs (empty, long, wrong type).
- Run the 2-account privacy test if any data is saved.
- Publish only after release gates pass.
- Checkpoint (commit or export ZIP).
Release gate (must be all “Yes”)
| Gate | Yes/No |
|---|---|
| App runs (no blank screens) | □ |
| Login works (signup/signin/signout) | □ |
| Smoke test passes end-to-end | □ |
| Bad inputs don’t crash it | □ |
| Errors are friendly + retry works | □ |
| Privacy test passes (2-account) | □ |
Production minimums
- Firestore rules locked down (no test mode)
- Secrets stored as env vars / secrets (never in code)
- Rate limiting on expensive actions (AI calls)
- Error logging so you can see failures
