Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/dlampatricio/florale/llms.txt

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

Floralé’s data-fetching layer lives in lib/products.ts and exposes four async functions for reading products and categories from Supabase. All calls go directly to the Supabase REST API using the native fetch with cache: 'no-store' — the Supabase JS client is intentionally not used here — making these functions safe to call from any Next.js Server Component or Route Handler without accidental caching.
Both NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY must be present in your environment. If either variable is missing, every function returns a safe empty value ([] for list functions, undefined for getProductById) rather than throwing, so the UI degrades gracefully during misconfigured builds.

Environment variables

VariableDescription
NEXT_PUBLIC_SUPABASE_URLThe base URL of your Supabase project (e.g. https://xyz.supabase.co)
NEXT_PUBLIC_SUPABASE_ANON_KEYThe public anonymous key issued by Supabase
Both variables are forwarded by Next.js to the browser via the NEXT_PUBLIC_ prefix, but the fetching functions run exclusively on the server — no credentials are ever exposed to the client bundle through this module.

Internal: mapProduct

Before any data reaches your components, rows returned from the products table are normalised by an internal mapProduct helper. The database uses snake_case column names; the TypeScript types use camelCase. The only structural change is:
category_id  (DB column)  →  categoryId  (TypeScript field)
All other fields (id, name, description, price, image) are copied as-is. Fields that may be null in the database (description, image) are coerced to empty strings.

getProducts

Returns every product in the catalogue, ordered by creation date (oldest first).
export async function getProducts(): Promise<Product[]>

Parameters

This function takes no parameters.

Return type

Product[]
array
An array of Product objects ordered by created_at ASC. Returns an empty array if the environment variables are missing or if the request fails.
id
string
Unique product identifier (UUID).
name
string
Display name of the product.
description
string
Long-form product description. Empty string when not set.
price
number
Price in the store’s base currency unit (e.g. cents or dollars).
image
string
URL or path for the product’s primary image. Empty string when not set.
categoryId
string
ID of the category this product belongs to (mapped from category_id).

Usage

// app/shop/page.tsx
import { getProducts } from '@/lib/products';

export default async function ShopPage() {
  const products = await getProducts();

  return (
    <ul>
      {products.map((product) => (
        <li key={product.id}>{product.name} — ${product.price}</li>
      ))}
    </ul>
  );
}

getProductById

Fetches a single product by its UUID. Returns undefined when no matching record is found.
export async function getProductById(id: string): Promise<Product | undefined>

Parameters

id
string
required
The UUID of the product to retrieve. The value is URL-encoded before being appended to the REST filter query.

Return type

Product | undefined
object | undefined
A single Product object when found, or undefined when no product matches the given id or when the request fails.
id
string
Unique product identifier (UUID).
name
string
Display name of the product.
description
string
Long-form description. Empty string when not set.
price
number
Price in the store’s base currency unit.
image
string
URL or path for the primary image. Empty string when not set.
categoryId
string
Owning category ID (mapped from category_id).

Usage

// app/shop/[id]/page.tsx
import { getProductById } from '@/lib/products';
import { notFound } from 'next/navigation';

interface Props {
  params: { id: string };
}

export default async function ProductPage({ params }: Props) {
  const product = await getProductById(params.id);

  if (!product) {
    notFound();
  }

  return (
    <article>
      <h1>{product.name}</h1>
      <p>{product.description}</p>
      <strong>${product.price}</strong>
    </article>
  );
}

getProductsByCategory

Returns all products that belong to a specific category, ordered by creation date (oldest first). This is the preferred way to power category landing pages.
export async function getProductsByCategory(categoryId: string): Promise<Product[]>

Parameters

categoryId
string
required
The ID of the category to filter by. Mapped to the category_id column in the database via the eq. PostgREST filter. The value is URL-encoded.

Return type

Product[]
array
An array of Product objects filtered to the given category, ordered by created_at ASC. Returns an empty array if no products exist in the category, if the environment variables are missing, or if the request fails.

Usage

// app/categories/[categoryId]/page.tsx
import { getProductsByCategory } from '@/lib/products';

interface Props {
  params: { categoryId: string };
}

export default async function CategoryPage({ params }: Props) {
  const products = await getProductsByCategory(params.categoryId);

  if (products.length === 0) {
    return <p>No products in this category yet.</p>;
  }

  return (
    <ul>
      {products.map((product) => (
        <li key={product.id}>{product.name}</li>
      ))}
    </ul>
  );
}

getCategories

Fetches every category available in the store, ordered by id ASC.
export async function getCategories(): Promise<Category[]>

Parameters

This function takes no parameters.

Return type

Category[]
array
An array of Category objects ordered by id ASC. Returns an empty array if the environment variables are missing or if the request fails.
id
string
Unique category identifier.
name
string
Human-readable category name (e.g. “Dried Florals”).
description
string
A short description of the category’s contents.

Usage

// components/CategoryNav.tsx
import { getCategories } from '@/lib/products';
import Link from 'next/link';

export default async function CategoryNav() {
  const categories = await getCategories();

  return (
    <nav>
      {categories.map((cat) => (
        <Link key={cat.id} href={`/categories/${cat.id}`}>
          {cat.name}
        </Link>
      ))}
    </nav>
  );
}

Error handling and graceful degradation

All four functions share the same internal fetchFromSupabase helper, which applies a consistent error-handling strategy:
ConditiongetProducts / getProductsByCategory / getCategoriesgetProductById
NEXT_PUBLIC_SUPABASE_URL or NEXT_PUBLIC_SUPABASE_ANON_KEY not setReturns [] immediatelyReturns undefined immediately
Non-ok HTTP response from SupabaseReturns []Returns undefined
Network error or thrown exceptionReturns [] (caught internally)Returns undefined (caught internally)
Empty result setReturns [] normallyReturns undefined (no matching row)
Because these functions never throw, you can call them at the top level of a Server Component without wrapping them in try/catch. Guard against empty arrays in your UI instead — for example by rendering a fallback message when products.length === 0.

Build docs developers (and LLMs) love