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
Libraryfeature 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
nameplatesrows.
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.
- Lists tenant-scoped folders from
FileUploader- Handles file selection and metadata entry (title, description, tags, folder).
- Calls
useLibrary().uploadFile().
LibraryGallery- Displays
LibraryItem[](bothfileandnameplatetypes). - Provides edit/delete/preview actions.
- Displays
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 oflibrary_foldersfor current tenant.createFolder(input)– create folder (withcreated_byuser).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 thelibrarystorage bucket + insertlibrary_files_newrow.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 toauth.users).tenant_id– tenant/company (FK tocompanies).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 innameplatesstorage bucket.prompt_used– prompt sent to AI provider (abstracted; not exposed in docs).created_at,updated_at.- Indexed by
user_id,tenant_id, andcreated_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_by–auth.users.idof 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 tolibrary_folders.title,description.tags–TEXT[]array for filtering.file_name,file_size,mime_type.storage_path– path inlibrarystorage 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
nameplatesbucket. - Policies allow authenticated users to read/write their own content.
- Stores nameplate images under the
-
Library bucket (from
20250119000004_create_library_storage.sql):- Stores library files under the
librarybucket. - Files are organized by tenant and optional folder.
- Stores library files under the
Upload, limits, and plan integration¶
Uploading files¶
uploadFile(input: UploadFileInput) in useLibrary:
- Gets current user (
supabase.auth.getUser()). - Looks up the user’s
tenant_idfromuser_profilesto match RLS expectations. - Checks plan limits:
- Counts existing
library_files_newrows for the tenant. - Looks up latest
subscriptionsrow for the tenant. - Uses
getPlanLimits(plan_name, subscription)to enforce per-plan library limits.
- Counts existing
- Generates a storage path:
{tenant_id}/{folder_id}/{filename}or{tenant_id}/{filename}.
- Uploads the file to
librarybucket. - Gets public URL.
- Inserts a row into
library_files_newwith 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
nameplatesscoped by tenant and optional folder. - Queries
library_files_newscoped by tenant and optional folder. - Normalizes both into
LibraryItemobjects and sorts bycreated_atdescending.
searchLibrary(filters):
- Filters
nameplatesbynameand folder. - Filters
library_files_newby: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:
- User opens
/libraryor/design/cad-library(future). useLibraryloads folders and items for the tenant.- User uploads files and generates nameplates (via separate flows).
- Files and nameplates are stored in Supabase Storage and tracked in
library_files_new/nameplatestables. - Users search, filter, and organize assets by folder and tags.
Related docs¶
- Inventory Flow – for items that may reference CAD assets.
- Supabase Architecture – full data model.
- Frontend Architecture – route map and shared components.
- Billing & Stripe Flow – for plan limits used in
useLibrary.