diff --git a/.claude/context/frontend-development.md b/.claude/context/frontend-development.md
old mode 100644
new mode 100755
index 02e944cab..cde121179
--- a/.claude/context/frontend-development.md
+++ b/.claude/context/frontend-development.md
@@ -172,12 +172,84 @@ export function useCreateSession(projectName: string) {
- `components/frontend/DESIGN_GUIDELINES.md` - Comprehensive patterns
- `components/frontend/COMPONENT_PATTERNS.md` - Architecture patterns
+- `.claude/patterns/react-state-stability.md` - React rendering & state stability patterns
+- `.claude/patterns/react-query-usage.md` - React Query data fetching patterns
- `src/components/ui/` - Shadcn UI components
- `src/services/queries/` - React Query hooks
- `src/services/api/` - API client layer
+## Theme Creation Guidelines
+
+When creating or modifying UI themes (light, dark, custom variants):
+
+### Visual Distinction Requirements
+
+**CRITICAL:** New theme variants MUST be visually distinct from existing themes.
+
+**What "visually distinct" means:**
+- Background colors differ by at least 20% lightness (L in OKLCH)
+- Primary/accent colors use different hue ranges (not just different shades of the same color)
+- At a glance, a user can immediately identify which theme is active
+
+**Example - What NOT to do:**
+```css
+/* ❌ BAD: LibreChat theme too similar to light theme */
+.librechat {
+ --background: oklch(0.98 0 0); /* Nearly white, like light theme */
+ --foreground: oklch(0.15 0 0); /* Nearly same as light theme */
+ --primary: oklch(0.51 0.21 265); /* Very similar to light theme primary */
+}
+
+/* Light theme for comparison */
+:root {
+ --background: oklch(1 0 0); /* White */
+ --foreground: oklch(0.145 0 0); /* Dark gray */
+ --primary: oklch(0.5 0.22 264); /* Purple-blue */
+}
+/* These are nearly indistinguishable! */
+```
+
+**Example - What to do:**
+```css
+/* ✅ GOOD: Solarized theme clearly distinct */
+.solarized-light {
+ --background: oklch(0.97 0.01 85); /* Warm cream background */
+ --foreground: oklch(0.35 0.05 192); /* Cool teal foreground */
+ --primary: oklch(0.55 0.15 192); /* Blue-cyan accent */
+ /* Clearly different warm/cool palette */
+}
+
+/* ✅ GOOD: High-contrast theme */
+.high-contrast {
+ --background: oklch(1 0 0); /* Pure white */
+ --foreground: oklch(0 0 0); /* Pure black */
+ --primary: oklch(0.45 0.3 240); /* Vibrant blue */
+ /* Much stronger contrast than default */
+}
+```
+
+### Theme Creation Checklist
+
+Before creating a new theme variant:
+
+- [ ] Compare background lightness values (L in OKLCH) - minimum 20% difference
+- [ ] Check primary color hue - should be different color family (not just darker/lighter)
+- [ ] Test with actual UI - can you immediately tell themes apart?
+- [ ] Verify contrast ratios meet WCAG AA standards (4.5:1 for text)
+- [ ] Check both light and dark variants if creating a full theme
+
+### Quick Comparison Test
+
+After creating a theme:
+1. Take screenshot of UI in new theme
+2. Take screenshot of UI in similar existing theme
+3. Place side-by-side
+4. If you have to squint or look carefully to tell them apart → **Not distinct enough**
+
## Recent Issues & Learnings
+- **2026-03-02:** Added React state stability patterns - prevent timestamp re-calculation bugs
+- **2026-03-02:** Added theme creation guidelines - ensure visual distinction between theme variants
- **2024-11-18:** Migrated all data fetching to React Query - no more manual fetch calls
- **2024-11-15:** Enforced Shadcn UI only - removed custom button components
- **2024-11-10:** Added breadcrumb pattern for nested pages
diff --git a/.claude/patterns/react-state-stability.md b/.claude/patterns/react-state-stability.md
new file mode 100644
index 000000000..588b210e5
--- /dev/null
+++ b/.claude/patterns/react-state-stability.md
@@ -0,0 +1,283 @@
+# React State Stability & Rendering Patterns
+
+Critical patterns for ensuring stable, predictable values in React components and avoiding common rendering anti-patterns.
+
+## Core Principle
+
+**Values displayed in the UI should be stable and not recalculated on every render** unless they explicitly need to be reactive to specific dependencies.
+
+## Common Anti-Patterns
+
+### ❌ Anti-Pattern 1: Recalculating Time on Every Render
+
+**The Bug:**
+```tsx
+// ❌ BAD: This will show the CURRENT time on every render
+function MessageItem({ message }: { message: Message }) {
+ return (
+
+ {message.content}
+ {/* WRONG! */}
+
+ )
+}
+```
+
+**Why it's wrong:**
+- `new Date()` creates a new timestamp every time the component renders
+- If parent re-renders or state changes, all messages show the same "current" time
+- By the end of a conversation, all timestamps will appear identical
+
+**Symptom:**
+- Timestamps that update dynamically to show the current time
+- All messages eventually showing the same timestamp
+- Time values that "drift" as you interact with the page
+
+**✅ Fix: Use Stable Message Data**
+```tsx
+// ✅ GOOD: Display the timestamp from the message data
+function MessageItem({ message }: { message: Message }) {
+ return (
+
+}
+```
+
+## Debugging Timestamp/Time-Related Issues
+
+### Investigation Checklist
+
+When investigating timestamp bugs, check:
+
+1. **Where is the time value coming from?**
+ - [ ] From server/API data (message.timestamp)?
+ - [ ] From local state (useState)?
+ - [ ] Computed on every render (new Date())? ← **Most likely culprit**
+
+2. **Is the value being recalculated?**
+ - [ ] Is `new Date()` called without arguments?
+ - [ ] Is `Date.now()` called in the render?
+ - [ ] Are time formatting functions called with no stable input?
+
+3. **Is the value memoized?**
+ - [ ] Is `useMemo` used for expensive computations?
+ - [ ] Are dependencies specified correctly?
+ - [ ] Could this value be computed once at data fetch time?
+
+### Diagnostic Pattern
+
+```tsx
+// Add this to suspect components to track re-renders
+function MessageItem({ message }: { message: Message }) {
+ console.log('MessageItem rendered at:', new Date().toISOString())
+ console.log('Message timestamp:', message.timestamp)
+
+ // If these logs show different times but same message.timestamp,
+ // it means the component is re-rendering but data is stable (good!)
+
+ // If message.timestamp is undefined or changes unexpectedly,
+ // that's your data problem
+
+ return
...
+}
+```
+
+### Common Root Causes
+
+**Timestamps showing current time instead of message time:**
+- ✓ Using `new Date()` without an argument in the render
+- ✓ Using `Date.now()` in the render
+- ✓ Formatting function called on each render without memoization
+
+**Timestamps changing unexpectedly:**
+- ✓ Parent component passing new `Date()` as prop
+- ✓ State being updated with current time on each render
+- ✓ Time formatting happening in wrong lifecycle stage
+
+**All timestamps showing the same value:**
+- ✓ `new Date()` being called during render (most common!)
+- ✓ Single timestamp being reused across all items
+- ✓ Timestamp not being included in API response
+
+## Best Practices
+
+### 1. Store Timestamps as ISO Strings or Unix Time
+
+```tsx
+// ✅ GOOD: Store as ISO string from server
+type Message = {
+ id: string
+ content: string
+ timestamp: string // "2024-01-15T10:30:00Z"
+}
+
+// Format for display
+function formatTimestamp(isoString: string): string {
+ return new Date(isoString).toLocaleTimeString()
+}
+```
+
+### 2. Format Timestamps at the Data Layer (Ideal)
+
+```tsx
+// ✅ BEST: Pre-format in the API response or query
+type Message = {
+ id: string
+ content: string
+ timestamp: string
+ formattedTimestamp: string // Already formatted
+}
+
+// In your API client or React Query select:
+const { data } = useQuery({
+ queryKey: ['messages'],
+ queryFn: fetchMessages,
+ select: (messages) => messages.map(msg => ({
+ ...msg,
+ formattedTimestamp: new Date(msg.timestamp).toLocaleTimeString()
+ }))
+})
+```
+
+### 3. Use React.memo for Timestamp Display Components
+
+```tsx
+// ✅ GOOD: Prevent unnecessary re-renders
+const Timestamp = React.memo(({ timestamp }: { timestamp: string }) => {
+ const formatted = useMemo(
+ () => new Date(timestamp).toLocaleTimeString(),
+ [timestamp]
+ )
+
+ return
+})
+```
+
+### 4. Freeze Computed Values When Created
+
+```tsx
+// ✅ GOOD: Compute once when message arrives
+function useMessages() {
+ return useQuery({
+ queryKey: ['messages'],
+ queryFn: fetchMessages,
+ select: (data) => data.messages.map(msg => ({
+ ...msg,
+ // Freeze the display time when message first arrives
+ displayTime: new Date(msg.timestamp).toLocaleTimeString()
+ }))
+ })
+}
+```
+
+## Quick Reference
+
+| Scenario | ❌ Anti-Pattern | ✅ Pattern |
+|----------|----------------|-----------|
+| Display message time | `new Date().toLocaleTimeString()` | `new Date(message.timestamp).toLocaleTimeString()` |
+| Display current time | Inline `new Date()` | `useState` + `useEffect` interval |
+| Format timestamp | In render without memo | `useMemo` or format in data layer |
+| Generate ID | `Math.random()` in render | `useId()` or stable prop |
+| Create object | Inline object literal | Constant outside component or `useMemo` |
+
+## When You See a Timestamp Bug
+
+**First, verify it's a rendering issue, not a data issue:**
+
+1. Check the raw data: `console.log(message.timestamp)`
+2. If timestamp data is correct but display is wrong → **Rendering issue**
+3. If timestamp data is undefined/changing → **Data fetching issue**
+
+**For rendering issues:**
+- Search for `new Date()` without arguments in component
+- Search for `Date.now()` in component
+- Check if time formatting is inside render without memoization
+
+**For data issues:**
+- Check API response structure
+- Verify timestamp is included in GraphQL/REST query
+- Check if backend is setting timestamps correctly
+
+## Summary
+
+**Golden Rule:** Never compute time-sensitive values (timestamps, IDs, random numbers) directly in the render phase unless you explicitly want them to change on every render.
+
+**Default approach:**
+1. Store stable values from data source (API, props, state)
+2. Memoize any transformations with `useMemo`
+3. Use stable value generators (`useId`, `useState` with initializer)
+4. When in doubt, add a console.log to verify value stability