← All Articles 🔧 Tool-Specific Guides High By Nishant Kumar Verma

How to Start Vibe Coding (Without Shipping a Security Hole)

How to start vibe coding, step by step: pick a tool, write the first prompt, connect GitHub, keep keys in env vars, turn on Supabase RLS, then deploy.

SEC-014 SEC-006 SEC-001

Quick Answer

To start vibe coding, pick one AI tool and write a first prompt that says who uses the app, what data it stores and what must stay private. Connect GitHub early, so every change has a history you can undo. Keep API keys in the tool's secrets store or in environment variables, never in the chat or the code. If you use Supabase, turn on Row Level Security for every table and add policies. Then publish, and test the live app before you share the link.

Andrej Karpathy named vibe coding in a post on 2 February 2025: you talk to an AI model and "forget that the code even exists". Building that way is fast. But once real people sign up, the code you never read is holding their data. These seven steps go in order, with the one setting in each that keeps a first app from leaking.

Step 1: Pick One Tool

There are two kinds of tool. App builders run in your browser and build the whole app from chat. Coding agents work on code in your own editor or terminal. This is how each one describes itself in its own docs:

Tool Kind What its docs say it does
LovableApp builderBuilds and deploys full-stack web apps from plain-language chat
BoltApp builderBuilds websites and apps, with Bolt Database for storing data
Replit AgentApp builderTurns ideas into apps from plain language
CursorCoding agentA coding agent for building software
Claude CodeCoding agentReads your codebase, edits files and runs commands, in a terminal, IDE, desktop app or browser

Sources: Lovable, Bolt, Replit Agent, Cursor and Claude Code.

If you have never written code, an app builder is the easier start: Lovable and Bolt, for example, can host the app and store its data for you. If you already have a repository, a coding agent fits better. Pick one and stay with it for your first project.

Step 2: Write a First Prompt That Names the Data

Lovable's prompting guide suggests answering four questions before you type: what the product is, who it is for, why they will use it, and the one key action they should take. For a safe app, add three more: what data it stores, who may see each piece, and which keys it will need. A first prompt can look like this:

Build an invoice tracker for freelancers.
Who: freelancers sign up with email. Each one has their own clients and invoices.
Key action: create an invoice and mark it paid.
Data: client name, client email, amount, due date, paid or unpaid.
Private: a user can only ever see and change their own clients and invoices.
Database: use Supabase and turn on Row Level Security for every table.
Keys: Stripe comes later. Never write an API key into the code.
Before writing code, ask me about anything that is unclear.

The last line matters. The same guide recommends letting the tool ask questions before it writes code, and says Plan mode works well for this. After that, make one meaningful change per prompt, as the guide advises.

Never paste a key into the chat. Lovable's security docs say it detects API keys pasted into the project chat and steers you to its Secrets store instead. Step 4 covers where keys belong.

Step 3: Connect GitHub Before You Build Much

GitHub gives every change a record. A commit stores what changed, when, and who made the change. When a prompt breaks your app, you can revert that commit. The revert is a new commit that undoes it, and the original stays in the history.

  • Lovable: open Project settings, then Git, then GitHub, and click Connect. Lovable creates a new repository, private by default, and syncs both ways on one branch. It cannot link to an existing repository, and deleting the repository stops the sync (docs).
  • Bolt: click the GitHub icon in the top-right corner and log in. Bolt creates a commit when a change does not break the project, and a new repository starts as private (docs).
  • Coding agents: your project is a folder on your own machine. Claude Code, for example, works with git directly and can stage changes and write commit messages for you.

Add a .gitignore file before the first commit and list your .env files in it. GitHub's docs on ignoring files note that a rule there does not untrack a file that is already committed. You have to remove it with git rm --cached first.

Step 4: Keep Secrets in Environment Variables

Services such as Supabase and Stripe give you two kinds of key. A publishable key is meant for the browser. A secret key is not. Supabase says its publishable key is safe to expose, because it only reaches what Row Level Security allows, while a secret key bypasses every policy. Stripe's key docs treat its pk_ and sk_ keys the same way, and ask you not to put keys in source code checked into version control.

The trap is the prefix. Vite and Next.js both copy some variables into the code every visitor downloads:

Framework Sent to the browser Not sent to the browser
ViteVariables starting with VITE_Everything else
Next.jsVariables starting with NEXT_PUBLIC_Everything else

Sources: Vite env variables and Next.js environment variables.

Vite's docs say VITE_ variables should not hold API keys. Next.js writes NEXT_PUBLIC_ values into the JavaScript sent to the browser at build time. So a secret key must never carry either prefix.

import { createClient } from '@supabase/supabase-js'

// BAD: the secret key is typed into the code, so it lands in GitHub
const supabaseAdmin = createClient(
  'https://your-project.supabase.co',
  'sb_secret_...'
)

// BAD: the NEXT_PUBLIC_ prefix copies the secret into the browser bundle
const supabaseAdmin = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_SECRET_KEY!
)

// GOOD: browser code reads the publishable key from an environment variable
export const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!
)

// GOOD: server-only code (a route or a worker) reads the secret key, with no prefix
export const supabaseAdmin = createClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_SECRET_KEY!
)

Where the value lives depends on the tool. In a Lovable project connected to Supabase, you enter a key through the secure input Lovable shows. It is stored in your Supabase project for edge functions to read, never in your code or repository (docs). In Replit, open Tools, then Secrets, and add a New Secret, which reaches your app as an environment variable (docs). In your own project, keep keys in a .env file that git ignores.

If a key was ever committed, GitHub's guide to removing sensitive data says to revoke or rotate it first. Rotating may be all you need. More detail: hardcoded API keys in Bolt and Lovable and client-side secret exposure.

Step 5: Set Database Access Rules (Supabase RLS)

This step decides who can read your users' data. Lovable's Supabase docs put it plainly: "Missing RLS policies are the most common way app data gets exposed." Supabase's Row Level Security guide says to enable RLS on every table in an exposed schema, because a table without it is readable and writable by any role with a grant on it.

Turning RLS on with no policies locks the table: nothing comes back through the API with the publishable key until you add policies. The guide's steps are to enable RLS, revoke the existing grants from the anon and authenticated roles, grant back only what each role needs, and write one policy per operation. For the invoice app from Step 2:

-- BAD: RLS is off, so the table is open to any role with a grant on it

-- GOOD: turn RLS on, reset the grants, then allow each user only their own rows
alter table public.invoices enable row level security;
revoke all on table public.invoices from anon, authenticated;
grant select, insert, update, delete on table public.invoices to authenticated;

create policy "Users can view their own invoices"
on invoices for select
to authenticated
using ( (select auth.uid()) = user_id );

create policy "Users can create their own invoices"
on invoices for insert
to authenticated
with check ( (select auth.uid()) = user_id );

Add update and delete policies the same way, one each. The (select auth.uid()) form is the one Supabase recommends, because wrapping the call lets Postgres cache the result per statement instead of calling the function on each row. The guide also has you test the policies with supabase test db. Our guide to Supabase Row Level Security goes further.

Not on Supabase? The rule is the same: every read and every write must check who is asking.

Step 6: Deploy

In Lovable, click Publish in the top-right corner of the editor, then Publish again in the dialog. The app goes live at an address ending in lovable.app. On the Free and Pro plans the default visibility is Public, which means anyone with the URL can open it. Invite only, for up to 10 people per project, is the other choice, and a custom domain needs a paid plan (checked on 24 October 2026, docs).

Opening the Publish dialog also runs Lovable's Quick scan, which takes about 10 seconds and checks database access rules, dependencies and MCP server exposure. Its findings do not block publishing unless a workspace admin turns on "Block publishing with critical issues". Read them anyway.

If you deploy a Next.js app yourself, set the environment variables on the host before the build, because Next.js freezes NEXT_PUBLIC_ values at build time. Our guide to deploying a vibe-coded app to production covers SSL, headers and monitoring.

Step 7: Check Before You Share the Link

A builder's scan is a start, not a sign-off. Lovable's Quick scan does not cover your application code. Only the Deep scan does, and it does not run automatically as you work. Lovable's own docs say its tools "cannot guarantee complete security". Before you post the link anywhere, run these checks:

  1. The two-account test. Sign up as two test users. Create an invoice as one, then try to load it as the other. If you can, your access rules are wrong.
  2. Supabase Security Advisor. Open it in the dashboard, or run supabase db advisors. Its lint 0013_rls_disabled_in_public flags tables in the public schema with RLS off (docs).
  3. Keys in the bundle. Search the JavaScript your site sends for secret key prefixes. Supabase secret keys start with sb_secret_, and Stripe secret keys with sk_live_ or sk_test_.
# List the script files your home page loads
curl -sL https://your-app.lovable.app | grep -oE 'src="[^"]+\.js"'

# Search one of them for secret key prefixes (no output is what you want)
curl -sL https://your-app.lovable.app/assets/index-XXXX.js | grep -oE "sb_secret_|sk_live_|sk_test_"

Tools like VibeDoctor's Vibe Check (vibedoctor.io) automatically scan your repository and your live site, and flag secrets in the code (Gitleaks plus its own secret checks), dependency CVEs (Trivy), imports of packages that do not exist and missing security headers, with specific file paths and line numbers. Free to sign up.

For the full list, work through our vibe coding security checklist, and keep the habits in vibe coding best practices for every session after this one.

FAQ

What skills do you need for vibe coding?

Fewer than for writing code by hand, but not none. The steps in this guide come down to five: describing your users and data clearly in a prompt, saving your work with Git, knowing where secrets belong, setting who can read each record, and testing the live app as two different users.

What is vibe coding?

Building software by describing what you want to an AI tool and letting it write the code. Andrej Karpathy coined the term in a post on 2 February 2025.

How do I start vibe coding with no coding experience?

Start with an app builder that runs in the browser, such as Lovable or Bolt. Name your users, your data and what must stay private in the first prompt, then connect GitHub.

What should a vibe coding prompt include?

What the app is, who it is for, why they will use it and the one key action. Then add what data it stores, who may see each piece, and a rule that no API key goes into the code.

Is it safe to put my Supabase key in the frontend?

Only the publishable key. Supabase says it is safe to expose because it only reaches what Row Level Security allows. The secret key bypasses every policy, so it must never go in a browser, a shipped app or source control.

Do I need GitHub to vibe code?

Not to start, but connect it early. Every commit records what changed and when, so you can revert a prompt that broke your app.

Diagnose your codebase - free

VibeDoctor checks for SEC-014, SEC-006, SEC-001 and 148 other issues across 21 diagnostic areas - security, performance, code quality, and more.

SCAN MY APP →