- Development:
http://localhost:3001 - Production:
https://studious.sh(or configured viaNEXT_PUBLIC_APP_URL)
- Framework: tRPC (TypeScript RPC)
- Base Path:
/trpc - Authentication: Session-based (Bearer token in Authorization header)
- Real-time: Pusher integration for live updates
- Database: PostgreSQL with Prisma ORM
Description: Register a new user account Authentication: Public Input Schema:
{
username: string (min 3 chars),
email: string (valid email),
password: string (min 6 chars),
confirmPassword: string
}Response:
{
user: {
id: string,
username: string
}
}Error Codes: CONFLICT (username/email exists)
Description: Authenticate user and create session Authentication: Public Input Schema:
{
username: string,
password: string
}Response:
{
token: string, // Session ID
user: {
id: string,
username: string
}
} | {
verified: false,
user: {
email: string
}
}Error Codes: UNAUTHORIZED (invalid credentials)
Description: End user session Authentication: Required Input Schema: None Response:
{
success: boolean
}Error Codes: UNAUTHORIZED (not authenticated)
Description: Verify authentication and get user profile Authentication: Required Input Schema: None Response:
{
user: {
id: string,
username: string,
profile: {
displayName?: string,
bio?: string,
location?: string,
website?: string,
profilePicture?: string,
profilePictureThumbnail?: string
}
}
}Error Codes: UNAUTHORIZED, NOT_FOUND
Description: Resend email verification Authentication: Public Input Schema:
{
email: string (valid email)
}Response:
{
success: boolean
}Error Codes: NOT_FOUND (user not found)
Description: Verify email with token Authentication: Public Input Schema:
{
token: string
}Response:
{
success: boolean
}Error Codes: NOT_FOUND, UNAUTHORIZED (expired)
Description: Get all conversations for authenticated user Authentication: Required Input Schema: None Response:
Array<{
id: string,
type: "DM" | "GROUP",
name?: string,
createdAt: Date,
updatedAt: Date,
members: Array<{
id: string,
userId: string,
role: "ADMIN" | "MEMBER",
lastViewedAt?: Date,
lastViewedMentionAt?: Date,
user: {
id: string,
username: string,
profile: {
displayName?: string,
profilePicture?: string
}
}
}>,
lastMessage?: {
id: string,
content: string,
createdAt: Date,
sender: {
id: string,
username: string,
profile: {
displayName?: string
}
}
},
unreadCount: number,
unreadMentionCount: number
}>Description: Create new conversation (DM or Group) Authentication: Required Input Schema:
{
type: "DM" | "GROUP",
name?: string, // Required for GROUP
memberIds: string[] // Usernames
}Response:
{
id: string,
type: "DM" | "GROUP",
name?: string,
createdAt: Date,
updatedAt: Date,
members: Array<{
id: string,
userId: string,
role: "ADMIN" | "MEMBER",
user: {
id: string,
username: string,
profile: {
displayName?: string,
profilePicture?: string
}
}
}>
}Error Codes: BAD_REQUEST (invalid input, members not found)
Description: Get specific conversation details Authentication: Required Input Schema:
{
conversationId: string
}Response:
{
id: string,
type: "DM" | "GROUP",
name?: string,
createdAt: Date,
updatedAt: Date,
members: Array<{
id: string,
userId: string,
role: "ADMIN" | "MEMBER",
user: {
id: string,
username: string,
profile: {
displayName?: string,
profilePicture?: string
}
}
}>
}Error Codes: NOT_FOUND (conversation not found or access denied)
Description: Get messages from a conversation with pagination Authentication: Required Input Schema:
{
conversationId: string,
cursor?: string, // ISO date string for pagination
limit?: number // 1-100, default 50
}Response:
{
messages: Array<{
id: string,
content: string,
senderId: string,
conversationId: string,
createdAt: Date,
sender: {
id: string,
username: string,
profile: {
displayName?: string,
profilePicture?: string
}
},
mentions: Array<{
user: {
id: string,
username: string,
profile: {
displayName?: string
}
}
}>,
mentionsMe: boolean
}>,
nextCursor?: string
}Error Codes: FORBIDDEN (not a member)
Description: Send a new message to conversation Authentication: Required Input Schema:
{
conversationId: string,
content: string, // 1-4000 chars
mentionedUserIds?: string[] // User IDs to mention
}Response:
{
id: string,
content: string,
senderId: string,
conversationId: string,
createdAt: Date,
sender: {
id: string,
username: string,
profile: {
displayName?: string,
profilePicture?: string
}
},
mentionedUserIds: string[]
}Real-time Events: Broadcasts new-message to conversation-{id} channel
Error Codes: FORBIDDEN, BAD_REQUEST
Description: Update an existing message Authentication: Required (sender only) Input Schema:
{
messageId: string,
content: string, // 1-4000 chars
mentionedUserIds?: string[]
}Response:
{
id: string,
content: string,
senderId: string,
conversationId: string,
createdAt: Date,
sender: {
id: string,
username: string,
profile: {
displayName?: string,
profilePicture?: string
}
},
mentionedUserIds: string[]
}Real-time Events: Broadcasts message-updated to conversation-{id} channel
Error Codes: NOT_FOUND, FORBIDDEN, BAD_REQUEST
Description: Delete a message Authentication: Required (sender only) Input Schema:
{
messageId: string
}Response:
{
success: boolean,
messageId: string
}Real-time Events: Broadcasts message-deleted to conversation-{id} channel
Error Codes: NOT_FOUND, FORBIDDEN
Description: Mark conversation as read (update lastViewedAt) Authentication: Required Input Schema:
{
conversationId: string
}Response:
{
success: boolean
}Real-time Events: Broadcasts conversation-viewed to conversation-{id} channel
Error Codes: FORBIDDEN
Description: Mark mentions as read (update lastViewedMentionAt) Authentication: Required Input Schema:
{
conversationId: string
}Response:
{
success: boolean
}Real-time Events: Broadcasts mentions-viewed to conversation-{id} channel
Error Codes: FORBIDDEN
Description: Get unread message and mention counts for conversation Authentication: Required Input Schema:
{
conversationId: string
}Response:
{
unreadCount: number,
unreadMentionCount: number
}Error Codes: FORBIDDEN
conversation-{conversationId}: All conversation members
new-message: New message sentmessage-updated: Message editedmessage-deleted: Message deletedconversation-viewed: User viewed conversationmentions-viewed: User viewed mentions
BAD_REQUEST(400): Invalid input dataUNAUTHORIZED(401): Authentication required/failedFORBIDDEN(403): Access deniedNOT_FOUND(404): Resource not foundCONFLICT(409): Resource already existsINTERNAL_SERVER_ERROR(500): Server error
{
error: {
code: string,
message: string,
data?: {
zodError?: object, // Validation errors
prismaError?: object // Database errors
}
}
}- Register:
POST /trpc/auth.register→ Returns user info - Login:
POST /trpc/auth.login→ Returns session token - Use Token: Include
Authorization: Bearer {token}in headers - Verify:
GET /trpc/auth.check→ Verify session and get user profile - Logout:
POST /trpc/auth.logout→ End session
- User: Authentication and profile data
- Session: User sessions and verification tokens
- UserProfile: Extended user information
- Conversation: Chat conversations (DM/Group)
- ConversationMember: User membership in conversations
- Message: Chat messages
- Mention: User mentions in messages
- Session-based authentication
- Email verification system
- Real-time messaging with Pusher
- Mention system with read tracking
- Unread message/mention counting
- Conversation member roles (ADMIN/MEMBER)
DATABASE_URL: PostgreSQL connection stringPUSHER_APP_ID,PUSHER_KEY,PUSHER_SECRET,PUSHER_CLUSTER: Pusher configNEXT_PUBLIC_APP_URL: Frontend URL for CORSPORT: Server port (default: 3001)
npm run dev: Development with hot reloadnpm run build: Build TypeScriptnpm start: Production servernpm run generate: Generate Prisma clientnpm run seed: Seed database