See the app here.
- app
- auth
- callback
- route.ts (handles Google OAuth redirection?)
- callback
- messages
- login
- page.tsx (login page)
- handles email authentication and redirects for Google OAuth
- page.tsx (login page)
- page.tsx (landing page)
- auth
- lib
- supabase
- client.ts
- server.ts
- supabase
- public (folder for images and icons)
- proxy.ts
- runs on every request and redirects unauthenticated user
users should be able to log in with an email and passwordusers should be able to log outusers should be able to send and receive messagesusers should be able to set usernames (unique) and display names (doesn't need to be unique)users should be able to search for users based on username or display name and start a conversation with them
- users should be able to reply to messages
users should be able to add profile imagesusers should be able to update profile images- users should be able to see when others in the chat are typing
users should be able to recover their account if they forget their password
- users should be able to react to messages with emojis
- users should be able to create custom reactions
- users should be able to react to messages with custom reactions
- users should be able to select custom reaction memes to send in their chats from the app's image store
- users should be able to create custom reaction memes
- users should be able to delete messages
| Thing | Canvas dimensions | Brush dimensions |
|---|---|---|
| jas icon | 60x60 | 4x4 |
| logout icon | 60x60 | 4x4 |
| back icon | 32x60 | 8x8 |
| edit icon | 7x32 | 8x8 |
| header | 32x80 | 16x16 |
| border | 64x64 | 16x16 |
| cursors | 26x26 | N/A |
Using Supabase's PostgreSQL platform. Handles authentication via Supabase client using .signUp({ email, password }), .signInWithPassword({ email, password }), and .signInWithOAuth(provider). Currently only supports email authentication and Google OAuth.
- User (auth)
- UUID (autogenerated)
- email_confirmed_at
- last_sign_in_at
- created_at
- updated_at
- phone_confirmed_at
- deleted_at
- display_name
- providers
- provider_type
- Profile (public) - automatically created when new auth.user is created
- id (references User UUID)
- updated_at
- username
- display_name
- avatar_url
- Conversation (public)
- id (autogenerated)
- created_at
- Conversation Member (public)
- conversation_id (references Conversation UUID)
- user_id (references User UUID)
- primary_key (conversation_id, user_id)
- Message (public)
- index: (conversation_id, created_at)
- id (autogenerated)
- conversation_id (references Conversation UUID)
- sender_id (references User UUID)
- content
- created_at
- Note: auth.uid() is populated automatically from the JWT request -- Users can only read messages from conversations they're in create policy "members can read messages" on messages for select using ( auth.uid() in ( select user_id from conversation_members where conversation_id = messages.conversation_id ) );
-- Users can only send messages as themselves create policy "members can insert messages" on messages for insert with check ( auth.uid() = sender_id and auth.uid() in ( select user_id from conversation_members where conversation_id = messages.conversation_id ) );
-- Users can only see conversations they're a member of create policy "members can read conversations" on conversations for select using ( auth.uid() in ( select user_id from conversation_members where conversation_id = conversations.id ) );
-- Users can create conversations if they're authenticated
-- Users can only see their own membership records create policy "members can read own memberships" on conversation_members for select using (auth.uid() = user_id);
-- Users can read any profile (for showing names in conversations) create policy "profiles are publicly readable" on profiles for select using (true);
-- Users can only update their own profile create policy "users can update own profile" on profiles for update using (auth.uid() = id);