Skip to main content

Overview

Music Store uses Supabase as its backend-as-a-service platform, providing:
  • PostgreSQL database for product data
  • Real-time subscriptions (optional)
  • RESTful API auto-generated from database schema
  • Row Level Security (RLS) for data access control

Supabase Client Configuration

The application uses a centralized Supabase client located at backend/supabaseClient.js:
backend/supabaseClient.js
import { createClient } from "@supabase/supabase-js";

const supabaseUrl = import.meta.env.VITE_SUPABASE_URL; 
const supabaseKey = import.meta.env.VITE_SUPABASE_KEY; 
export const supabase = createClient(supabaseUrl, supabaseKey);
The client uses Vite’s import.meta.env to access environment variables prefixed with VITE_.

Setting Up Your Supabase Project

1

Create a Supabase Account

  1. Go to supabase.com
  2. Sign up for a free account
  3. Create a new project
  4. Choose a database password (save this securely)
  5. Select a region close to your users
2

Get Your API Credentials

After project creation, navigate to Settings > API:
  • Project URL - Your unique Supabase URL (e.g., https://xxxxx.supabase.co)
  • Project API Key (anon/public) - Safe to use in client-side code
Never commit your service_role key to version control. Only use the anon (public) key in your frontend.
Copy these values - you’ll need them for your .env.local file.
3

Create the Database Schema

Navigate to the SQL Editor in your Supabase dashboard and run:
CREATE TABLE productos (
  id BIGSERIAL PRIMARY KEY,
  nombre TEXT NOT NULL,
  descripcion TEXT,
  precio NUMERIC(10, 2) NOT NULL,
  categoria TEXT NOT NULL,
  imagen_url TEXT,
  marca TEXT,
  stock INTEGER DEFAULT 0,
  destacado BOOLEAN DEFAULT false,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
This creates the productos table with all necessary fields for the store.
4

Configure Row Level Security (Optional)

For read-only public access, enable RLS and add a policy:
-- Enable Row Level Security
ALTER TABLE productos ENABLE ROW LEVEL SECURITY;

-- Allow public read access
CREATE POLICY "Allow public read access"
  ON productos
  FOR SELECT
  TO anon
  USING (true);
RLS is optional for this application since products are publicly viewable. You can disable RLS for simpler development.
5

Add Sample Data

Insert some sample products to test your setup:
INSERT INTO productos (nombre, descripcion, precio, categoria, marca, stock, destacado)
VALUES 
  ('Fender Stratocaster', 'Classic electric guitar with versatile tone', 1299.99, 'Guitarras Electricas', 'Fender', 5, true),
  ('Gibson Les Paul', 'Legendary rock guitar with rich sustain', 2499.99, 'Guitarras Electricas', 'Gibson', 3, true),
  ('Yamaha P-125', 'Digital piano with weighted keys', 649.99, 'Pianos', 'Yamaha', 8, false),
  ('Pearl Export', '5-piece drum kit for beginners', 799.99, 'Baterias', 'Pearl', 2, false);
6

Configure Environment Variables

Add your Supabase credentials to .env.local:
.env.local
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_KEY=your-anon-public-key-here
See the Environment Variables guide for detailed setup.

Database Schema Reference

productos Table

ColumnTypeDescription
idBIGSERIALAuto-incrementing primary key
nombreTEXTProduct name (required)
descripcionTEXTProduct description
precioNUMERIC(10,2)Price in currency units (required)
categoriaTEXTProduct category (e.g., “Guitarras Electricas”)
imagen_urlTEXTURL or path to product image
marcaTEXTBrand name (e.g., “Fender”, “Gibson”)
stockINTEGERAvailable inventory count
destacadoBOOLEANWhether product is featured
created_atTIMESTAMPRecord creation timestamp

Using Supabase in Components

Import the client and query data:
import { supabase } from "../backend/supabaseClient.js";
import { useEffect, useState } from "react";

function ProductList() {
  const [productos, setProductos] = useState([]);

  useEffect(() => {
    async function fetchProductos() {
      const { data, error } = await supabase
        .from("productos")
        .select("*")
        .order('created_at', { ascending: false });
      
      if (error) {
        console.error("Error fetching products:", error);
      } else {
        setProductos(data);
      }
    }
    fetchProductos();
  }, []);

  return (
    <div>
      {productos.map(p => (
        <div key={p.id}>{p.nombre} - ${p.precio}</div>
      ))}
    </div>
  );
}

Common Queries

const { data, error } = await supabase
  .from("productos")
  .select("*");
const { data, error } = await supabase
  .from("productos")
  .select("*")
  .eq('categoria', 'Guitarras Electricas');
const { data, error } = await supabase
  .from("productos")
  .select("*")
  .eq('id', productId)
  .single();
const { data, error } = await supabase
  .from("productos")
  .select("*")
  .ilike('nombre', `%${searchTerm}%`);

Troubleshooting

  • Verify your VITE_SUPABASE_KEY in .env.local matches the dashboard
  • Make sure you’re using the anon (public) key, not the service_role key
  • Restart the dev server after changing environment variables
  • Run the CREATE TABLE SQL in the Supabase SQL Editor
  • Verify the table name is exactly productos (lowercase)
  • Check that you’re connected to the correct Supabase project
  • Check Row Level Security policies if enabled
  • Verify data exists: run SELECT * FROM productos in SQL Editor
  • Check browser console for error messages
  • Ensure file is named exactly .env.local (not .env)
  • Variables must start with VITE_ prefix
  • Restart the Vite dev server with npm run dev
Always use the anon (public) API key in your frontend code. The service_role key bypasses all security rules and should only be used in secure backend environments.

Next Steps

Environment Variables

Learn how to configure your .env.local file

Project Structure

Understand how Supabase integrates with the app

Supabase Docs

Official Supabase documentation

Supabase JS Client

JavaScript client library reference

Build docs developers (and LLMs) love