Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ProyectoFerretek/FerreMarket/llms.txt

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

FerreMarket delegates all authentication to Supabase Auth, including session management, credential validation, and password recovery. The React side of this integration lives in src/context/AuthContext.tsx, which provides an AuthContextProvider component and a UserAuth hook that together expose every auth method to the rest of the application. Rather than scattering raw supabase.auth.* calls throughout the codebase, every component that needs to sign a user in, out, or perform account operations should use the methods surfaced by UserAuth().

AuthContext Provider

AuthContextProvider is declared in src/context/AuthContext.tsx and wraps the entire application in src/App.tsx. It owns the session state and keeps it synchronised with the Supabase Auth lifecycle via the onAuthStateChange listener.
// src/App.tsx (simplified)
function App() {
  return (
    <BrowserRouter>
      <AuthContextProvider>
        <Routes>
          <Route path="/" element={<Landing />} />
          <Route path="/admin/login" element={<Login />} />
          <Route path="/admin" element={<ProtectedRoute><Layout /></ProtectedRoute>}>
            {/* ...protected routes */}
          </Route>
        </Routes>
      </AuthContextProvider>
    </BrowserRouter>
  );
}
On mount, AuthContextProvider calls supabase.auth.getSession() to restore any existing session from local storage, then registers supabase.auth.onAuthStateChange to react to subsequent sign-in, sign-out, and token-refresh events:
useEffect(() => {
  supabase.auth.getSession().then(({ data: { session } }) => {
    setSession(session);
  });

  supabase.auth.onAuthStateChange((_event, session) => {
    setSession(session);
  });
}, []);
Because session starts as undefined (not yet resolved) rather than null (confirmed signed-out), consumer components can distinguish the loading state from a confirmed logged-out state — see Session State below.

Available Auth Methods

All methods are returned by the UserAuth() hook and can be destructured directly in any component inside AuthContextProvider.

signInUser(email, password)

signInUser(email: string, password: any): Promise<{ success: boolean; data?: any; error?: any }>
Calls supabase.auth.signInWithPassword with the provided credentials. The email is lowercased before the request is sent to ensure case-insensitive matching.
  • On success — returns { success: true, data } where data contains the Supabase Session and User objects.
  • On failure — displays a toast notification (“Error al iniciar sesión. Por favor, verifica tus credenciales.”) and returns { success: false, error }.
const { signInUser } = UserAuth();

const result = await signInUser('admin@ferremarkt.com', 'secret');
if (!result.success) {
  console.error('Login failed:', result.error);
}

signUpNewUser(email, password)

signUpNewUser(email: string, password: any): Promise<{ success: boolean; data?: any; error?: any }>
Provisions a new Supabase Auth user by invoking the create-user Edge Function rather than calling supabase.auth.signUp directly. This server-side approach allows the function to run with admin privileges, bypassing email confirmation requirements and enabling the user to be created without the caller needing elevated permissions on the client.
  • On success — returns { success: true, data }. The data.user.id field contains the new user’s Supabase Auth UUID, which must be stored as uid in the usuarios table.
  • On failure — returns { success: false, error }.
signUpNewUser calls the create-user Supabase Edge Function. This function must be deployed to your Supabase project before new users can be created from the FerreMarket UI. Attempting to call this method without the function deployed will result in a network error and the user will not be created. See the Supabase Edge Functions documentation for deployment instructions.

signOut()

signOut(): Promise<void | { success: boolean; error?: any }>
Calls supabase.auth.signOut(), which invalidates the current session token and clears the local session from storage. After sign-out, session is set to null by the onAuthStateChange listener, causing ProtectedRoute to redirect the user to /admin/login. On error, returns { success: false, error } instead of resolving silently.
const { signOut } = UserAuth();

const handleLogout = async () => {
  await signOut();
  // User is automatically redirected to /admin/login by ProtectedRoute
};

deleteUser(uid)

deleteUser(uid: string): Promise<{ success: boolean; error?: any }>
Permanently removes a Supabase Auth user by invoking the delete-user Edge Function with an HTTP DELETE method. The uid parameter must be the Supabase Auth UUID (Usuario.uid), not the internal database ID.
  • On success — returns { success: true }.
  • On failure — logs the error and returns { success: false, error }.
The Edge Function receives the following request body:
{
  "userId": "<supabase-auth-uuid>"
}
After calling deleteUser, you must also call the database-level eliminarUsuario(id) to remove the corresponding row from the usuarios table. deleteUser only removes the Supabase Auth entry — the database record is a separate operation.

recoverPassword(email)

recoverPassword(email: string): Promise<{ success: boolean; error?: any }>
Sends a password-reset email by invoking the send-password-recovery-email Edge Function. The email is lowercased before dispatch.
  • On success — returns { success: true }. The user receives an email with a temporary password-reset link.
  • On failure — returns { success: false, error }.

session

The current Supabase Session object (or a sentinel value indicating the loading/logged-out state). Exposed directly from context so any component can read the authentication state without calling a function.

Using the UserAuth Hook

Import and destructure UserAuth() inside any component that is a descendant of AuthContextProvider:
import { UserAuth } from '../context/AuthContext';

const MyComponent = () => {
  const { session, signInUser, signOut } = UserAuth();

  const handleLogin = async () => {
    const result = await signInUser('user@example.com', 'password123');
    if (!result.success) {
      console.error('Login failed:', result.error);
    }
  };

  if (session === undefined) {
    return <p>Loading...</p>;
  }

  if (session === null) {
    return <button onClick={handleLogin}>Sign In</button>;
  }

  return (
    <div>
      <p>Logged in as {session.user.email}</p>
      <button onClick={signOut}>Sign Out</button>
    </div>
  );
};

Session State

The session value follows a three-state lifecycle that maps directly to the application’s auth flow:
ValueTypeMeaning
undefinedundefinedLoadinggetSession() has not yet resolved. Render a spinner or skeleton.
nullnullLogged out — The session resolved with no active user. Redirect to /admin/login.
Session objectSessionAuthenticated — A valid Supabase session exists. session.user contains the Auth user data.
ProtectedRoute relies on this three-state contract to avoid briefly flashing the login redirect during the initial load:
const ProtectedRoute = ({ children }) => {
  const { session } = UserAuth();

  if (session) {
    // undefined is falsy — this only renders children when session is a real Session object
    return <>{children}</>;
  } else {
    return <Navigate to="/admin/login" replace />;
  }
};
Both undefined (loading) and null (logged out) are falsy, so ProtectedRoute will redirect to /admin/login during the brief loading window before getSession() resolves. If you need to show a loading state instead of an immediate redirect, check session === undefined explicitly before returning <Navigate />.

Supabase Client Initialisation

The Supabase client is created once in src/lib/supabase/Supabase.tsx and imported wherever direct Supabase access is needed:
import { createClient } from '@supabase/supabase-js';

const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
const supabaseKey = import.meta.env.VITE_SUPABASE_ANON_KEY;
const supabase = createClient(supabaseUrl, supabaseKey);

export default supabase;
Both environment variables must be present in your .env file (or Vite environment configuration) before starting the development server or building for production:
VITE_SUPABASE_URL=https://<your-project-ref>.supabase.co
VITE_SUPABASE_ANON_KEY=<your-anon-key>

Supabase Edge Functions

User creation, deletion, and password recovery all route through Supabase Edge Functions rather than the client SDK directly. This design allows the functions to execute with service-role privileges on the server — operations that would otherwise require the secret service_role key, which must never be exposed to the browser. The three Edge Functions used by FerreMarket are:
Function NameTriggered ByDescription
create-usersignUpNewUser()Creates a new Supabase Auth user with admin privileges. Accepts { email, password }.
delete-userdeleteUser()Permanently removes a Supabase Auth user. Accepts { userId } via HTTP DELETE.
send-password-recovery-emailrecoverPassword()Sends a password-reset email to the specified address. Accepts { email }.
These functions must be deployed to your Supabase project before the corresponding UI actions will work.
For step-by-step instructions on writing, testing locally with the Supabase CLI, and deploying Edge Functions to your project, see the official Supabase Edge Functions documentation.

Build docs developers (and LLMs) love