Clever Widget Factory
No description available
Install / Use
/learn @whiteboxllms/Clever Widget FactoryREADME
Clever Widget Factory
A comprehensive asset management and accountability system built with React, TypeScript, and AWS.
Current Architecture (Post-Migration)
⚠️ IMPORTANT: We are NO LONGER using Supabase. The application has been migrated to AWS infrastructure.
Technology Stack
- Frontend: React + TypeScript + Vite (runs on port 8080)
- Backend API: AWS API Gateway + Lambda
- Database: AWS RDS PostgreSQL
- Authentication: AWS Cognito
- File Storage: AWS S3
- Infrastructure: Fully AWS-based
Local Development Setup
Prerequisites
- Node.js & npm installed - install with nvm
Development Setup
-
Clone and install:
git clone <YOUR_GIT_URL> cd clever-widget-factory npm i -
Start the frontend:
npm run devThis starts the Vite dev server on http://localhost:8080
API Configuration
IMPORTANT: The VITE_API_BASE_URL should NOT include the /api suffix:
- ✅ Correct:
https://xxx.execute-api.us-west-2.amazonaws.com/prod - ❌ Wrong:
https://xxx.execute-api.us-west-2.amazonaws.com/prod/api
The apiService automatically adds /api to all endpoints.
API Endpoints
The AWS API Gateway provides these endpoints:
GET /health- Health checkGET /api/actions- Get all actionsPOST /api/actions- Create actionPUT /api/actions/{id}- Update actionDELETE /api/actions/{id}- Delete actionGET /api/organization_members- Get organization membersGET /api/tools- Get toolsGET /api/parts- Get partsPOST /api/query- Execute custom SQL queriesPOST /api/semantic-search- Semantic search using Bedrock embeddings
/api/tools response
Tools are served by the cwf-core-lambda function which queries the AWS RDS instance. Each tool row now includes checkout metadata resolved server-side (no extra checkout request required):
is_checked_out(boolean)checked_out_user_idchecked_out_tochecked_out_dateexpected_return_datecheckout_intended_usagecheckout_notes
When a tool has an active checkout (is_returned = false in checkouts), status is automatically overridden to checked_out.
Database Connection
- All environments: AWS RDS PostgreSQL instance
Database Migrations
Run database migrations using the Lambda function:
aws lambda invoke --function-name cwf-db-migration --payload '{"sql":"YOUR_SQL_HERE"}' response.json --region us-west-2 --cli-binary-format raw-in-base64-out
API Gateway Management
Adding new endpoints:
# Add endpoint with authorizer
./scripts/add-api-endpoint.sh /api/your-endpoint GET
# Deploy changes
aws apigateway create-deployment --rest-api-id 0720au267k --stage-name prod --region us-west-2
Verify all endpoints have authorizers:
./scripts/verify-api-authorizers.sh
Important: All API endpoints (except /api/health and /api/schema) MUST have the authorizer configured. The verification script runs weekly via GitHub Actions.
Migration Status
✅ COMPLETED: Migrated from Supabase to AWS infrastructure
- Frontend updated to use API service instead of Supabase client
- Database migrated to PostgreSQL
- Authentication moved to AWS Cognito
- File storage moved to AWS S3
- Policy agreement system implemented (actions now use
policy_agreed_at/policy_agreed_byfields)
User ID Migration Reference
During Cognito migration, user IDs were updated. Reference for any remaining migrations:
| User | Old UUID | New Cognito UUID |
|------|----------|------------------|
| Malone | 4d7124f9-c0f2-490d-a765-3a3f8d1dbad8 | 989163e0-7011-70ee-6d93-853674acd43c |
| Lester Paniel | 7dd4187f-ff2a-4367-9e7b-0c8741f25495 | 68d173b0-60f1-70ea-6084-338e74051fcc |
| Mae Dela Torre | 48155769-4d22-4d36-9982-095ac9ad6b2c | 1891f310-c071-705a-2c72-0d0a33c92bf0 |
| Stefan Hamilton | b8006f2b-0ec7-4107-b05a-b4c6b49541fd | 08617390-b001-708d-f61e-07a1698282ec |
Development Best Practices
TanStack Query Cache Pattern
Problem: Storing entity objects in local state creates stale snapshots that don't update when the cache refetches.
Solution: Store IDs in state, look up entities from cache.
// ❌ BAD - Creates stale snapshot
const [editingAction, setEditingAction] = useState<Action | null>(null);
<Dialog action={editingAction} />
// ✅ GOOD - Always fresh from cache
const [editingActionId, setEditingActionId] = useState<string | null>(null);
const editingAction = actions.find(a => a.id === editingActionId);
<Dialog action={editingAction} />
When to use:
- Edit dialogs (Actions, Missions, Issues, Tools, etc.)
- Any component that displays cached data that can be updated elsewhere
- Forms that stay open during save operations
Implementation:
- Store only the ID in
useState - Look up the entity from the TanStack Query cache using
find() - The lookup always returns fresh data after refetches
See src/pages/Actions.tsx for reference implementation.
What technologies are used for this project?
This project is built with:
- Frontend: React 18, TypeScript, Vite
- UI Components: shadcn-ui, Radix UI, Tailwind CSS
- Database: AWS RDS PostgreSQL
- Authentication: AWS Cognito
- State Management: React Query (TanStack Query)
- Forms: React Hook Form with Zod validation
- Rich Text: Tiptap editor
- Image Processing: Browser Image Compression
- Date Handling: date-fns
- Icons: Lucide React
Testing
Run the test suite:
npm test # Run all tests
npm run test:watch # Watch mode
npm run test:ui # UI mode
npm run test:coverage # With coverage
API Endpoint Tests
Test specific API endpoints:
# Get auth token from browser (copy from Network tab)
TOKEN="Bearer eyJraWQ..."
# Test action_implementation_updates endpoint
./tests/api/action-implementation-updates-502.test.sh "$TOKEN"
See docs/502-ERROR-ACTION-IMPLEMENTATION-UPDATES.md for troubleshooting 502 errors.
Legacy Files (To Be Removed)
The following files are legacy from the Supabase era and should be ignored:
supabase/directory- Any files referencing
@supabase/supabase-js SUPABASE_TO_AWS_MIGRATION_PLAN.md(migration is complete)
Semantic Search
The application uses AWS Bedrock Titan embeddings for semantic search across tools and parts.
Architecture:
cwf-semantic-searchLambda: Handles search requests, generates embeddings via Bedrock, queries vector databasecwf-embeddings-lambda: Standalone Lambda for generating embeddings (used by backfill scripts)- VPC Endpoint:
bedrock-runtimeendpoint allows Lambda in VPC to access Bedrock - Database: PostgreSQL with pgvector extension for vector similarity search
- Embedding Model: Amazon Titan Text Embeddings v1 (1536 dimensions)
- Indexed Fields: Only
nameanddescriptionfields are embedded for semantic search
Backfill embeddings:
./backfill-embeddings-full-context.sh
This generates embeddings for all tools and parts using their name and description fields.
Search endpoint:
POST /api/semantic-search
{
"query": "search text",
"table": "parts" | "tools",
"limit": 10
}
TODO / Known Issues
- Proper Solution: Implement presigned URL generation via backend Lambda
- Create Lambda endpoint:
POST /api/upload/presigned-url - Lambda generates temporary presigned URL with expiration
- Frontend uploads directly to S3 using presigned URL
- Remove
VITE_AWS_ACCESS_KEY_IDandVITE_AWS_SECRET_ACCESS_KEYfrom frontend
- Create Lambda endpoint:
- Files:
src/hooks/useImageUpload.tsx,src/lib/s3Client.ts
Database Functions & Triggers
- Important: All Lambda functions MUST pass
organization_idexplicitly from the authorizer context. The stub function is ONLY for legacy triggers. - Proper Fix Needed:
- Find all triggers using
get_user_organization_id()(seefind-triggers-using-org-id.sql) - Remove triggers or update them to not use this function
- Verify all Lambda INSERT statements explicitly include
organization_idfrom authorizer context (NOT from request body) - Remove stub function once triggers are cleaned up
- Find all triggers using
- Files:
fix-get-user-org-id.sql,find-triggers-using-org-id.sql
