Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/bicyblex/bicyblexStore/llms.txt

Use this file to discover all available pages before exploring further.

Bicyblex Store relies entirely on Supabase for its database, file storage, and user authentication. Every admin action — publishing products, managing categories, uploading images, and writing news articles — flows through a single Supabase project. This guide walks through setting up all required resources in a new or existing Supabase project so the application is fully operational from day one.
1
Create a Supabase project
2
Go to supabase.com, sign in, and click New project. Choose an organisation, give the project a name (e.g. bicyblex-store), set a strong database password, and select the region closest to your users.
3
Once the project finishes provisioning, open Project Settings → API and note down two values — you will need them in the next step:
4
  • Project URLNEXT_PUBLIC_SUPABASE_URL
  • anon public keyNEXT_PUBLIC_SUPABASE_ANON_KEY
  • 5
    Add both to your .env.local file as described in Environment Variables.
    6
    Create the categories table
    7
    The categories table is the foundation of the product catalogue. Every product references a category via a foreign key, and the category’s slug drives the dynamic specification fields rendered in the product form.
    8
    Open the SQL Editor in your Supabase dashboard and run:
    9
    CREATE TABLE categories (
      id   SERIAL PRIMARY KEY,
      name TEXT NOT NULL,
      slug TEXT NOT NULL UNIQUE
    );
    
    10
    The application expects four specific category slugs — bicicletas, bicimotos-electricas, kits-electricos, and accesorios — because ProductForm.jsx maps each slug to a set of dynamic technical-spec fields via its CONFIG object:
    11
    SlugSpec fields renderedbicicletasaro, material, frenobicimotos-electricasautonomia, potencia, velocidadkits-electricosdescripcionaccesoriosDato 1, Dato 2, Dato 3
    12
    Seed the initial categories with the following INSERT:
    13
    INSERT INTO categories (name, slug) VALUES
      ('Bicicletas', 'bicicletas'),
      ('Bicimotos Eléctricas', 'bicimotos-electricas'),
      ('Kits Eléctricos', 'kits-electricos'),
      ('Accesorios', 'accesorios');
    
    14
    You can add extra categories through the dashboard’s category manager, which auto-generates slugs from the category name. Only the four slugs above trigger predefined spec field sets in the product form — new slugs will produce no spec fields until the CONFIG object in ProductForm.jsx is updated.
    15
    Create the products table
    16
    The products table stores the full inventory. It references categories via a foreign key and uses a JSONB column for flexible, per-category technical specifications.
    17
    CREATE TABLE products (
      id          SERIAL PRIMARY KEY,
      name        TEXT NOT NULL,
      price       NUMERIC(10, 2) NOT NULL DEFAULT 0,
      stock       INTEGER NOT NULL DEFAULT 0,
      category_id INTEGER REFERENCES categories(id),
      specs       JSONB DEFAULT '{}',
      image       TEXT,
      tag         TEXT DEFAULT 'general'
    );
    
    18
    Column notes:
    19
  • price — stored as NUMERIC(10, 2); the application reads and writes it as a JavaScript float via parseFloat().
  • stock — read and written as an integer via parseInt().
  • category_id — foreign key to categories.id; the product manager queries it with .select("*, categories(name)") to join the category name in a single round-trip.
  • specs — a JSONB object whose keys vary by category (e.g. { "aro": "29\"", "material": "Aluminio", "freno": "Disco" } for bicicletas).
  • image — stores the full public URL of the image uploaded to the products storage bucket.
  • tag — a free-text label; defaults to 'general'.
  • 20
    Create the news table
    21
    The news table backs the newsletter / blog section managed from the /dashboard/newsletter panel. Slugs and excerpts are auto-generated by the application at save time.
    22
    CREATE TABLE news (
      id         SERIAL PRIMARY KEY,
      title      TEXT NOT NULL,
      content    TEXT NOT NULL,
      image      TEXT,
      slug       TEXT NOT NULL UNIQUE,
      excerpt    TEXT,
      created_at TIMESTAMPTZ DEFAULT NOW()
    );
    
    23
    The slug is derived from the article title by lower-casing, stripping accents, and replacing spaces with hyphens. The excerpt is the first 150 characters of content, both computed client-side before the INSERT.
    24
    Create Storage buckets
    25
    Bicyblex Store uses two Supabase Storage buckets — one for product images and one for news cover images. In your Supabase dashboard, go to Storage and create each bucket:
    26

    products bucket

    Bucket name: productsSet the bucket to Public so that the CDN URLs returned by getPublicUrl() are accessible to all storefront visitors without authentication.Product images are converted to WebP format client-side before upload and stored with a timestamp-randomised filename.

    news bucket

    Bucket name: newsSet the bucket to Public for the same reason — news cover images are displayed on the public-facing storefront.Files are stored inside a news/ prefix path within the bucket (e.g. news/1720000000000-abc123.jpg).
    27
    For each bucket, after creation go to Storage → Policies and verify that the anon role has at minimum SELECT access so that public image URLs resolve correctly. For admin upload/delete operations, ensure the authenticated role has INSERT, UPDATE, and DELETE permissions, or disable bucket-level RLS entirely for a simple setup (see Step 7).
    28
    Create an auth user
    29
    The /dashboard route is protected by Supabase Auth. The application calls supabase.auth.getSession() on load to verify the session and supabase.auth.signOut() on logout. You must create at least one admin user manually:
    30
  • In your Supabase dashboard, go to Authentication → Users.
  • Click Add user → Create new user.
  • Enter the admin email address and a strong password.
  • Click Create user.
  • 31
    Use these credentials to sign in to the /dashboard page of your deployed or local Bicyblex Store instance. No further role configuration is required — any authenticated Supabase user has access to the admin dashboard.
    32
    Configure Row Level Security (RLS)
    33
    Supabase enables Row Level Security (RLS) by default on all new tables. With RLS active and no policies defined, all reads and writes from the client will be silently blocked, causing the dashboard to display empty tables and all save operations to fail without an obvious error. You must either define appropriate policies or disable RLS before the application will function correctly.
    34
    For a simple admin-only deployment where the anon key is only used by trusted operators, you can disable RLS on all three tables:
    35
    ALTER TABLE categories DISABLE ROW LEVEL SECURITY;
    ALTER TABLE products   DISABLE ROW LEVEL SECURITY;
    ALTER TABLE news       DISABLE ROW LEVEL SECURITY;
    
    36
    For a production deployment with public storefront access, consider keeping RLS enabled and adding a permissive SELECT policy for the anon role on products, categories, and news, while restricting INSERT, UPDATE, and DELETE to the authenticated role:
    37
    -- Allow public read access
    CREATE POLICY "Public read" ON products FOR SELECT USING (true);
    CREATE POLICY "Public read" ON categories FOR SELECT USING (true);
    CREATE POLICY "Public read" ON news FOR SELECT USING (true);
    
    -- Allow authenticated users full write access
    CREATE POLICY "Auth write" ON products FOR ALL TO authenticated USING (true);
    CREATE POLICY "Auth write" ON categories FOR ALL TO authenticated USING (true);
    CREATE POLICY "Auth write" ON news FOR ALL TO authenticated USING (true);
    

    Storage bucket policies

    When a bucket is set to public in Supabase, its files are accessible via their public URL with no authentication required — this is the correct setting for Bicyblex Store since product and news images are displayed on the public storefront. For upload and delete operations (triggered from the admin dashboard), Supabase Storage uses the same RLS policy model as the database. Ensure the authenticated role has the following permissions on both the products and news buckets:
    OperationRoleRequired
    SELECTanonYes — for public image URL resolution
    INSERTauthenticatedYes — for uploading new images
    UPDATEauthenticatedYes — for replacing existing images
    DELETEauthenticatedYes — for removing old images
    You can configure these policies under Storage → Policies in the Supabase dashboard, or by running INSERT INTO storage.policies statements via the SQL editor.
    Once all resources are created, return to Environment Variables to add your Project URL and anon key to .env.local, then start the dev server with npm run dev.

    Build docs developers (and LLMs) love