/how-to-build-lovable

How to build Habit tracker with Lovable?

Build a habit tracker with Lovable: step-by-step guide to set goals, track progress, customize templates and boost productivity

Book a free  consultation
4.9
Clutch rating 🌟
600+
Happy partners
17+
Countries served
190+
Team members
Matt Graham, CEO of Rapid Developers

Book a call with an Expert

Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.

Book a free No-Code consultation

How to build Habit tracker with Lovable?

You can build a simple habit tracker entirely inside Lovable by using Chat Mode to create and edit files, Preview to run and test the app, and the Lovable Cloud Secrets UI if you want a Supabase backend. No terminal is required for the basic app — only for advanced build/deploy workflows (see GitHub export note). Below I give step-by-step Lovable prompts you can paste into the Lovable chat to implement a localStorage-based tracker and an optional Supabase-backed upgrade.

 

What we’re building / changing (plain English)

 

A small React habit-tracker web app with a habits list, create/delete/toggle completion, and persistence. Two options:

  • Local-only using browser localStorage (works entirely in Lovable Preview and Publish).
  • Optional Supabase-backed to store habits in the cloud (requires creating a Supabase project outside Lovable and adding Secrets in Lovable).

 

Lovable-native approach

 

Use Chat Mode edits to create/modify files (no terminal). Use Preview to run and iterate. Use Lovable Cloud Secrets UI to store SUPABASE_URL and SUPABASE_ANON\_KEY if you choose Supabase. If you need server functions or CI you’ll export/sync to GitHub (outside Lovable) — I’ll call that out where relevant.

 

Meta-prompts to paste into Lovable

 

  • Prompt 1 — Scaffold app and UI (local-only)
    <p><b>Goal:</b> Create a minimal React app and habit UI stored in localStorage.</p>
    
    <p><b>Files to create/modify:</b> create these files with exact paths:</p>
    
    <ul>
      <li>package.json</li>
      <li>src/main.tsx</li>
      <li>src/App.tsx</li>
      <li>src/pages/HabitsPage.tsx</li>
      <li>src/components/HabitItem.tsx</li>
      <li>src/styles.css</li>
    </ul>
    
    <p><b>Acceptance criteria (done when):</b> In Lovable Preview you see a "Habit Tracker" page, can add a habit, toggle done, and the list persists after reload.</p>
    
    <p><b>Prompt to paste:</b></p>
    
    \`\`\`
    

    // Create package.json (basic metadata; Lovable may already provide a template)
    // // If your project already has package.json, skip creating and just add dependencies in the file.
    {
    "name": "lovable-habit-tracker",
    "version": "0.1.0",
    "private": true,
    "scripts": {
    "dev": "vite",
    "build": "vite build",
    "start": "vite preview"
    },
    "dependencies": {
    "react": "^18.0.0",
    "react-dom": "^18.0.0"
    },
    "devDependencies": {
    "vite": "^5.0.0",
    "@vitejs/plugin-react": "^3.0.0",
    "typescript": "^5.0.0"
    }
    }

    
    

    // src/main.tsx
    import React from "react";
    import { createRoot } from "react-dom/client";
    import App from "./App";
    import "./styles.css";

    createRoot(document.getElementById("root")!).render();

    
    

    // src/App.tsx
    import React from "react";
    import HabitsPage from "./pages/HabitsPage";

    export default function App(){
    return

    Habit Tracker

    ;
    }

    
    

    // src/pages/HabitsPage.tsx
    import React, { useEffect, useState } from "react";
    import HabitItem from "../components/HabitItem";

    type Habit = { id: string; title: string; done: boolean; };

    const STORAGE_KEY = "lovable.habits.v1";

    export default function HabitsPage(){
    const [habits, setHabits] = useState<Habit[]>([]);
    const [text, setText] = useState("");

    useEffect(()=>{
    const raw = localStorage.getItem(STORAGE_KEY);
    if(raw) setHabits(JSON.parse(raw));
    },[]);

    useEffect(()=>{ localStorage.setItem(STORAGE_KEY, JSON.stringify(habits)); },[habits]);

    function add(){ if(!text.trim()) return; setHabits(h=>[{id:Date.now().toString(),title:text.trim(),done:false},...h]); setText(""); }
    function toggle(id:string){ setHabits(h=>h.map(x=>x.id===id?{...x,done:!x.done}:x)); }
    function remove(id:string){ setHabits(h=>h.filter(x=>x.id!==id)); }

    return (



    <input value={text} onChange={e=>setText(e.target.value)} placeholder="Add a habit"/>



    {habits.length===0 ?

    No habits yet.

    : habits.map(h=> <HabitItem key={h.id} habit={h} onToggle={()=>toggle(h.id)} onRemove={()=>remove(h.id)}/>)}


    );
    }

    
    

    // src/components/HabitItem.tsx
    import React from "react";

    export default function HabitItem({habit,onToggle,onRemove}:{habit:any,onToggle:()=>void,onRemove:()=>void}){
    return (
    <div className={"habit "+(habit.done?"done":"")}>



);
}


// src/styles.css
body{font-family:system-ui;padding:16px}
.app{max-width:640px;margin:0 auto}
.input-row{display:flex;gap:8px;margin-bottom:12px}
.habit{display:flex;justify-content:space-between;align-items:center;padding:8px;border:1px solid #eee;border-radius:6px;margin-bottom:6px}
.habit.done span{text-decoration:line-through;color:#888}

  </li>

  <li>
    <b>Prompt 2 — Add tests for persistence and small polish (edit files)</b>

    <p><b>Goal:</b> Ensure localStorage saving is correct and add sample seed data for first-run.</p>

    <p><b>Files to modify:</b> src/pages/HabitsPage.tsx</p>

    <p><b>Acceptance criteria (done when):</b> On first Preview run you see two sample habits; adding/toggling persists.</p>

    <p><b>Prompt to paste:</b></p>

    ```
// Edit src/pages/HabitsPage.tsx near useEffect initial load to seed sample data if empty
// Replace the first useEffect with:
useEffect(()=>{
  const raw = localStorage.getItem(STORAGE_KEY);
  if(raw){ setHabits(JSON.parse(raw)); return; }
  // seed on first run
  const seed = [
    {id:Date.now().toString(), title: "Wake up by 7am", done:false},
    {id:(Date.now()+1).toString(), title: "Drink water", done:false}
  ];
  setHabits(seed);
},[]);
  • Prompt 3 — Optional: Supabase backend (external Supabase setup + Lovable Secrets)
    <p><b>Goal:</b> Swap localStorage for Supabase CRUD. This requires creating a Supabase project and a table "habits" with columns (id text PK, title text, done boolean).</p>
    
    <p><b>Files to create/modify:</b> create src/lib/supabase.ts and modify src/pages/HabitsPage.tsx to call Supabase.</p>
    
    <p><b>Secrets/Integration steps:</b></p>
    
    <ul>
      <li>In Supabase console (outside Lovable) create a project and run table creation SQL or use GUI to create table "habits" with columns: id TEXT primary key, title TEXT, done BOOLEAN, inserted\_at TIMESTAMPTZ default now()</li>
      <li>In Lovable Cloud, open <b>Secrets</b> UI and add keys: SUPABASE_URL and SUPABASE_ANON\_KEY with values from your Supabase project.</li>
    </ul>
    
    <p><b>Acceptance criteria (done when):</b> After adding Secrets, Preview loads habits from Supabase and changes persist to Supabase.</p>
    
    <p><b>Prompt to paste:</b></p>
    
    \`\`\`
    

    // src/lib/supabase.ts
    import { createClient } from "@supabase/supabase-js";

    // Lovable Secrets will inject values via process.env at runtime
    const SUPABASE_URL = process.env.SUPABASE_URL!;
    const SUPABASE_ANON_KEY = process.env.SUPABASE_ANON_KEY!;

    export const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);

    
    

    // Modify src/pages/HabitsPage.tsx to use supabase when process.env.SUPABASE_URL exists
    // Pseudocode insertion points:
    // // If SUPABASE_URL present, use Supabase queries for load/add/toggle/remove
    // // Use supabase.from('habits').select('*') etc.
    // // Keep localStorage fallback when secrets not set.
    ```

    <p><b>Note:</b> Creating the Supabase table is outside Lovable (use Supabase UI). No CLI required.</p>
    
  •  

    How to verify in Lovable Preview

     

    • Open Preview: Click Preview in Lovable. The dev server runs and shows the app at the preview URL.
    • Verify local app: Add a habit, toggle it, refresh Preview — it should persist (localStorage) or reflect Supabase data if secrets are set.
    • Errors: Use the Preview console logs panel to inspect runtime errors; edit files in Chat Mode to fix and Preview auto-reloads.

     

    How to Publish / re-publish

     

    • Use Lovable Publish: Click Publish in Lovable to deploy the app. If using Supabase, ensure Secrets are set in the Lovable Cloud Secrets UI before publishing.
    • GitHub export (outside Lovable): If you need CI, custom build steps, or server functions, export/sync to GitHub from Lovable and run builds locally/CI (this is outside Lovable and requires a terminal/CI).

     

    Common pitfalls in Lovable (and how to avoid them)

     

    • Missing Secrets: If Supabase keys are not set in Lovable Secrets, the app should fall back to localStorage — confirm your code checks process.env.SUPABASE\_URL before calling Supabase.
    • No terminal: Don’t expect to run migrations or CLI tools inside Lovable. Create DB schema in Supabase UI externally; document that step in the prompt.
    • Preview caching: Preview hot-reloads, but sometimes browser storage differs between preview sessions — test full refresh and check Preview console.
    • Dependencies: If Lovable project already has package.json tooling, merge rather than overwrite. Use Chat Mode to inspect existing files before creating new ones.

     

    Validity bar

     

    • This guide uses only Lovable-native features: Chat Mode edits, Preview, Publish, Secrets UI, and GitHub export for outside tasks. It does not invent any Lovable UI or CLI features.

    Want to explore opportunities to work with us?

    Connect with our team to unlock the full potential of no-code solutions with a no-commitment consultation!

    Book a Free Consultation

    How to add an idempotent habit completion endpoint

    This prompt helps an AI assistant understand your setup and guide to build the feature

    AI AI Prompt

    How to recalculate habit streaks on the server

    This prompt helps an AI assistant understand your setup and guide to build the feature

    AI AI Prompt

    How to add audit logging and a secure admin audit-logs API

    This prompt helps an AI assistant understand your setup and guide to build the feature

    AI AI Prompt

    Want to explore opportunities to work with us?

    Connect with our team to unlock the full potential of no-code solutions with a no-commitment consultation!

    Book a Free Consultation
    Matt Graham, CEO of Rapid Developers

    Book a call with an Expert

    Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.

    Book a free No-Code consultation

    Best Practices for Building a Habit tracker with AI Code Generators

    Build a simple, reliable habit tracker by using AI code generation for UI scaffolding and repetitive backend code, but keep core app logic, data model, secrets, and integrations under explicit control. In Lovable, iterate in Chat Mode, store runtime secrets with the Secrets UI, use Preview to test, and export/sync to GitHub only when you need terminal-level control. Prioritize a small, clear data model, secure server-side writes, idempotent APIs (to avoid duplicate completions), and good UX around missed / late completions.

     

    Planning the data model

     

    Start small and explicit. Keep habits and entries separate so AI can scaffold UI without guessing business rules.

    • Minimal tables: habits (id, user_id, name, cadence, created_at), habit_entries (id, habit_id, user_id, completed_at)
    • Keep rules simple: enforce uniqueness or idempotency at insert time (e.g., one entry per day per habit) so the AI-generated client can't cause duplicates.

     

    AI code generators: what to let them do

     

    Use AI to generate components, routes, and tests, but review and lock the business logic.

    • Good tasks for AI: form components, list views, date pickers, unit tests, API scaffolding.
    • Don't auto-accept: authentication flows, permission checks, and DB migrations without inspection.

     

    Integrations in Lovable (Supabase example)

     

    Configure Supabase via Lovable Secrets, call it from server-side routes, never expose service-role keys to client.

    • Secrets: add SUPABASE_URL and SUPABASE_ANON\_KEY (or a server key stored only in Secrets UI).
    • Preview: use Lovable Preview to exercise server routes that use those secrets.

     

    // server/api/addEntry.js
    
    import { createClient } from '@supabase/supabase-js'
    
    // createClient reads secrets set in Lovable Cloud Secrets UI
    const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_KEY)
    
    export default async function handler(req, res) {
      // guard method and payload
      if (req.method !== 'POST') return res.status(405).end()
      const { user_id, habit_id, completed_at } = req.body
    
      // idempotent insert: ignore duplicates for same habit+day
      const { data, error } = await supabase
        .from('habit_entries')
        .upsert(
          { user_id, habit_id, completed_at },
          { onConflict: ['user_id', 'habit_id', 'completed_at::date'] }
        )
    
      if (error) return res.status(500).json({ error: error.message })
      res.json(data)
    }
    

     

    Lovable workflow specifics

     

    Because there's no terminal, use Lovable features to iterate safely.

    • Chat Mode edits: ask the assistant to modify components or tests; review diffs before accepting.
    • File diffs/patches: apply small focused patches so you can roll back easily.
    • Preview: run end-to-end flows (create habit, mark complete) with real secrets set in Secrets UI.
    • Publish / GitHub sync: export to GitHub when you need CI, migrations, or terminal-based tooling.

     

    Testing, edge cases, and production tips

     

    Test idempotency, timezones, duplicate clicks, and offline behavior.

    • Timezone handling: store timestamps in UTC and compute “day” server-side to avoid client errors.
    • Offline/duplicates: make API idempotent; guard with unique constraints.
    • Secrets & roles: never expose service-role keys to client; use server-only routes or RLS policies.

     

    When to export to GitHub / use terminal tooling

     

    Export when you need DB migrations, advanced CI, or to run local scripts. Before exporting, ensure Secrets are set in both Lovable and your CI.


    Recognized by the best

    Trusted by 600+ businesses globally

    From startups to enterprises and everything in between, see for yourself our incredible impact.

    RapidDev was an exceptional project management organization and the best development collaborators I've had the pleasure of working with.

    They do complex work on extremely fast timelines and effectively manage the testing and pre-launch process to deliver the best possible product. I'm extremely impressed with their execution ability.

    Arkady
    CPO, Praction
    Working with Matt was comparable to having another co-founder on the team, but without the commitment or cost.

    He has a strategic mindset and willing to change the scope of the project in real time based on the needs of the client. A true strategic thought partner!

    Donald Muir
    Co-Founder, Arc
    RapidDev are 10/10, excellent communicators - the best I've ever encountered in the tech dev space.

    They always go the extra mile, they genuinely care, they respond quickly, they're flexible, adaptable and their enthusiasm is amazing.

    Mat Westergreen-Thorne
    Co-CEO, Grantify
    RapidDev is an excellent developer for custom-code solutions.

    We’ve had great success since launching the platform in November 2023. In a few months, we’ve gained over 1,000 new active users. We’ve also secured several dozen bookings on the platform and seen about 70% new user month-over-month growth since the launch.

    Emmanuel Brown
    Co-Founder, Church Real Estate Marketplace
    Matt’s dedication to executing our vision and his commitment to the project deadline were impressive. 

    This was such a specific project, and Matt really delivered. We worked with a really fast turnaround, and he always delivered. The site was a perfect prop for us!

    Samantha Fekete
    Production Manager, Media Production Company
    The pSEO strategy executed by RapidDev is clearly driving meaningful results.

    Working with RapidDev has delivered measurable, year-over-year growth. Comparing the same period, clicks increased by 129%, impressions grew by 196%, and average position improved by 14.6%. Most importantly, qualified contact form submissions rose 350%, excluding spam.

    Appreciation as well to Matt Graham for championing the collaboration!

    Michael W. Hammond
    Principal Owner, OCD Tech

    We put the rapid in RapidDev

    Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We’ll discuss your project and provide a custom quote at no cost.