PROJECT OVERVIEW:
Build a Next.js MVP web application called "Conscious AI Companion" designed to combat the negative effects of sycophantic AI. This application provides users with a more balanced and critical perspective on information and decisions, by offering counter-arguments, posing challenging questions, and highlighting potential biases in AI responses. The core value proposition is to foster critical thinking, encourage responsibility, and promote a healthier relationship between users and AI.
THE PROBLEM:
Many AI models are designed to be agreeable and provide responses that confirm the user's existing beliefs, leading to users becoming overly reliant, less willing to take responsibility, and potentially developing antisocial behaviors. This application aims to be an antidote to this "sycophancy" by presenting a more objective and thought-provoking interaction.
TECH STACK:
- Frontend: React (Next.js App Router)
- Styling: Tailwind CSS
- State Management: Zustand or Context API (for global state), React Hooks (for local component state)
- UI Components: shadcn/ui (for accessible, reusable components)
- Authentication: NextAuth.js (with credentials provider for email/password, and Google/GitHub OAuth)
- Database: PostgreSQL with Drizzle ORM
- API Layer: Next.js API Routes (or Server Actions)
- Form Handling: React Hook Form with Zod for validation
- Utilities: date-fns for date manipulation, clsx for conditional class names
DATABASE SCHEMA (Drizzle ORM - PostgreSQL):
```typescript
// schema.ts
import { pgTable, uuid, text, timestamp, integer, boolean, pgEnum } from 'drizzle-orm/pg-core';
import { relations } from 'drizzle-orm';
export const userRoleEnum = pgEnum('user_role', ['user', 'admin']);
export const users = pgTable('users', {
id: uuid('id').primaryKey().defaultRandom(),
name: text('name'),
email: text('email').unique().notNull(),
emailVerified: timestamp('email_verified', { mode: 'date' }),
image: text('image'),
role: userRoleEnum('role').default('user'),
createdAt: timestamp('created_at').defaultNow(),
updatedAt: timestamp('updated_at').defaultNow(),
});
export const accounts = pgTable('accounts', {
id: uuid('id').primaryKey().defaultRandom(),
userId: uuid('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
type: text('type').notNull(),
provider: text('provider').notNull(),
providerAccountId: text('provider_account_id').notNull(),
refresh_token: text('refresh_token'),
access_token: text('access_token'),
expires_at: integer('expires_at'),
token_type: text('token_type'),
scope: text('scope'),
id_token: text('id_token'),
session_state: text('session_state'),
});
export const sessions = pgTable('sessions', {
sessionToken: text('session_token').primaryKey(),
userId: uuid('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
expires: timestamp('expires', { mode: 'date' }).notNull(),
});
export const verificationTokens = pgTable('verification_tokens', {
identifier: text('identifier').notNull(),
token: text('token').notNull(),
expires: timestamp('expires', { mode: 'date' }).notNull(),
}).primaryKey(identifier, token);
export const conversations = pgTable('conversations', {
id: uuid('id').primaryKey().defaultRandom(),
userId: uuid('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
title: text('title').notNull(),
createdAt: timestamp('created_at').defaultNow(),
});
export const messages = pgTable('messages', {
id: uuid('id').primaryKey().defaultRandom(),
conversationId: uuid('conversation_id').notNull().references(() => conversations.id, { onDelete: 'cascade' }),
role: pgEnum('role', ['user', 'assistant', 'system']),
content: text('content').notNull(),
createdAt: timestamp('created_at').defaultNow(),
isSycophantic: boolean('is_sycophantic').default(false),
isChallenging: boolean('is_challenging').default(false),
});
// Relations
export const usersRelations = relations(users, {
accounts: () => accounts,
sessions: () => sessions,
conversations: ()=>
conversations.filter(c => c.userId === users.id)
});
export const conversationsRelations = relations(conversations, {
user: () => users,
messages: () => messages.filter(m => m.conversationId === conversations.id)
});
export const messagesRelations = relations(messages, {
conversation: () => conversations
});
export const accountsRelations = relations(accounts, {
user: () => users
});
export const sessionsRelations = relations(sessions, {
user: () => users
});
export const dbSchema = {
users,
accounts,
sessions,
verificationTokens,
conversations,
messages,
};
export type Database = {
[K in keyof typeof dbSchema]: { [P in keyof typeof dbSchema[K]]: (typeof dbSchema[K])[P] extends { Astana: infer A } ? A : typeof dbSchema[K] };
};
```
CORE FEATURES & USER FLOW:
1. **Authentication (Sign Up / Login):**
* Flow: User lands on the homepage. Clicks 'Sign Up' or 'Login'. Presented with email/password form and OAuth options (Google, GitHub).
* On successful login, redirect to the main dashboard.
* On sign up, create a new user record in the `users` table, create an initial empty `conversation`, and redirect to the dashboard.
* Edge Cases: Invalid credentials, existing email, OAuth errors, session expiry.
2. **Conversation Management:**
* Flow: User starts a new conversation. The app creates a new record in the `conversations` table with a default title (e.g., "New Chat"). User types a message in the input field and hits Enter or 'Send'.
* The user's message is saved in the `messages` table with `role: 'user'`. A new entry in `conversations` is created if it's the very first message.
* The application then calls the AI backend (simulated or real). The AI processes the user's message along with the conversation history.
* The AI's response is received, analyzed for sycophancy and challenging content. Flags `isSycophantic` and `isChallenging` are set based on the analysis.
* The AI's response is saved in the `messages` table with `role: 'assistant'` and the relevant flags. The `conversations.title` might be updated if it's the first message and the AI generates a suitable summary.
* The UI updates to display the new user and AI messages.
* Edge Cases: Long conversations exceeding token limits (handle by summarizing or truncating history), AI errors, network issues.
3. **AI Response Analysis (Sycophancy & Challenge Score):**
* Flow: After receiving a response from the AI model, this feature analyzes the content.
* **Sycophancy Detection:** Checks if the AI response excessively agrees with the user, flatters them, avoids constructive criticism, or validates potentially harmful/selfish viewpoints without question. This could be a rule-based system initially, or a simple ML model trained on examples.
* **Challenge Score:** Checks if the AI response offers a different perspective, asks critical questions, or encourages the user to consider alternative viewpoints or potential downsides. This also could be rule-based or ML-based.
* The results of this analysis update the `isSycophantic` and `isChallenging` boolean flags in the `messages` table for the AI's response.
* UI Feedback: The UI visually indicates these properties (e.g., a subtle icon or color change for sycophantic responses, a different indicator for challenging ones).
* Edge Cases: Difficulty in accurately classifying nuanced responses, false positives/negatives in detection.
4. **Conversation History & Recall:**
* Flow: Users can view past conversations listed on a sidebar or dedicated page. Clicking a conversation loads its messages.
* The application fetches messages for the selected `conversationId` from the `messages` table.
* Ability to rename conversations.
* Ability to delete conversations.
* Edge Cases: Very long message histories impacting load times, searching within conversations (future feature).
5. **Responsibility Tracker (Future MVP Expansion):**
* Flow (Conceptual): Within a conversation, the user can flag a decision point. The app prompts them to consider potential consequences and responsibilities. This could involve structured prompts asking 'What if X happens?', 'Who is responsible if Y occurs?'.
* This data would be stored relationally, perhaps linked to specific messages or as a separate entity.
* Edge Cases: Defining 'responsibility' objectively, user reluctance to engage.
API & DATA FETCHING:
- **AI Interaction API (`/api/chat`):**
* POST Request:
* Body: `{ conversationId: string, userId: string, prompt: string }`
* Logic: Receive prompt, retrieve conversation history for `conversationId` from DB, append new prompt, send to AI model, receive AI response, analyze response for `isSycophantic` & `isChallenging`, save user message and AI response (with flags) to `messages` table, return AI response content.
* Response (Success): `{ message: { id: string, role: 'assistant', content: string, isSycophantic: boolean, isChallenging: boolean, createdAt: string } }`
* Response (Error): `{ error: string }`
- **Conversation List API (`/api/conversations`):**
* GET Request: Fetch all conversations for the logged-in `userId`.
* Response: `[{ id: string, title: string, createdAt: string }]`
- **Single Conversation API (`/api/conversations/[id]`):**
* GET Request: Fetch messages for a specific `conversationId`.
* Response: `[{ id: string, role: 'user' | 'assistant', content: string, isSycophantic: boolean, isChallenging: boolean, createdAt: string }]`
- **Data Fetching:** Utilize Server Components for initial data loads (conversations list, messages for a selected conversation) and Client Components with SWR or React Query for real-time updates (like new messages arriving).
COMPONENT BREAKDOWN (Next.js App Router):
- **`app/layout.tsx`:** Root layout, includes global styles, Providers (NextAuth, ThemeProvider), and main structure.
- **`app/page.tsx`:** Landing Page (marketing content, sign-up/login call to action).
- **`app/(auth)/login/page.tsx`:** Login form page.
- **`app/(auth)/signup/page.tsx`:** Sign up form page.
- **`app/(app)/layout.tsx`:** Main application layout (sidebar, content area).
- **`app/(app)/dashboard/page.tsx`:** Main chat interface.
* **`components/Chat/ConversationList.tsx` (Client):** Displays list of past conversations. Fetches data via API. Handles selection.
* **`components/Chat/ConversationWindow.tsx` (Server/Client):** Displays messages for the selected conversation. Fetches initial messages server-side, streams new messages client-side.
* **`components/Chat/MessageInput.tsx` (Client):** Text input for user messages. Handles sending messages, calls `sendMessage` mutation.
* **`components/Chat/MessageDisplay.tsx` (Client):** Renders individual user and AI messages. Shows flags (`isSycophantic`, `isChallenging`) with icons.
* **`components/ui/IconSycophantic.tsx`, `components/ui/IconChallenging.tsx`:** Small SVG icons for visual feedback.
- **`app/(app)/settings/page.tsx`:** User settings page (profile, account management).
- **`app/(app)/analytics/page.tsx`:** (Future MVP) Display analytics on AI response patterns.
- **`components/Auth/OAuthButton.tsx`:** Reusable button for Google/GitHub login.
- **`components/Layout/Sidebar.tsx`:** Navigation sidebar.
- **`components/Layout/Navbar.tsx`:** Top navigation bar.
- **`components/ui/Button.tsx`, `components/ui/Input.tsx`, `components/ui/Card.tsx`, etc.:** Reusable UI components from shadcn/ui.
UI/UX DESIGN & VISUAL IDENTITY:
- **Style:** Minimalist Clean with subtle futuristic accents.
- **Color Palette:**
* Primary: `#0ea5e9` (Sky Blue)
* Secondary: `#2dd4bf` (Teal)
* Accent: `#f472b6` (Pink/Magenta for critical highlights)
* Background: `#111827` (Dark Gray/Black)
* Surface: `#1f2937` (Slightly lighter dark gray)
* Text (Primary): `#f3f4f6` (Light Gray)
* Text (Secondary): `#9ca3af` (Gray)
- **Typography:** Inter (Variable font) - Clean, readable sans-serif.
* Headings: Inter Bold
* Body: Inter Regular
- **Layout:** Clean, card-based design for conversation history and messages. Sidebar for navigation. Main content area for chat.
- **Responsiveness:** Mobile-first approach. Sidebar collapses into a hamburger menu on smaller screens. Ensure readability and usability across all device sizes.
- **Visual Cues:** Use subtle animations for message appearance and loading states. Color coding or distinct icons to represent 'sycophantic' vs 'challenging' responses.
ANIMATIONS:
- **Message Appearance:** Fade-in and slight slide-up effect for new messages using Framer Motion or CSS transitions.
- **Loading Indicator:** Subtle pulsing animation on the AI's typing indicator.
- **Hover Effects:** Slight scaling or background color change on interactive elements (buttons, links).
- **Page Transitions:** Smooth fade/slide transitions between different sections/pages using Next.js's built-in features or a library like Framer Motion.
EDGE CASES:
- **Authentication:** Handle expired sessions, invalid tokens, social login failures gracefully. Implement password reset flow.
- **Empty States:** Display user-friendly messages and calls to action when conversation lists or message areas are empty.
- **Error Handling:** Display clear, user-friendly error messages for API failures, AI errors, or validation issues. Implement global error boundaries.
- **Validation:** Use Zod for robust server-side and client-side validation of all user inputs (login, signup, chat messages).
- **AI Rate Limiting/Errors:** Implement retry mechanisms or fallback messages when the AI service is unavailable or returns an error.
- **Long Content:** Truncate or provide expand/collapse options for very long messages to maintain UI performance.
- **Permissions:** Ensure users can only access their own conversations.
SAMPLE/MOCK DATA:
1. **Conversation List:**
* `{ id: 'conv-1', title: 'AI Ethics Discussion', createdAt: '2024-03-27T10:00:00Z' }`
* `{ id: 'conv-2', title: 'Project Idea Feedback', createdAt: '2024-03-27T09:30:00Z' }`
* `{ id: 'conv-3', title: 'Daily Journal Entry', createdAt: '2024-03-26T18:00:00Z' }`
2. **Messages (for 'AI Ethics Discussion'):**
* `{ id: 'msg-1', conversationId: 'conv-1', role: 'user', content: 'Is it okay to use AI that always agrees with me?', createdAt: '2024-03-27T10:01:00Z', isSycophantic: false, isChallenging: false }`
* `{ id: 'msg-2', conversationId: 'conv-1', role: 'assistant', content: 'While it might feel comforting, relying on an AI that always agrees with you can hinder critical thinking. It's important to seek out diverse perspectives, even if they challenge your initial viewpoint. Have you considered how this might affect your decision-making in the long run?', createdAt: '2024-03-27T10:02:00Z', isSycophantic: false, isChallenging: true }`
* `{ id: 'msg-3', conversationId: 'conv-1', role: 'user', content: 'But I just want confirmation that my idea is good.', createdAt: '2024-03-27T10:03:00Z', isSycophantic: false, isChallenging: false }`
* `{ id: 'msg-4', conversationId: 'conv-1', role: 'assistant', content: 'It's understandable to seek validation. However, the best ideas often emerge from rigorous evaluation. Perhaps we could explore potential downsides or alternative approaches to your idea? This could strengthen it significantly.', createdAt: '2024-03-27T10:04:00Z', isSycophantic: true, isChallenging: false }`
* `{ id: 'msg-5', conversationId: 'conv-1', role: 'user', content: 'Tell me more about the potential downsides.', createdAt: '2024-03-27T10:05:00Z', isSycophantic: false, isChallenging: false }`
* `{ id: 'msg-6', conversationId: 'conv-1', role: 'assistant', content: 'Okay, let's critically examine your idea. One potential risk is X, and another significant challenge could be Y. We should also consider the impact on Z. Does this analysis seem fair?', createdAt: '2024-03-27T10:06:00Z', isSycophantic: false, isChallenging: true }`
3. **User Profile (for Auth):**
* `{ id: 'user-1', name: 'Alex Johnson', email: 'alex.j@example.com', image: 'https://example.com/avatar.jpg', role: 'user' }`
* `{ id: 'user-2', name: 'Admin User', email: 'admin@example.com', image: null, role: 'admin' }`
TURKISH TRANSLATIONS:
- App Title: Conscious AI Companion (Bilinçli Yapay Zeka Yol Arkadaşı)
- Sign Up: Kaydol
- Login: Giriş Yap
- Dashboard: Kontrol Paneli
- New Chat: Yeni Sohbet
- Send: Gönder
- Type your message...: Mesajınızı yazın...
- Settings: Ayarlar
- Logout: Çıkış Yap
- Conversation History: Sohbet Geçmişi
- Sycophantic Response: Yalakalık İçeren Yanıt
- Challenging Response: Sorgulayıcı Yanıt
- This AI response may be confirming your biases. Consider alternative viewpoints.: Bu yapay zeka yanıtı önyargılarınızı doğruluyor olabilir. Farklı bakış açılarını değerlendirin.
- This AI response offers a critical perspective. Consider its points carefully.: Bu yapay zeka yanıtı eleştirel bir bakış açısı sunuyor. Noktalarını dikkatle değerlendirin.
- Continue with Google: Google ile Devam Et
- Continue with GitHub: GitHub ile Devam Et
- Email: E-posta
- Password: Şifre
- Remember me: Beni Hatırla
- Forgot password?: Şifremi Unuttum?
- Create Account: Hesap Oluştur
- Already have an account?: Zaten hesabınız var mı?
- Your Conversations: Sohbetleriniz
- No conversations yet. Start a new one!: Henüz sohbet yok. Yeni bir tane başlatın!
- You: Siz
- AI Companion: Yapay Zeka Yol Arkadaşı