Skip to main content

saved_posts

Overview

The saved_posts table allows users to save posts for later reference. Saved posts can optionally be organized into shelves (folders) and annotated with personal notes. Saving is a private action -- other users cannot see who saved their posts.

Relevant Invariants

  • Invariant #6: "No Public Comparative Metrics" -- Save counts are never shown to anyone
  • Invariant #14: "Privacy Is Infrastructure" -- Saves are completely private to the user

Schema

-- Pre-existing table (inferred from frontend code)
CREATE TABLE saved_posts (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID REFERENCES auth.users(id) NOT NULL,
post_id UUID REFERENCES posts(id) ON DELETE CASCADE NOT NULL,
shelf_id UUID REFERENCES shelves(id) ON DELETE SET NULL,
note TEXT,
saved_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(user_id, post_id)
);

Columns

ColumnTypeNullableDefaultDescription
iduuidNouuid_generate_v4()Primary key
user_iduuidNo--User who saved the post
post_iduuidNo--The saved post, cascades on post delete
shelf_iduuidYes--Optional shelf for organization
notetextYes--Personal note about why it was saved
saved_attimestamptzNoNOW()When the post was saved

RLS Policies

-- SELECT: Users can only see their own saved posts
CREATE POLICY "Users can view own saved posts"
ON saved_posts FOR SELECT
USING (auth.uid() = user_id);

-- INSERT: Users can save posts
CREATE POLICY "Users can save posts"
ON saved_posts FOR INSERT
WITH CHECK (auth.uid() = user_id);

-- UPDATE: Users can update shelf assignment or note
CREATE POLICY "Users can update own saved posts"
ON saved_posts FOR UPDATE
USING (auth.uid() = user_id);

-- DELETE: Users can unsave posts
CREATE POLICY "Users can unsave posts"
ON saved_posts FOR DELETE
USING (auth.uid() = user_id);

Last updated: 2026-02-07