Skip to content

Design Studio & Library Flow

This page explains the design-related features: the CAD library and the general Library, including how files and AI-generated nameplates are stored and organized.

Note: A dedicated "Nameplate Studio" UI is not yet present under src/pages/design/ in this snapshot. Nameplate data is still modeled in Supabase and surfaced via the Library.


Screens

CAD File Library (/design/cad-library)

File: src/pages/design/CADFileLibrary.tsx

Current behavior:

  • Simple page shell using DashboardLayout.
  • Displays title "CAD File Library" and description about storing and organizing CAD files.
  • Does not yet render the full library UI; CAD files are managed via the more general Library feature described below.

Intended role:

  • Entry point focused specifically on CAD assets.
  • In a future iteration, this page might:
    • Pre-filter the Library for CAD file MIME types.
    • Offer CAD-specific metadata (e.g. millimeter dimensions, versions, compatible settings).

Library (/library)

File: src/pages/Library.tsx

The Library is a combined view for:

  • Uploaded files (images, PDFs, other assets) used across marketing, design, and operations.
  • AI-generated nameplates (from the Nameplate Studio) stored as nameplates rows.

Key responsibilities:

  • Show a folder sidebar for organizing assets by tenant.
  • Provide file upload and metadata management.
  • Surface both traditional files and nameplate assets in a single gallery.
  • Support search and tag-based filtering.

Key components:

  • FolderSidebar
    • Lists tenant-scoped folders from library_folders.
    • Supports create, rename, delete (only when empty), and moving files between folders.
  • FileUploader
    • Handles file selection and metadata entry (title, description, tags, folder).
    • Calls useLibrary().uploadFile().
  • LibraryGallery
    • Displays LibraryItem[] (both file and nameplate types).
    • Provides edit/delete/preview actions.
  • FilePreviewModal
    • Shows a larger preview of images and nameplates.
  • Edit dialog
    • Lets the user update title, description, tags, and folder association.

Library data & operations

useLibrary hook

File: src/hooks/useLibrary.ts

Exposes:

  • Folder operations:
    • fetchFolders() – list of library_folders for current tenant.
    • createFolder(input) – create folder (with created_by user).
    • updateFolder(input) – rename / change description.
    • deleteFolder(folderId) – delete folder only if empty.
  • Item operations:
    • fetchLibraryItems(folderId?) – fetch both nameplates and files, optionally filtered by folder.
    • uploadFile(input) – upload a file into the library storage bucket + insert library_files_new row.
    • updateFileMetadata(input) – update title, description, tags, or folder.
    • deleteFile(fileId) – delete file from storage + library_files_new.
    • searchLibrary(filters) – search across nameplates and files by query/tags/mime type.

The hook uses useAuth() to get tenantId and ensures all queries are scoped to the current tenant.


Supabase tables

Nameplates

Migration: 20250118000000_create_nameplates.sql

  • nameplates

    • Stores generated nameplate metadata and usage tracking.
    • Fields (subset):
    • id – primary key.
    • user_id – creator (FK to auth.users).
    • tenant_id – tenant/company (FK to companies).
    • name – display text on the nameplate.
    • metal_type – e.g. 14k gold, 18k gold, etc.
    • purity – optional text for karat/purity.
    • with_diamonds – boolean flag.
    • font – chosen font style.
    • image_url – Supabase Storage URL for rendered image.
    • storage_path – path in nameplates storage bucket.
    • prompt_used – prompt sent to AI provider (abstracted; not exposed in docs).
    • created_at, updated_at.
    • Indexed by user_id, tenant_id, and created_at.
    • Row-Level Security ensures users see only their own nameplates.
  • nameplate_usage

    • Tracks per-user monthly usage to enforce limits (e.g. 20 nameplates per user per month).
    • Fields: user_id, tenant_id, nameplate_id, usage_month, created_at.
    • Enforces a unique (user_id, usage_month) pair.

Nameplates are surfaced in the Library UI as LibraryItem of type "nameplate".

Library folders

Migration: 20250119000000_create_library_folders.sql

  • library_folders
    • Folder structure for library items.
    • Fields:
    • id – primary key.
    • tenant_id – owning company.
    • name – folder name (unique per tenant).
    • description – optional.
    • created_byauth.users.id of creator.
    • created_at, updated_at.
    • RLS ensures tenant scoping.
    • Additional migration (20250208000010_add_is_protected_to_library_folders.sql) adds flags for protected folders (e.g. system folders).

Library files

Migration: 20250119000001_create_library_files.sql

  • library_files_new
    • Metadata for uploaded library files.
    • Fields:
    • id – primary key.
    • tenant_id – owning company.
    • user_id – uploader.
    • folder_id – optional FK to library_folders.
    • title, description.
    • tagsTEXT[] array for filtering.
    • file_name, file_size, mime_type.
    • storage_path – path in library storage bucket.
    • image_url – public URL for display.
    • created_at, updated_at.
    • Multiple indexes for tenant, user, folder, created_at, and tags (GIN).
    • RLS ensured by dedicated policies.

Storage buckets

  • Nameplates bucket (from 20250118000001_create_nameplates_storage.sql):

    • Stores nameplate images under the nameplates bucket.
    • Policies allow authenticated users to read/write their own content.
  • Library bucket (from 20250119000004_create_library_storage.sql):

    • Stores library files under the library bucket.
    • Files are organized by tenant and optional folder.

Upload, limits, and plan integration

Uploading files

uploadFile(input: UploadFileInput) in useLibrary:

  1. Gets current user (supabase.auth.getUser()).
  2. Looks up the user’s tenant_id from user_profiles to match RLS expectations.
  3. Checks plan limits:
    • Counts existing library_files_new rows for the tenant.
    • Looks up latest subscriptions row for the tenant.
    • Uses getPlanLimits(plan_name, subscription) to enforce per-plan library limits.
  4. Generates a storage path:
    • {tenant_id}/{folder_id}/{filename} or {tenant_id}/{filename}.
  5. Uploads the file to library bucket.
  6. Gets public URL.
  7. Inserts a row into library_files_new with tenant/user/metadata.

If the DB insert fails, it attempts to delete the uploaded file to avoid orphaned storage.

Searching and browsing

fetchLibraryItems(folderId?):

  • Queries nameplates scoped by tenant and optional folder.
  • Queries library_files_new scoped by tenant and optional folder.
  • Normalizes both into LibraryItem objects and sorts by created_at descending.

searchLibrary(filters):

  • Filters nameplates by name and folder.
  • Filters library_files_new by:
    • title, description, file_name (ILIKE search).
    • tags (contains filter).
    • mime_type.
  • Combines and sorts results.

Flow diagram

flowchart LR
  U[User] --> LIB[/Library screen/]
  LIB --> HOOK[useLibrary]

  subgraph Supabase
    FOLD[(library_folders)]
    FILES[(library_files_new)]
    NP[(nameplates)]
    NPU[(nameplate_usage)]
    STOR[Storage: library & nameplates buckets]
  end

  HOOK --> FOLD
  HOOK --> FILES
  HOOK --> NP
  HOOK --> STOR

  click LIB "../architecture/frontend/" "Library & design UI"
  click HOOK "../architecture/frontend/" "useLibrary hook"
  click FILES "../architecture/supabase/" "Library files schema"
  click NP "../architecture/supabase/" "Nameplates schema"

Narrative:

  1. User opens /library or /design/cad-library (future).
  2. useLibrary loads folders and items for the tenant.
  3. User uploads files and generates nameplates (via separate flows).
  4. Files and nameplates are stored in Supabase Storage and tracked in library_files_new / nameplates tables.
  5. Users search, filter, and organize assets by folder and tags.