DROP DATABASE vintagecoding; CREATE DATABASE vintagecoding; USE vintagecoding; CREATE TABLE roles ( id INT PRIMARY KEY AUTO_INCREMENT, role VARCHAR(16) NOT NULL ); INSERT INTO roles (role) VALUES ('owner'), ('developer'), ('user'); CREATE TABLE user ( id INT PRIMARY KEY, username VARCHAR(32) NOT NULL UNIQUE, email VARCHAR(64), passwordHash VARCHAR(256) NOT NULL, role INT DEFAULT 3, createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, lastActive TIMESTAMP DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, isActive BOOLEAN DEFAULT FALSE, profilePicture VARCHAR(256), bio VARCHAR(256), website VARCHAR(64), FOREIGN KEY (role) REFERENCES roles (id) ON DELETE CASCADE ); INSERT INTO user (id, username, email, passwordHash, role, profilePicture) VALUES (1, 'joshashton', 'me@joshashton.dev', '$2y$12$CDMWB7IzcURWaxPxb1RrZezgy5acNFU7kSogM/ObohAZPT0.3H75K', 1, '2025.jpg'); CREATE TABLE rememberUser ( token VARCHAR(128) PRIMARY KEY, id INT NOT NULL, remoteAddr VARCHAR(64) NOT NULL, httpForward VARCHAR(64), createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (id) REFERENCES user (id) ON DELETE CASCADE ); -- TODO: Need cron job to auto-delete after 30 days of inactivity CREATE TABLE postTypes ( id INT PRIMARY KEY AUTO_INCREMENT, postType VARCHAR(16) ); INSERT INTO postTypes (postType) VALUES ('essay'), ('moment'), ('thought'); CREATE TABLE postStatus ( id INT PRIMARY KEY AUTO_INCREMENT, status VARCHAR(16) ); INSERT INTO postStatus (status) VALUES ('draft'), ('published'); CREATE TABLE spaceVisibility ( id INT PRIMARY KEY AUTO_INCREMENT, spaceVisibility VARCHAR(16) ); INSERT INTO spaceVisibility (spaceVisibility) VALUES ('open'), ('public'), ('request'), ('invite'), ('private'); CREATE TABLE space ( id INT PRIMARY KEY, visibility INT NOT NULL, name VARCHAR(64) NOT NULL, description TEXT, parent INT DEFAULT NULL, createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (parent) REFERENCES space(id) ON DELETE SET NULL, FOREIGN KEY (visibility) REFERENCES spaceVisibility(id) ); INSERT INTO space (id, visibility, name, description) VALUES (1, 5, "joshashton", "Thoughts, Moments, and Essays that I braindump."), (2025, 1, "Open", "Thoughts, Moments, and Essays that are open for all."); CREATE TABLE spaceRoles ( id INT PRIMARY KEY AUTO_INCREMENT, role VARCHAR(16) NOT NULL ); INSERT INTO spaceRoles (role) VALUES ("owner"), ("administrator"), ("moderator"), ("viewer"); CREATE TABLE spaceMembers ( id INT PRIMARY KEY AUTO_INCREMENT, user INT NOT NULL, space INT NOT NULL, role INT NOT NULL, addedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, favorited BOOLEAN DEFAULT FALSE, FOREIGN KEY (user) REFERENCES user(id), FOREIGN KEY (space) REFERENCES space(id), FOREIGN KEY (role) REFERENCES spaceRoles(id) ); INSERT INTO spaceMembers (id, user, space, role) VALUES (2, 1, 2025, 1), (1, 1, 1, 1); CREATE TABLE post ( id INT PRIMARY KEY, space INT NOT NULL, creator INT NOT NULL, postType INT NOT NULL, status INT NOT NULL, title VARCHAR(255), -- Make title nullable to accommodate Moments and Thoughts markdown TEXT, -- For Essays excerpt VARCHAR(255), -- For Essays caption TEXT, -- For Moments images TEXT, -- Store image filenames as JSON for Moments thought TEXT, -- For Thoughts seenCount INT DEFAULT 0, createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (space) REFERENCES space(id) ON DELETE CASCADE, FOREIGN KEY (status) REFERENCES postStatus(id) ON DELETE CASCADE, FOREIGN KEY (creator) REFERENCES user(id) ON DELETE CASCADE, FOREIGN KEY (postType) REFERENCES postTypes(id) ); CREATE TABLE spacePosts ( post INT NOT NULL, space INT NOT NULL, PRIMARY KEY (post, space), FOREIGN KEY (post) REFERENCES post(id) ON DELETE CASCADE, FOREIGN KEY (space) REFERENCES space(id) ON DELETE CASCADE ); CREATE TABLE topics ( id INT PRIMARY KEY AUTO_INCREMENT, topic VARCHAR(16) NOT NULL ); CREATE TABLE postTopics ( post INT NOT NULL, topic INT NOT NULL, PRIMARY KEY (post, topic), FOREIGN KEY (post) REFERENCES post(id) ON DELETE CASCADE, FOREIGN KEY (topic) REFERENCES topics(id) ON DELETE CASCADE ); CREATE TABLE todoPriority ( id INT PRIMARY KEY AUTO_INCREMENT, priority VARCHAR(16) NOT NULL ); INSERT INTO todoPriority (priority) VALUES ("Low"), ("Medium"), ("High"), ("Urgent"); CREATE TABLE todo ( id INT NOT NULL, space INT NOT NULL, title VARCHAR(32) NOT NULL, description TEXT, due DATETIME, priority INT NOT NULL, link TEXT, createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id, space), FOREIGN KEY (space) REFERENCES space(id) ON DELETE CASCADE, FOREIGN KEY (priority) REFERENCES todoPriority(id) ); INSERT INTO todo (id, space, title, description, due, priority, link) VALUES (2026, 1, "weave.space", "Need to finish building this site.", CURRENT_TIMESTAMP, 3, "weave.space"); CREATE TABLE follows ( follower INT NOT NULL, following INT NOT NULL, notifyUser BOOLEAN DEFAULT FALSE, followed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (follower, following), FOREIGN KEY (follower) REFERENCES user(id) ON DELETE CASCADE, FOREIGN KEY (following) REFERENCES user(id) ON DELETE CASCADE );