Skip to main content

home_room_modules

Overview

The home_room_modules table stores individual content blocks placed within a user's HomeRoom. Each module has a type (one of: about, mebook, photos, links, featured_posts, guestbook), display order, enable/collapse toggles, per-module visibility controls, and optional configuration JSON. Layout positioning columns (added by 20260202_room_layouts.sql) support freeform, grid, and mindmap layout modes.

Default modules are automatically created for each new user via a trigger on the profiles table. A unique constraint on (user_id, module_type) ensures one module of each type per user.

Schema

-- From 20260130_homeroom_foundation.sql
CREATE TABLE home_room_modules (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID REFERENCES profiles(id) ON DELETE CASCADE NOT NULL,

-- Module identification
module_type TEXT NOT NULL CHECK (module_type IN (
'about', 'mebook', 'photos', 'links', 'featured_posts', 'guestbook'
)),

-- Display settings
order_index INT NOT NULL DEFAULT 0,
is_enabled BOOLEAN DEFAULT TRUE,
default_collapsed BOOLEAN DEFAULT FALSE,
custom_title TEXT,

-- Visibility
visibility_scope TEXT DEFAULT 'inherit' CHECK (visibility_scope IN (
'inherit', 'public', 'friends', 'circles', 'specific'
)),
allowed_viewer_ids UUID[] DEFAULT NULL,

-- Module-specific config
config_json JSONB DEFAULT '{}',

created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),

UNIQUE(user_id, module_type),

-- Layout positioning (added by 20260202_room_layouts.sql)
position_x INT DEFAULT NULL,
position_y INT DEFAULT NULL,
width INT DEFAULT NULL,
height INT DEFAULT NULL,
grid_column INT DEFAULT NULL,
grid_row INT DEFAULT NULL,
grid_span INT DEFAULT 1,
connected_to UUID[] DEFAULT NULL,
z_index INT DEFAULT 0
);

Columns

ColumnTypeNullableDefaultDescription
iduuidNogen_random_uuid()Primary key
user_iduuidNo--Module owner, references profiles(id)
module_typetextNo--Module type: about, mebook, photos, links, featured_posts, guestbook
order_indexintNo0Sort order in single-column layout
is_enabledbooleanNoTRUEWhether module is active
default_collapsedbooleanNoFALSEWhether module starts collapsed
custom_titletextYes--Optional override of default module title
visibility_scopetextNo'inherit'Visibility: inherit, public, friends, circles, specific
allowed_viewer_idsuuid[]YesNULLSpecific user IDs allowed when scope is 'specific'
config_jsonjsonbNo'{}'Module-specific configuration data
created_attimestamptzNoNOW()Creation timestamp
updated_attimestamptzNoNOW()Last update timestamp (auto-updated by trigger)
position_xintYesNULLX position for freeform/mindmap layouts
position_yintYesNULLY position for freeform/mindmap layouts
widthintYesNULLCustom width override
heightintYesNULLCustom height override
grid_columnintYesNULLSpecific column assignment for column layouts
grid_rowintYesNULLSpecific row assignment for grid layouts
grid_spanintNo1Number of columns to span
connected_touuid[]YesNULLArray of module IDs this connects to (mindmap)
z_indexintNo0Stacking order for overlapping modules

Constraints

  • UNIQUE(user_id, module_type) -- One module of each type per user
  • module_type must be one of: about, mebook, photos, links, featured_posts, guestbook
  • visibility_scope must be one of: inherit, public, friends, circles, specific

Triggers

-- Auto-updates updated_at on row changes (reuses the home_room_settings function)
CREATE TRIGGER home_room_modules_updated
BEFORE UPDATE ON home_room_modules
FOR EACH ROW EXECUTE FUNCTION update_home_room_settings_updated_at();

Default Modules

When a new profile is created, the following modules are auto-inserted:

module_typeorder_indexis_enabled
about0TRUE
photos1TRUE
mebook2FALSE
links3TRUE
featured_posts4TRUE
guestbook5FALSE

RLS Policies

-- SELECT: Visibility based on module scope, friendship, and specific viewer list
CREATE POLICY "Users can view modules based on visibility"
ON home_room_modules FOR SELECT TO authenticated
USING (
user_id = auth.uid()
OR (
is_enabled = TRUE
AND (
visibility_scope = 'public'
OR visibility_scope = 'inherit'
OR (visibility_scope = 'friends' AND user_id IN (
SELECT CASE
WHEN requester_id = auth.uid() THEN addressee_id
ELSE requester_id
END
FROM friendships
WHERE status = 'accepted'
AND (requester_id = auth.uid() OR addressee_id = auth.uid())
))
OR (visibility_scope = 'specific' AND auth.uid() = ANY(allowed_viewer_ids))
)
)
);

-- ALL (INSERT/UPDATE/DELETE): Only owner can manage their own modules
CREATE POLICY "Users can manage own modules"
ON home_room_modules FOR ALL TO authenticated
USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);

Indexes

CREATE INDEX idx_home_room_modules_user_id ON home_room_modules(user_id);
CREATE INDEX idx_home_room_modules_type ON home_room_modules(module_type);

Last updated: 2026-02-07