* feat(community): filter empty projects from public gallery Add is_empty column to projects table so the public gallery only shows projects with actual content. Scene graph emptiness is computed on save and on creation, and a backfill migration marks existing non-empty projects. Also cleans up import ordering, fixes README migration path, and removes stale feedback table migration. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Use ESNext modules and bundler resolution Update packages/db tsconfig to emit ESNext modules and use 'bundler' moduleResolution. This enables modern ESM output and bundler-style resolution for the db package (keeps outDir and rootDir unchanged). * feat(editor): add dark mode theme and grid visibility toggle Add theme state to viewer store with light/dark modes, dark-aware lighting and background colors, grid show/hide toggle in settings, and theme toggle buttons in the sidebar. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add ground occluder, animated lighting & UI tweaks Introduce a ground occluder and smoother animated lighting while adjusting editor UI and icons. Viewer: add GroundOccluder (uses polygon-clipping to union slab/zone polygons) and AnimatedBackground, integrate both into the Canvas; improve Lights to interpolate intensities/colors/ambient for smooth theme transitions. Editor: refactor sidebar header to support inline project title editing and move the theme toggle; replace some lucide icons with image assets and add a settings icon (apps/editor/public/icons/settings.png). Also add polygon-clipping to the viewer package dependencies. * Update dark mode background color and clean up imports Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
6.6 KiB
6.6 KiB
Community Feature
This directory contains the optional community features (cloud synchronization and authentication) for the Pascal Editor. This feature is specific to the Pascal platform and can be safely removed if you're using the editor standalone.
What This Does
The community feature provides:
- Authentication - Sign in with magic link via Better Auth
- Property Management - Create and manage properties with Google Maps address search
- Scene Loading - Automatically load property scenes from the database when a property is selected
- Auto-Save - Automatically save scene changes to the database (2-second debounce)
- Database Sync - Save and load editor state from a PostgreSQL database via Supabase
Architecture
features/community/
├── lib/
│ ├── auth/
│ │ ├── client.ts # Re-exports from @pascal-app/auth
│ │ ├── server.ts # Server-side session handling
│ │ └── hooks.ts # useAuth React hook
│ ├── properties/
│ │ ├── actions.ts # Server actions for CRUD operations
│ │ ├── types.ts # TypeScript types for properties
│ │ ├── hooks.ts # Property React hooks
│ │ └── store.ts # Zustand store for property state
│ ├── models/
│ │ ├── actions.ts # Scene model CRUD operations
│ │ └── hooks.ts # Scene loading and auto-save hooks
│ ├── database/
│ │ └── server.ts # Re-exports from @pascal-app/db
│ └── utils/
│ └── id-generator.ts # nanoid-based ID generation
├── components/
│ ├── cloud-save-button.tsx # Main UI entry point (top-right button)
│ ├── sign-in-dialog.tsx # Magic link sign-in dialog
│ ├── profile-dropdown.tsx # User profile menu
│ ├── property-dropdown.tsx # Property selector dropdown
│ ├── new-property-dialog.tsx # Create new property dialog
│ └── google-address-search.tsx # Google Maps autocomplete
└── README.md # This file
How It Works
Authentication Flow
- User clicks "Save to cloud" button
- Signs in with magic link (email-based, no password)
- Better Auth session is stored in cookies
- Server actions validate session using Better Auth API
Property Management
- User creates a property with a real-world address (Google Maps)
- Address and property are saved to PostgreSQL via Supabase
- Properties are associated with the authenticated user
- User can switch between properties
Scene Management
- When a property is selected, its scene is loaded from
properties_modelstable - If no scene exists, loads default empty scene
- Scene changes are auto-saved every 2 seconds (debounced)
- Updates existing model (highest version) instead of creating new ones
- Scene graph includes all nodes and hierarchy
Database Integration
- Uses Supabase (PostgreSQL) for database access
- Better Auth manages authentication tables directly
- Server actions use service role key to bypass RLS
- Permissions enforced by filtering on
owner_id - Tables:
users,sessions,properties,properties_addresses,properties_models
Required Environment Variables
# Database Connection
DATABASE_URL=postgresql://postgres:postgres@127.0.0.1:54322/postgres
# Supabase Configuration
NEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_anon_key_here
SUPABASE_SERVICE_ROLE_KEY=your_service_role_key_here
# Better Auth
BETTER_AUTH_SECRET=<generate_with_openssl_rand_base64_32>
BETTER_AUTH_URL=http://localhost:3000
# Google Maps API Key (for address search)
NEXT_PUBLIC_GOOGLE_MAPS_API_KEY=your_google_maps_key_here
Generate BETTER_AUTH_SECRET:
openssl rand -base64 32
Dependencies
The community feature requires these packages:
{
"better-auth": "^1.4.18",
"@supabase/supabase-js": "^2.95.3",
"@react-google-maps/api": "^2.20.8",
"nanoid": "^5.1.6"
}
How to Remove (For Open Source Users)
If you want to use the editor without community features:
1. Delete this directory
rm -rf features/community
2. Remove the CloudSaveButton from the editor
Edit components/editor/index.tsx:
- import { CloudSaveButton } from '@/features/community/components/cloud-save-button'
export default function Editor() {
return (
<div className="w-full h-full">
<ActionMenu />
<PanelManager />
- <CloudSaveButton />
3. Remove dependencies (optional)
Edit package.json:
- "better-auth": "^1.4.18",
- "@supabase/supabase-js": "^2.95.3",
- "@react-google-maps/api": "^2.20.8",
- "nanoid": "^5.1.6"
4. Remove environment variables
Delete from .env.local and .env.example:
- NEXT_PUBLIC_API_URL=...
- NEXT_PUBLIC_SUPABASE_URL=...
- NEXT_PUBLIC_SUPABASE_ANON_KEY=...
- SUPABASE_SERVICE_ROLE_KEY=...
- NEXT_PUBLIC_GOOGLE_MAPS_API_KEY=...
That's it! The editor will work as a standalone application without any cloud features.
Backend Requirements
This feature requires:
- Supabase local development instance
- PostgreSQL database with the following tables:
users- User accounts (Better Auth)sessions- Authentication sessions (Better Auth)verification_tokens- Magic link tokens (Better Auth)properties- Property recordsproperties_addresses- Property addressesproperties_models- Scene graph models
- Database migrations are managed in
supabase/migrations/
Development
To work on this feature:
- Install dependencies:
bun install - Start Supabase local development:
bun db:start - Run database migrations:
bun db:reset - Configure all environment variables in
apps/editor/.env.local - Run the editor:
bun dev
The editor will be available at http://localhost:3000.
For detailed setup instructions, see SETUP.md in the root directory.
Notes
- This feature uses server actions (Next.js App Router) for all database operations
- Authentication is handled by Better Auth with magic link support
- Better Auth server is configured in
packages/authand mounted at/api/auth/* - The editor queries the database directly using Supabase with service role key
- IDs are generated using nanoid with custom alphabet
- Scene state is managed with a Zustand store for reliable property switching
- Scene changes are auto-saved with 2-second debouncing to the currently selected property