Frontend Guide

STORM DAY frontend is built with Vue 3 Composition API, TypeScript, Pinia for state management, and Nuxt UI components. The architecture follows Atomic Design principles.

Routes

PathViewAuth
/loginLoginView.vueGuest only
/registerRegisterView.vueGuest only
/chatChatView.vueRequired

Pinia Stores

authStore

Manages authentication state, persisted in localStorage.

src/stores/auth.ts
// src/stores/auth.ts
interface AuthState {
  accessToken: string | null
  refreshToken: string | null
  user: {
    id: string
    username: string
    display_name: string
    email: string
    avatar_url?: string
  } | null
}

// Actions
login(email: string, password: string): Promise<void>
register(data: RegisterData): Promise<void>
logout(): void
refresh(): Promise<void>
updateProfile(displayName: string): Promise<void>
updatePassword(currentPassword: string, newPassword: string): Promise<void>

chatStore

Manages conversations, messages, members, and WebSocket connection.

src/stores/chat.ts
// src/stores/chat.ts
interface ChatState {
  conversations: Conversation[]
  messagesByConversation: Record<string, Message[]>
  membersByConversation: Record<string, ChatUser[]>
  activeConversationId: string | null
  typingUsers: Record<string, TypingUser[]>
}

// Getters
activeConversation: Conversation | null
activeMessages: Message[]
activeMembers: ChatUser[]
activeTypingUsers: TypingUser[]
membersLabel: string
systemMessage: string | null

// Actions
fetchConversations(): Promise<void>
selectConversation(id: string): Promise<void>
createConversation(memberIds: string[], name?: string): Promise<void>
deleteConversation(id: string): Promise<void>
sendMessage(content: string, options?: MessageOptions): Promise<void>
editMessage(messageId: string, content: string): Promise<void>
emitTyping(): void
initWebSocket(): void
destroyWebSocket(): void

Component Structure

Components follow Atomic Design methodology:

src/components/
├── atoms/
│   ├── BaseAvatar.vue
│   ├── IconGhostButton.vue
│   ├── LoadingText.vue
│   ├── MessageStatusBadge.vue
│   ├── SystemMessageText.vue
│   └── BackgroundCanvas.vue
│
├── molecules/
│   ├── MessageBubble.vue
│   ├── ChatComposer.vue
│   ├── ConversationItem.vue
│   ├── DateDivider.vue
│   ├── MessageReplyQuote.vue
│   ├── MessageForwardQuote.vue
│   ├── MessageOptionsMenu.vue
│   ├── MessageSeenByAvatars.vue
│   ├── ReplyPreviewBanner.vue
│   ├── TypingIndicator.vue
│   ├── ForwardConversationPicker.vue
│   └── UserPickerItem.vue
│
├── organisms/
│   ├── ChatSidebar.vue
│   ├── ChatThread.vue
│   ├── ChatMembersRail.vue
│   ├── CreateConversationPanel.vue
│   ├── AccountSettingsModal.vue
│   ├── ConversationInfoPanel.vue
│   └── UserProfileModal.vue
│
├── templates/
│   ├── AuthLayoutTemplate.vue
│   └── ChatLayoutTemplate.vue
│
└── views/
    ├── LoginView.vue
    ├── RegisterView.vue
    └── ChatView.vue

Key UI Features

Dark/Light Theme

CSS variable based theming with toggle support

GSAP Animations

Fade in/out transitions between conversations and chat header animations

WebGL Background

Custom GLSL shaders with noise-based animated canvas on auth pages

Optimistic UI

Messages appear instantly with status: sending → sent → delivered → seen

Reply & Forward

Reply to messages with preview banner, forward to other conversations

Message Editing

Edit own messages within 2-minute window

Typing Indicator

Animated dots when remote users are typing

Seen Avatars

Avatar stack below last seen message in group chats

Media Upload

Attach files via composer with drag-and-drop support

Mobile Responsive

Sidebar hidden on mobile with back button in chat header

Message Features

Optimistic Send

Messages are assigned a temporary UUID and displayed immediately. The UUID is replaced with the server-generated ID on API response.

Reply Quotes

Click reply on a message to show a preview banner in the composer. The reply_to_id is sent with the message.

Forward Quotes

Click forward to open the ForwardConversationPicker modal and forward the message to another conversation.

Typing Indicator

Shows animated dots when remote users are typing. Auto-clears after 3 seconds of inactivity.

Delivery & Seen Receipts

Message status badge updates in real-time. Seen avatars stack below the last seen message in groups.

Background Resync

Silent background resync every 350ms after WebSocket events to ensure consistency.