PROJECT OVERVIEW:
Generate a fully functional, multi-page Next.js MVP application for a novel version control system named 'Manyana'. Manyana leverages CRDTs to provide a superior conflict resolution experience compared to traditional VCS. The core value proposition is to transform complex, opaque merge conflicts into clear, actionable, and visually informative 'conflict markers', significantly improving developer productivity and collaboration. The app will allow users to connect their existing Git repositories and visualize/resolve conflicts with unprecedented clarity.
TECH STACK:
- Frontend Framework: React with Next.js (App Router)
- Styling: Tailwind CSS
- ORM: Drizzle ORM with PostgreSQL (or other compatible DB like Neon/Turso via Drizzle)
- UI Component Library: shadcn/ui
- Authentication: NextAuth.js (for OAuth with GitHub, GitLab)
- State Management: React Context API / Zustand (for global state, if needed)
- Form Handling: React Hook Form with Zod for validation
- Version Control Integration: Utilize a robust Git client library (e.g., isomorphic-git) for frontend operations where feasible, and communicate with a backend service for complex Git operations or synchronization.
- CRDT Library: Integrate a suitable CRDT library (e.g., Yjs, Automerge) if implementing pure CRDT logic, or focus on a sophisticated diff/merge visualization layer on top of Git.
- Deployment: Vercel
DATABASE SCHEMA (Drizzle ORM for PostgreSQL):
```sql
table('users', {
id: uuid()
.primaryKey()
.notNull(),
name: text('name'),
email: text('email')
.unique()
.notNull(),
emailVerified: timestamp('emailVerified', { mode: 'date' }),
image: text('image'),
createdAt: timestamp('createdAt', { mode: 'date' }).default(sql`now()`).notNull(),
updatedAt: timestamp('updatedAt', { mode: 'date' }).default(sql`now()`).notNull(),
});
table('accounts', {
provider: text('provider').notNull(),
type: text('type').notNull(),
providerAccountId: text('providerAccountId').notNull(),
userId: uuid()
.notNull()
.references(() => users.id, {
onDelete: 'cascade',
}),
access_token: text('access_token'),
refresh_token: text('refresh_token'),
expires_at: bigint('expires_at'),
token_type: text('token_type'),
scope: text('scope'),
id_token: text('id_token'),
session_state: text('session_state'),
}).primaryKey(sql`("provider", "providerAccountId")`);
table('sessions', {
sessionToken: text('sessionToken').primaryKey().notNull(),
userId: uuid()
.notNull()
.references(() => users.id, {
onDelete: 'cascade',
}),
expires: timestamp('expires', { mode: 'date' }).notNull(),
});
table('verificationTokens', {
identifier: text('identifier').notNull(),
token: text('token').notNull(),
expires: timestamp('expires', { mode: 'date' }).notNull(),
}).primaryKey(sql`("identifier", "token")`);
table('repositories', {
id: uuid()
.primaryKey()
.notNull(),
userId: uuid()
.notNull()
.references(() => users.id, {
onDelete: 'cascade',
}),
name: text('name').notNull(),
gitUrl: text('gitUrl').notNull(),
createdAt: timestamp('createdAt', { mode: 'date' }).default(sql`now()`).notNull(),
updatedAt: timestamp('updatedAt', { mode: 'date' }).default(sql`now()`).notNull(),
});
table('commits', {
id: uuid()
.primaryKey()
.notNull(),
repositoryId: uuid()
.notNull()
.references(() => repositories.id, {
onDelete: 'cascade',
}),
hash: text('hash').notNull(),
message: text('message'),
authorName: text('authorName'),
authorEmail: text('authorEmail'),
date: timestamp('date', { mode: 'date' }).notNull(),
createdAt: timestamp('createdAt', { mode: 'date' }).default(sql`now()`).notNull(),
});
table('conflictMarkers', {
id: uuid()
.primaryKey()
.notNull(),
commitId: uuid()
.notNull()
.references(() => commits.id, {
onDelete: 'cascade',
}),
filePath: text('filePath').notNull(),
markerType: text('markerType').notNull(), // e.g., 'deleted_left', 'added_right', 'modified_both'
content: text('content'), // The snippet of code or text related to the marker
position: integer('position'), // Line number or character offset
createdAt: timestamp('createdAt', { mode: 'date' }).default(sql`now()`).notNull(),
});
```
CORE FEATURES & USER FLOW:
1. **Authentication Flow:**
* User lands on the homepage.
* Clicks 'Sign In / Sign Up' button.
* Presented with OAuth options (GitHub, GitLab).
* User selects provider, redirects to provider's auth page.
* User authorizes Manyana.
* User is redirected back to the app, logged in.
* User's profile and connected accounts are stored/updated in the `users` and `accounts` tables.
2. **Repository Connection:**
* After login, user navigates to a 'Repositories' page.
* Clicks 'Connect Repository' button.
* Enters the Git URL of their repository.
* The backend attempts to clone/fetch the repository (using provided credentials/token).
* If successful, the repository details are saved in the `repositories` table, linked to the user.
* The application triggers a background job to fetch initial commit history and analyze for conflicts.
3. **Conflict Detection and Visualization:**
* Backend service (or frontend with isomorphic-git) processes the repository history.
* Identifies merge commits and associated file changes.
* Compares changes between branches leading to the merge. Utilizes a diffing algorithm to detect overlapping modifications.
* For each conflict, it generates structured data representing the conflicting segments (e.g., the deleted function, the added line, the modified section). This data populates the `conflictMarkers` table.
* Frontend fetches conflict data for a selected commit/merge.
* The 'Conflict Resolution' page displays the file content with custom markers:
* `<<<<<<< begin deleted left`
* `def calculate(x):
a = x * 2`
* `======= begin added right`
* `logger.debug(f"a={a}")`
* `======= begin deleted left`
* `b = a + 1
return b`
* `>>>>>>> end conflict`
* Each marker is styled distinctly (color, icon) to indicate its type and origin (left/right branch). Hovering over a marker shows author, commit message snippet, and exact change.
4. **Interactive Conflict Resolution:**
* On the Conflict Resolution page, for each conflict block:
* Buttons like 'Keep Left', 'Keep Right', 'Edit Manually' are presented.
* User clicks a button.
* The UI updates the file content based on the user's choice. For 'Keep Left/Right', the corresponding conflicting code is applied, and the other is discarded. 'Edit Manually' opens a simple inline editor.
* Once all conflicts in a file are resolved, the user clicks 'Accept Resolution'.
* The application generates a new commit resolving the conflict (potentially using `git merge --continue` conceptually or by applying changes and creating a new commit).
* (MVP Limitation: This will initially be a visualization and manual application of changes, not a direct Git commit. Later versions could integrate more deeply).
API & DATA FETCHING (Next.js App Router Example):
- **`POST /api/repositories`**: Connect a new repository.
* Request Body: `{ "gitUrl": "..." }`
* Response: `201 Created` with repository details or `400 Bad Request`.
- **`GET /api/repositories`**: Fetch list of connected repositories for the logged-in user.
* Response: `200 OK` with `[{ "id": "...", "name": "...", "gitUrl": "..." }]`.
- **`GET /api/repositories/[repoId]/conflicts`**: Fetch commits with conflicts for a specific repository.
* Response: `200 OK` with `[{ "commitHash": "...", "message": "...", "conflicts": [ { "filePath": "...", "markerType": "...", "content": "...", "position": ... }, ... ] }]`.
- **`GET /api/files?repoId=...&commitHash=...&filePath=...`**: Fetch file content and conflict markers for a specific file in a commit.
* Response: `200 OK` with `{ "content": "...", "markers": [...] }`.
- **`POST /api/resolve-conflict`**: Submit resolution for a conflict.
* Request Body: `{ "repoId": "...", "commitHash": "...", "filePath": "...", "resolvedContent": "..." }`
* Response: `200 OK` indicating success, or `500 Internal Server Error`.
Data Fetching in Components:
- Use server components for initial data loading where possible (e.g., fetching repository list).
- Use client components with `fetch` or libraries like SWR/React Query for dynamic data, form submissions, and real-time updates.
- Pass data down via props or use context for global state.
UI/UX DESIGN & VISUAL IDENTITY:
- **Style:** Modern, Clean, Developer-Focused.
- **Color Palette:**
* Primary: `#2563eb` (Blue-600)
* Secondary: `#10b981` (Green-500)
* Accent: `#f59e0b` (Amber-500)
* Background: `#f9fafb` (Light Mode), `#111827` (Dark Mode - Default)
* Text: `#1f2937` (Light Mode), `#e5e7eb` (Dark Mode)
* Conflict Markers:
* Deleted Left: `#dc2626` (Red-600) with subtle striped pattern.
* Added Right: `#10b981` (Green-500) with subtle dotted pattern.
* Modified Both: `#a16207` (Amber-600)
- **Typography:** Inter, Roboto Mono (for code snippets).
- **Layout:**
* Sidebar Navigation (Repositories, Settings, etc.).
* Main content area displaying files, diffs, and conflict resolution interfaces.
* Use `max-width` and centering for main content readability.
* Clear visual hierarchy using spacing, font weights, and subtle borders.
- **Responsive Rules:** Mobile-first approach. Sidebar collapses into a hamburger menu on smaller screens. Content areas adjust fluidly. Code views should allow horizontal scrolling.
- **Visual Elements:** Subtle use of gradients in buttons or headers. Clean icons from lucide-react or similar.
COMPONENT BREAKDOWN (Next.js App Router Structure):
- **`app/layout.tsx`**: Root layout (HTML, Head, Body, global providers, Tailwind CSS setup).
- **`app/page.tsx`**: Landing Page (Marketing content, value proposition, CTA).
- **`app/auth/signin/page.tsx`**: Sign-in page with OAuth buttons.
- **`app/(app)/dashboard/page.tsx`**: Main dashboard after login. Overview of connected repositories.
- **`app/(app)/repositories/page.tsx`**: List of connected repositories. Button to connect new ones.
- **`app/(app)/repositories/[repoId]/page.tsx`**: Repository detail page. Shows commits, branches, files list.
- **`app/(app)/repositories/[repoId]/commits/[commitHash]/page.tsx`**: Commit detail page. Shows file changes in the commit.
- **`app/(app)/repositories/[repoId]/conflicts/page.tsx`**: The core Conflict Resolution interface.
* Displays file list with conflict indicators.
* Select a file to view the conflict diff.
* Renders the custom conflict markers.
* Includes interactive resolution controls (buttons, inline editor).
- **`app/(app)/settings/page.tsx`**: User settings page (Profile, connected accounts).
- **Shared Components (`components/ui/*`)**: Buttons, Modals, Input Fields, Tables, Icons (from shadcn/ui).
- **`components/layout/Sidebar.tsx`**: Navigation sidebar.
- **`components/layout/Navbar.tsx`**: Top navigation bar.
- **`components/code/ConflictDiffViewer.tsx`**: Component to render file content with custom conflict markers.
- **`components/code/ConflictMarker.tsx`**: Individual styled marker component.
- **`components/forms/ConnectRepoForm.tsx`**: Form for connecting repositories.
- **`components/auth/SignInButton.tsx`**: Reusable sign-in buttons.
State Management:
- Local component state for UI elements (e.g., modal visibility, input values).
- React Context or Zustand for global state like user authentication status, repository list, selected repository/commit.
- Server component data fetching handles initial state for pages.
ANIMATIONS:
- **Page Transitions:** Subtle fade-in/out using Next.js `layout.tsx` or a dedicated library.
- **Hover Effects:** Slight scale or background color change on buttons and interactive elements.
- **Loading States:** Spinners or skeleton loaders (`react-loading-skeleton`) for data fetching.
- **Conflict Marker Emphasis:** Slight pulse or border highlight when a conflict marker is hovered or selected.
- **Layout Transitions:** Smooth transitions when sidebar collapses/expands or items are added/removed from lists.
EDGE CASES:
- **Authentication:** Handle expired tokens, re-authentication requirements. Ensure secure token storage.
- **Empty States:** Display informative messages and CTAs when no repositories are connected, no commits exist, or no conflicts are found.
- **Authorization:** Ensure users can only access their own repositories and data.
- **Error Handling:** Graceful error display for API failures, Git operation errors (e.g., invalid URL, network issues), validation errors.
- **Validation:** Use Zod for robust validation of form inputs (repo URL, etc.) and API request bodies.
- **Large Files/Repositories:** Implement strategies for handling large data (pagination, efficient diffing, lazy loading).
- **Git Operation Failures:** Provide clear feedback if backend Git operations fail (e.g., cloning, merging).
SAMPLE DATA:
1. **User:**
```json
{
"id": "uuid-user-1",
"name": "Alice Developer",
"email": "alice@example.com",
"image": "/images/avatars/alice.png"
}
```
2. **Repository:**
```json
{
"id": "uuid-repo-1",
"userId": "uuid-user-1",
"name": "awesome-project",
"gitUrl": "https://github.com/alice/awesome-project.git"
}
```
3. **Commit (with conflicts):**
```json
{
"id": "uuid-commit-1",
"repositoryId": "uuid-repo-1",
"hash": "a1b2c3d4e5f6",
"message": "feat: Implement new user auth flow",
"authorName": "Alice Developer",
"authorEmail": "alice@example.com",
"date": "2023-10-27T10:00:00Z"
}
```
4. **Conflict Marker (Deleted Left):**
```json
{
"id": "uuid-marker-1",
"commitId": "uuid-commit-1",
"filePath": "src/auth.js",
"markerType": "deleted_left",
"content": "function authenticateUser(user, pass) { // Old logic }",
"position": 5
}
```
5. **Conflict Marker (Added Right):**
```json
{
"id": "uuid-marker-2",
"commitId": "uuid-commit-1",
"filePath": "src/auth.js",
"markerType": "added_right",
"content": "// New JWT-based authentication logic",
"position": 10
}
```
6. **Conflict Marker (Modified Both):**
```json
{
"id": "uuid-marker-3",
"commitId": "uuid-commit-1",
"filePath": "src/utils.js",
"markerType": "modified_both",
"content": "// Refactored utility function",
"position": 25
}
```
7. **File Content Snippet (for context):**
```javascript
// ... other code ...
function authenticateUser(user, pass) { // Old logic }
// New JWT-based authentication logic
// ... other code ...
```
8. **Repository List (User Dashboard):**
```json
[
{
"id": "uuid-repo-1",
"name": "awesome-project",
"lastSync": "2023-10-27T11:30:00Z",
"hasConflicts": true
},
{
"id": "uuid-repo-2",
"name": "design-system",
"lastSync": "2023-10-26T09:15:00Z",
"hasConflicts": false
}
]
```
TURKISH TRANSLATIONS:
- Sign In / Sign Up: Giriş Yap / Kayıt Ol
- Connect Repository: Depo Bağla
- Repositories: Depolar
- Settings: Ayarlar
- Dashboard: Pano
- Commits: İşlemeler (Commitler)
- Conflicts: Çakışmalar
- File Path: Dosya Yolu
- Type: Tür
- Content: İçerik
- Position: Konum
- Keep Left: Solu Sakla
- Keep Right: Sağ Sakla
- Edit Manually: Manuel Düzenle
- Accept Resolution: Çözümü Kabul Et
- No Conflicts Found: Çakışma Bulunamadı
- Error Fetching Data: Veri Çekilirken Hata Oluştu
- Connecting...
: Bağlanıyor...
- Pull Request: Çekme İsteği (Pull Request)
- Merge: Birleştir
- Deleted Left: Soldan Silinen
- Added Right: Sağa Eklenen
- Modified Both: İkisi Tarafından Değiştirilen