Pinterest-style visual bookmarking app with: - URL metadata extraction (OG/Twitter meta, oEmbed fallback) - Image caching in Postgres with 480px thumbnails - Multi-tag filtering with Ctrl/Cmd for OR mode - Fuzzy tag suggestions and inline tag editing - Browser console auth() with first-use password setup - Brutalist UI with Commit Mono font and Pico CSS - Light/dark mode via browser preference
73 lines
2 KiB
SQL
73 lines
2 KiB
SQL
-- +goose Up
|
|
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
|
|
|
CREATE TABLE item (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
pub_id UUID NOT NULL DEFAULT gen_random_uuid(),
|
|
source_url TEXT NOT NULL,
|
|
title TEXT NOT NULL DEFAULT '',
|
|
description TEXT NOT NULL DEFAULT '',
|
|
site_name TEXT NOT NULL DEFAULT '',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
deleted_at TIMESTAMPTZ,
|
|
UNIQUE (pub_id)
|
|
);
|
|
|
|
CREATE INDEX idx_item_created_at ON item(created_at DESC);
|
|
CREATE INDEX idx_item_deleted_at ON item(deleted_at);
|
|
|
|
CREATE TABLE image (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
item_id BIGINT NOT NULL REFERENCES item(id) ON DELETE CASCADE,
|
|
original_url TEXT NOT NULL DEFAULT '',
|
|
content_type TEXT NOT NULL DEFAULT '',
|
|
bytes BYTEA NOT NULL,
|
|
width INT NOT NULL DEFAULT 0,
|
|
height INT NOT NULL DEFAULT 0,
|
|
is_thumb BOOLEAN NOT NULL DEFAULT FALSE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX idx_image_item ON image(item_id);
|
|
CREATE INDEX idx_image_thumb ON image(item_id, is_thumb);
|
|
|
|
CREATE TABLE tag (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
name TEXT NOT NULL UNIQUE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE item_tag (
|
|
item_id BIGINT NOT NULL REFERENCES item(id) ON DELETE CASCADE,
|
|
tag_id BIGINT NOT NULL REFERENCES tag(id) ON DELETE CASCADE,
|
|
PRIMARY KEY (item_id, tag_id)
|
|
);
|
|
|
|
CREATE INDEX idx_item_tag_item ON item_tag(item_id);
|
|
CREATE INDEX idx_item_tag_tag ON item_tag(tag_id);
|
|
|
|
CREATE TABLE auth (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
password_hash BYTEA NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE session (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
token TEXT NOT NULL UNIQUE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
expires_at TIMESTAMPTZ NOT NULL
|
|
);
|
|
|
|
CREATE INDEX idx_session_token ON session(token);
|
|
CREATE INDEX idx_session_expires_at ON session(expires_at);
|
|
|
|
-- +goose Down
|
|
DROP TABLE IF EXISTS session;
|
|
DROP TABLE IF EXISTS auth;
|
|
DROP TABLE IF EXISTS item_tag;
|
|
DROP TABLE IF EXISTS tag;
|
|
DROP TABLE IF EXISTS image;
|
|
DROP TABLE IF EXISTS item;
|
|
DROP EXTENSION IF EXISTS pgcrypto;
|