# Slack Clone - Basic MVP Requirements
## 1. Workspaces
- Create and join workspaces
- Workspace name and optional description
- Member roles (owner, admin, member)
- Workspace switching
- Basic workspace settings
## 2. Authentication
- Google sign-in only
- Protected routes
- Basic user profile (name, email, avatar)
## 3. Channels
- Create and join public channels within a workspace
- Channel name and optional description
- List of channel members
- Basic channel navigation
## 4. Direct Messaging
- One-on-one messaging within a workspace
- Conversation list in sidebar
- Basic online/offline status
## 5. Real-time Messaging
- Send and receive messages instantly
- Basic text messages
- Message history
- Edit and delete own messages
## 6. Channel/DM Organization
- Simple sidebar navigation
- List of channels
- List of direct messages
- Basic unread indicators
## 7. File Sharing
- Upload and share images
- Basic image preview
- Simple file list per channel
## 8. User Presence & Status
- Online/offline status
- Custom status message
- Last seen timestamp
## 9. Thread Support
- Create threads on messages
- View threaded conversations
- Thread notification badges
## 10. Emoji Reactions
- Add/remove reactions to messages
- Basic emoji picker
- Reaction counts
# Database Schema
## Workspaces table
```sql
create table workspaces (
id uuid primary key default uuid_generate_v4(),
name text not null,
slug text unique not null,
description text,
created_by uuid references users(id) on delete set null,
created_at timestamptz default now(),
updated_at timestamptz default now(),
invite_code text unique,
invite_expires_at timestamptz,
invite_is_revoked boolean default false
);
create index workspaces_invite_code_idx on workspaces(invite_code);
```
## Workspace members table
```sql
create table workspace_members (
workspace_id uuid references workspaces(id) on delete cascade,
user_id uuid references users(id) on delete cascade,
role text not null check (role in ('owner', 'admin', 'member')) default 'member',
joined_at timestamptz default now(),
primary key (workspace_id, user_id)
);
```
## Users table
```sql
create table users (
id uuid primary key default uuid_generate_v4(),
created_at timestamptz default now(),
email text unique not null,
name text not null,
avatar_url text,
status text,
last_seen timestamptz
);
```
## Channels table
```sql
create table channels (
id uuid primary key default uuid_generate_v4(),
workspace_id uuid references workspaces(id) on delete cascade not null,
name text not null,
description text,
created_by uuid references users(id) on delete set null,
created_at timestamptz default now(),
updated_at timestamptz default now(),
);
```
## Channel members table
```sql
create table channel_members (
channel_id uuid references channels(id) on delete cascade,
user_id uuid references users(id) on delete cascade,
role text not null check (role in ('admin', 'member')) default 'member',
joined_at timestamptz default now(),
primary key (channel_id, user_id)
);
```
## Conversations table
```sql
create table conversations (
id uuid primary key default uuid_generate_v4(),
workspace_id uuid references workspaces(id) on delete cascade not null,
created_at timestamptz default now(),
updated_at timestamptz default now(),
last_message_at timestamptz,
type text not null check (type in ('direct', 'group')) default 'direct'
);
```
## Conversation participants table
```sql
create table conversation_participants (
conversation_id uuid references conversations(id) on delete cascade,
user_id uuid references users(id) on delete cascade,
joined_at timestamptz default now(),
last_read_at timestamptz,
primary key (conversation_id, user_id)
);
```
## Messages table
```sql
create table messages (
id uuid primary key default uuid_generate_v4(),
conversation_id uuid references conversations(id) on delete cascade,
channel_id uuid references channels(id) on delete cascade,
user_id uuid references users(id) on delete cascade,
recipient_id uuid references users(id) on delete cascade,
parent_id uuid references messages(id) on delete cascade,
thread_participant boolean default false,
content text not null,
created_at timestamptz default now(),
updated_at timestamptz default now(),
-- messages must belong to either a conversation or channel
constraint message_container_check check (
(conversation_id is null and channel_id is not null) or
(conversation_id is not null and channel_id is null)
)
);
create index messages_user_id_idx on messages(user_id);
create index messages_recipient_id_idx on messages(recipient_id);
create index messages_parent_id_idx on messages(parent_id);
```
## Enable Row Level Security
```sql
alter table workspaces enable row level security;
alter table workspace_members enable row level security;
alter table channels enable row level security;
alter table messages enable row level security;
alter table channel_members enable row level security;
alter table channel_invites enable row level security;
alter table conversations enable row level security;
alter table conversation_participants enable row level security;
```
## Enable Realtime
```sql
alter publication supabase_realtime add table workspaces;
alter publication supabase_realtime add table workspace_members;
alter publication supabase_realtime add table channels;
alter publication supabase_realtime add table messages;
alter publication supabase_realtime add table channel_invites;
alter publication supabase_realtime add table conversations;
alter publication supabase_realtime add table conversation_participants;
```
# Tech Stack
## Core Framework
- **Next.js 14+** (App Router)
- **React 19**
- **TypeScript**
## Authentication & Database
- **NextAuth.js** (v5 beta) - Google authentication
- **Supabase** - PostgreSQL database with realtime capabilities
- Database
- Row Level Security
- Realtime subscriptions
- Storage (for file uploads)
## UI Components & Styling
- **Tailwind CSS**
- **shadcn/ui**
# Notes
In Next.js 15+, dynamic route parameters (like `params` and `searchParams`) are asynchronous.
You must await the entire `params` object before accessing its properties.
Use `npx shadcn@latest` not `npx shadcn-ui@latest`.auth.js
css
golang
javascript
next.js
nextauth
postgresql
react
+5 more
First Time Repository
TypeScript
Languages:
CSS: 3.8KB
JavaScript: 0.1KB
TypeScript: 104.8KB
Created: 1/7/2025
Updated: 1/9/2025