## PHASE 2.1: DATABASE SCHEMA DESIGN
## NourSky CRM — PostgreSQL (Neon Serverless)
DESIGN PRINCIPLES:
→ Everything is a BLOCK — workspace, database, page, and content are all blocks
→ Use JSONB for flexible, schema-less block properties (CRM custom fields)
→ Apply GIN indexes on JSONB columns for sub-millisecond CRM filtering
→ Design for horizontal sharding from day 1 (partition by workspace_id)
→ Use UUID v4 for all primary keys (globally unique, shard-safe)
REQUIRED TABLES:
1. workspaces — id, name, slug, theme JSONB, plan, created_at
2. users — id, clerk_user_id, email, display_name, avatar_url
3. workspace_members — workspace_id, user_id, role, joined_at (composite PK)
4. blocks — CORE TABLE (see schema below)
5. templates — id, name, category, blocks_json JSONB, is_public
6. workflow_automations— trigger_type, trigger_config JSONB, action_type, action_config JSONB
7. block_permissions — block_id, subject_type, subject_id, permission_level
8. activity_log — workspace_id, user_id, action, target_block_id, metadata JSONB
CORE BLOCKS TABLE SPECIFICATION:
CREATE TABLE blocks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
workspace_id UUID NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
parent_id UUID REFERENCES blocks(id) ON DELETE CASCADE,
type TEXT NOT NULL, -- paragraph|heading_1|page|child_database|...
properties JSONB NOT NULL DEFAULT '{}',
content UUID[] DEFAULT '{}', -- Ordered array of child block UUIDs
created_by UUID NOT NULL REFERENCES users(id),
last_edited_by UUID REFERENCES users(id),
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
is_archived BOOLEAN DEFAULT FALSE,
is_in_trash BOOLEAN DEFAULT FALSE,
cover_url TEXT,
icon TEXT -- Emoji or URL
);
REQUIRED INDEXES (for performance):
→ GIN index on blocks.properties (JSONB filtering for CRM views)
→ BTREE on blocks.workspace_id (all workspace queries)
→ BTREE on blocks.parent_id (tree traversal)
→ BTREE on blocks.type (block type filtering)
→ BTREE on blocks.created_at (sorting by date)
POSTGRESQL VIEWS REQUIRED:
→ v_database_records — Flattens JSONB properties into relational columns
→ v_kanban_view — Groups records by status property
→ v_calendar_view — Extracts date properties for calendar rendering
→ v_workspace_activity — Joins blocks + users for activity feed
DELIVERABLE:
Write the complete schema.sql migration file with:
- All CREATE TABLE statements in dependency order
- All indexes (GIN + BTREE)
- All PostgreSQL views with ON SELECT DO INSTEAD rules
- All ON DELETE CASCADE / SET NULL rules
- Seed data: 1 demo workspace, 3 demo users, 10 demo blocks
- Comment every column with its purpose
Output: /db/migrations/001_initial_schema.sql