Learn how to build a habit tracker with Lovable in our step-by-step guide. Boost productivity and develop healthier daily routines with ease.
Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
Creating a New Lovable Habit Tracker Project
index.html
– This will serve as the main user interface.app.js
– This file contains the logic for tracking habits.style.css
– This file will contain style rules to make the habit tracker visually appealing.
Building the User Interface (index.html)
index.html
file in Lovable’s editor and insert the following HTML snippet. This code sets up a simple structure for the habit tracker with an input to add new habits and a list container to display them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Habit Tracker</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<h1>My Habit Tracker</h1>
<input type="text" id="habitInput" placeholder="Enter a new habit">
<button id="addHabitBtn">Add Habit</button>
<ul id="habitList">
<!-- Habit items will appear here -->
</ul>
</div>
<script src="app.js"></script>
</body>
</html>
Implementing Habit Tracker Logic (app.js)
app.js
file in Lovable’s editor and paste the following JavaScript code. This code makes the habit tracker interactive by enabling adding new habits and toggling them as complete or incomplete.
document.addEventListener('DOMContentLoaded', function() {
const habitInput = document.getElementById('habitInput');
const addHabitBtn = document.getElementById('addHabitBtn');
const habitList = document.getElementById('habitList');
// Function to create a new habit list item.
function addHabit() {
const habitText = habitInput.value.trim();
if (habitText === '') {
alert('Please enter a habit!');
return;
}
const listItem = document.createElement('li');
listItem.textContent = habitText;
listItem.addEventListener('click', function() {
listItem.classList.toggle('completed');
});
habitList.appendChild(listItem);
habitInput.value = '';
}
addHabitBtn.addEventListener('click', addHabit);
// Optional: Allow pressing Enter to add a habit.
habitInput.addEventListener('keypress', function(event) {
if (event.key === 'Enter') {
addHabit();
}
});
});
Styling the Habit Tracker (style.css)
style.css
file in Lovable’s editor and add the following CSS. This makes the user interface clean and highlights completed habits.
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 0;
}
.container {
width: 90%;
max-width: 600px;
margin: 50px auto;
background: #fff;
padding: 20px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
text-align: center;
}
input[type="text"] {
width: 70%;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
button {
padding: 10px 15px;
margin-left: 10px;
border: none;
background: #28a745;
color: #fff;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background: #218838;
}
ul {
list-style-type: none;
padding: 0;
margin-top: 20px;
}
li {
padding: 10px;
border-bottom: 1px solid #ccc;
cursor: pointer;
}
li.completed {
text-decoration: line-through;
color: #777;
}
Integrating External Dependencies (Optional)
index.html
file. For instance, to include Moment.js, add the following snippet inside the <head> section:
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
Testing Your Habit Tracker
index.html
page.
Deploying and Sharing Your Habit Tracker
index.html
, app.js
, style.css
) are loading correctly.
const express = require('express');
const mongoose = require('mongoose');
const app = express();
app.use(express.json());
mongoose.connect('mongodb://localhost:27017/habittracker', {
useNewUrlParser: true,
useUnifiedTopology: true
});
const habitSchema = new mongoose.Schema({
name: { type: String, required: true },
frequency: { type: Number, default: 1 },
events: [{
date: { type: Date, default: Date.now },
completed: { type: Boolean, default: false }
}]
});
const Habit = mongoose.model('Habit', habitSchema);
app.post('/api/habit', async (req, res) => {
try {
const { name, frequency } = req.body;
const habit = new Habit({ name, frequency });
await habit.save();
res.status(201).json(habit);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.get('/api/habit/:id', async (req, res) => {
try {
const habit = await Habit.findById(req.params.id);
if (!habit) return res.status(404).json({ error: 'Habit not found' });
res.json(habit);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.post('/api/habit/:id/complete', async (req, res) => {
try {
const habit = await Habit.findById(req.params.id);
if (!habit) return res.status(404).json({ error: 'Habit not found' });
habit.events.push({ date: new Date(), completed: true });
await habit.save();
res.json(habit);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Server running on port ${port}`));
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Habit Tracker - Lovable Integration</title>
</head>
<body>
<h1>Habit Tracker: Complete Habit</h1>
<button id="completeHabit" data-habit-id="habit-456">Complete Habit</button>
<!-- This hidden form mimics a backend API endpoint call for habit completion -->
<script>
document.getElementById('completeHabit').addEventListener('click', async function () {
const habitId = this.getAttribute('data-habit-id');
// First: Notify your own backend about habit completion
try {
const backendResponse = await fetch('https://your-backend.example.com/api/habits/' + habitId + '/complete', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ completedAt: new Date().toISOString() })
});
if (!backendResponse.ok) {
throw new Error('Failed to update your backend');
}
// Second: Connect to the external Lovable API to send a celebratory notification
const lovableResponse = await fetch('https://api.lovable.com/v1/notify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_LOVABLE_API\_TOKEN'
},
body: JSON.stringify({
habitId: habitId,
message: 'Yay! You completed your habit today!',
timestamp: new Date().toISOString()
})
});
if (!lovableResponse.ok) {
throw new Error('Failed to send notification to Lovable');
}
const notificationResult = await lovableResponse.json();
console.log('Notification sent successfully:', notificationResult);
alert('Habit completed and notification sent!');
} catch (error) {
console.error(error);
alert('Error processing habit completion.');
}
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Habit Tracker - Daily Sync and Reward</title>
</head>
<body>
<h1>Daily Habit Sync</h1>
<button id="syncHabits">Sync and Reward Habits</button>
<div id="status"></div>
<script>
document.getElementById('syncHabits').addEventListener('click', async () => {
const statusDiv = document.getElementById('status');
statusDiv.innerHTML = 'Fetching today's habits...';
try {
// Fetch today's habits from your backend
const habitsRes = await fetch('https://your-backend.example.com/api/habits/today', {
method: 'GET',
headers: { 'Content-Type': 'application/json' }
});
if (!habitsRes.ok) throw new Error('Unable to fetch habits');
const habits = await habitsRes.json();
// Filter the habits that are completed but not yet rewarded
const completedHabits = habits.filter(habit => habit.completed && !habit.rewarded);
if (completedHabits.length === 0) {
statusDiv.innerHTML = 'No new completed habits to reward today.';
return;
}
// Process reward for every completed habit
for (const habit of completedHabits) {
// Send reward details to Lovable API to award points
const rewardRes = await fetch('https://api.lovable.com/v1/rewards', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_LOVABLE_API\_TOKEN'
},
body: JSON.stringify({
habitId: habit.id,
userId: habit.userId,
points: 10,
message: 'Great job on completing your habit today!'
})
});
if (!rewardRes.ok) {
statusDiv.innerHTML += `<p>Failed to reward habit: ${habit.name}</p>`;
continue;
}
// Update the backend to mark the habit as rewarded
await fetch(\`https://your-backend.example.com/api/habits/${habit.id}/reward\`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ rewarded: true })
});
statusDiv.innerHTML += `<p>Reward sent for habit: ${habit.name}</p>`;
}
} catch (error) {
statusDiv.innerHTML = \`<p>Error: ${error.message}</p>\`;
}
});
</script>
</body>
</html>
Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
Understanding the Habit Tracker & AI Code Generator Concept
Prerequisites
Project Setup
index.html
for the main user interface.app.js
for the application's logic.styles.css
for design and layout.
Using AI Code Generators in Your Project
index.html
file.app.js
file.
Setting Up a Basic Habit Tracker Interface
index.html
, start with a basic HTML skeleton:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css">
<title>Habit Tracker</title>
</head>
<body>
<h1>My Habit Tracker</h1>
<div id="habit-container">
<!-- Habits will be displayed here -->
</div>
<script src="app.js"></script>
</body>
</html>
styles.css
, add simple styling to enhance the look of the page.
body {
font-family: Arial, sans-serif;
margin: 20px;
}
#habit-container {
border: 1px solid #ccc;
padding: 10px;
border-radius: 5px;
}
Implementing Core Habit Tracker Functionality
app.js
file:
function addHabit(habit) {
let habits = JSON.parse(localStorage.getItem('habits')) || [];
habits.push(habit);
localStorage.setItem('habits', JSON.stringify(habits));
displayHabits();
}
function displayHabits() {
let habits = JSON.parse(localStorage.getItem('habits')) || [];
const container = document.getElementById('habit-container');
container.innerHTML = '';
habits.forEach(function(habit, index) {
const habitDiv = document.createElement('div');
habitDiv.textContent = habit;
container.appendChild(habitDiv);
});
}
Integrating AI-Generated Code Snippets Safely
Testing and Iteration
index.html
file in your browser to test the app.
Deployment and Best Practices
When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.