From Zero to Production-Ready: Building a Full-Stack App with React, Tailwind CSS, and Supabase
Introduction
This guide walks you through creating a basic full-stack application using React for the frontend, Tailwind CSS for styling, and Supabase as the backend. We'll cover setting up each technology and connecting them to build a simple to-do list app.
Setting Up the Project
First, initialize a React project using Create React App:
npx create-react-app todo-app
cd todo-app
Next, install Tailwind CSS:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
Configure tailwind.config.js
:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
Include Tailwind directives in src/index.css
:
@tailwind base;
@tailwind components;
@tailwind utilities;
Finally, install the Supabase client library:
npm install @supabase/supabase-js
Creating the Supabase Backend
- Create a new project on the Supabase website (supabase.com).
- Retrieve your Supabase URL and API key from the project settings.
- Create a table named
todos
with columns:id
(UUID, primary key),task
(text), andcompleted
(boolean, default false).
Connecting React to Supabase
Create a supabaseClient.js
file:
import { createClient } from '@supabase/supabase-js';
const supabaseUrl = process.env.REACT_APP_SUPABASE_URL;
const supabaseKey = process.env.REACT_APP_SUPABASE_ANON_KEY;
const supabase = createClient(supabaseUrl, supabaseKey);
export default supabase;
Remember to set your Supabase URL and API key in your .env
file (create one if it doesn't exist):
REACT_APP_SUPABASE_URL=YOUR_SUPABASE_URL
REACT_APP_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY
Building the React Components
Create a TodoList.js
component:
import React, { useState, useEffect } from 'react';
import supabase from './supabaseClient';
function TodoList() {
const [todos, setTodos] = useState([]);
const [newTask, setNewTask] = useState('');
useEffect(() => {
fetchTodos();
}, []);
const fetchTodos = async () => {
const { data, error } = await supabase
.from('todos')
.select('*')
.order('id', { ascending: false });
if (error) {
console.error('Error fetching todos:', error);
} else {
setTodos(data);
}
};
const addTodo = async () => {
if (newTask.trim() === '') return;
const { data, error } = await supabase
.from('todos')
.insert([{ task: newTask, completed: false }])
.select();
if (error) {
console.error('Error adding todo:', error);
} else {
setTodos([...todos, data[0]]);
setNewTask('');
}
};
const toggleComplete = async (id, completed) => {
const { error } = await supabase
.from('todos')
.update({ completed: !completed })
.eq('id', id)
if(error){
console.log("error updating todo", error);
} else {
fetchTodos();
}
}
return (
<div className="max-w-md mx-auto p-4">
<h1 className="text-2xl font-bold mb-4">My To-Do List</h1>
<div className="flex mb-4">
<input
type="text"
className="shadow appearance-none border rounded w-full py-2 px-3 mr-4 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
placeholder="Add New Task"
value={newTask}
onChange={(e) => setNewTask(e.target.value)}
/>
<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline" onClick={addTodo}>Add</button>
</div>
<ul>
{todos.map((todo) => (
<li key={todo.id} className="flex items-center justify-between py-2 border-b border-gray-200">
<span className={todo.completed ? 'line-through text-gray-500' : 'text-gray-800'}>{todo.task}</span>
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleComplete(todo.id, todo.completed)}
className="mr-2 leading-tight"
/>
</li>
))}
</ul>
</div>
);
}
export default TodoList;
Update App.js
to use the TodoList
component:
import React from 'react';
import TodoList from './TodoList';
function App() {
return (
<div className="App">
<TodoList />
</div>
);
}
export default App;
Running the Application
Start the React development server:
npm start
Visit http://localhost:3000
in your browser to see your to-do list application.
Conclusion
This guide provides a basic implementation of a full-stack application using React, Tailwind CSS, and Supabase. You can expand this further by adding features like user authentication, more complex data structures, and more sophisticated styling. Experiment and explore the capabilities of each technology to build even more powerful applications.