From 6079f8ca395eab90668e1fcf52cbdafd67b3da1b Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 30 Apr 2026 02:54:14 +0000 Subject: [PATCH 1/4] Add AGENTS.md with Cursor Cloud development instructions Co-authored-by: Cole Collins --- AGENTS.md | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..6e83d89 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,57 @@ +# AGENTS.md + +## Cursor Cloud specific instructions + +### Overview + +CodeVault is an AI-powered code intelligence platform built with **Next.js 16** (App Router), **TypeScript**, **Tailwind CSS v4**, and **Shadcn UI**. It connects to GitHub repos, scans files, and uses AI to discover application blueprints. + +### Package manager + +This project uses **pnpm**. The lockfile is `pnpm-lock.yaml`. + +### Scripts (from `package.json`) + +| Command | Purpose | +|---------|---------| +| `pnpm dev` | Start Next.js dev server (port 3000) | +| `pnpm build` | Production build | +| `pnpm lint` | Run ESLint | +| `pnpm exec tsc --noEmit` | Type check | + +### Lint and type check + +- **Lint**: `pnpm lint` — runs ESLint. The codebase has a few pre-existing lint warnings/errors (unused vars, `prefer-const`, `set-state-in-effect`). These are not regressions. +- **Type check**: `pnpm exec tsc --noEmit` — clean pass. If you see errors referencing `.next/types/validator.ts` or `.next/dev/types/validator.ts`, run `rm -rf .next` first, as stale generated types can cause false failures. + +### No automated test suite + +There is no test framework (jest, vitest, playwright, etc.) configured in this codebase. CI only runs lint + typecheck. + +### Database + +The app uses `@neondatabase/serverless` (Neon's HTTP-based serverless PostgreSQL driver). This driver communicates via HTTP fetch, **not** a standard PostgreSQL socket connection. For local development you have two options: + +1. **Use a real Neon database** (recommended): Set `DATABASE_URL` to a Neon connection string. The schema migration is at `scripts/01-create-schema.sql`, or hit `GET /api/setup/init-db` to initialize the DB via the app. +2. **Use local PostgreSQL with neon-http-proxy**: Run `ghcr.io/timowilhelm/local-neon-http-proxy` Docker container and configure `neonConfig.fetchEndpoint` in the app to point to it. This requires more setup (see the GitHub issue at neondatabase/serverless#33). + +### Environment variables + +Copy `.env.example` to `.env.local`. Required variables: + +- `DATABASE_URL` — Neon PostgreSQL connection string +- `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET` — GitHub OAuth App credentials +- `NEXT_PUBLIC_APP_URL` — App URL (use the local dev server URL) +- `OPENAI_API_KEY` — For AI analysis features +- `ANTHROPIC_API_KEY` — Optional, for scaffold generation + +### Authentication + +The app uses GitHub OAuth. The middleware at `middleware.ts` blocks unauthenticated access to `/dashboard/*` routes by checking `github_user_id` and `github_access_token` cookies. To test dashboard features, you need a working GitHub OAuth App with the callback URL set to `{NEXT_PUBLIC_APP_URL}/api/auth/github/callback`. + +### Key gotchas + +- The landing page (`/`) works without any database or API credentials — it's a static page. +- All dashboard routes require authentication cookies set by the GitHub OAuth flow. +- The `@neondatabase/serverless` driver's `neon()` function uses HTTP fetch (not TCP sockets), so standard `pg` connection strings to local PostgreSQL won't work directly — you need either a Neon database or the HTTP proxy. +- The pnpm install may warn about ignored build scripts for `sharp` and `unrs-resolver`. This is fine and doesn't affect functionality. From 436bcdffe57e5473c660226bf86ad1609f167017 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 30 Apr 2026 04:26:00 +0000 Subject: [PATCH 2/4] Migrate database from Neon to Supabase (postgres.js) - Replace @neondatabase/serverless with postgres (postgres.js) package - Update lib/db.ts to use postgres.js with connection pooling singleton - Update lib/queries.ts with proper typed generics for postgres.js - Update all documentation (README, QUICK_START, VERCEL_SETUP, etc.) - Update .env.example with Supabase connection string format - Update AGENTS.md with new database instructions The postgres.js driver connects via standard TCP sockets, making it compatible with any PostgreSQL database (Supabase, local, etc.) without needing the Neon HTTP proxy. Co-authored-by: Cole Collins --- .env.example | 5 ++- AGENTS.md | 8 +--- ARCHITECTURE.md | 2 +- IMPLEMENTATION_SUMMARY.md | 6 +-- QUICK_START.md | 8 ++-- README.md | 6 +-- VERCEL_SETUP.md | 8 ++-- lib/db.ts | 12 ++++-- lib/queries.ts | 20 +++++----- next-env.d.ts | 2 +- package.json | 2 +- pnpm-lock.yaml | 78 +++---------------------------------- scripts/setup-deployment.sh | 2 +- 13 files changed, 47 insertions(+), 112 deletions(-) diff --git a/.env.example b/.env.example index e25292d..b2874aa 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,6 @@ -# Neon PostgreSQL Database -DATABASE_URL=postgresql://user:password@host/dbname?sslmode=require +# Supabase PostgreSQL Database +# Find your connection string in the Supabase dashboard: Settings → Database → Connection string → URI +DATABASE_URL=postgresql://postgres.[project-ref]:[password]@aws-0-[region].pooler.supabase.com:6543/postgres # GitHub OAuth App # Create at: https://github.com/settings/developers diff --git a/AGENTS.md b/AGENTS.md index 6e83d89..211febe 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -30,16 +30,13 @@ There is no test framework (jest, vitest, playwright, etc.) configured in this c ### Database -The app uses `@neondatabase/serverless` (Neon's HTTP-based serverless PostgreSQL driver). This driver communicates via HTTP fetch, **not** a standard PostgreSQL socket connection. For local development you have two options: - -1. **Use a real Neon database** (recommended): Set `DATABASE_URL` to a Neon connection string. The schema migration is at `scripts/01-create-schema.sql`, or hit `GET /api/setup/init-db` to initialize the DB via the app. -2. **Use local PostgreSQL with neon-http-proxy**: Run `ghcr.io/timowilhelm/local-neon-http-proxy` Docker container and configure `neonConfig.fetchEndpoint` in the app to point to it. This requires more setup (see the GitHub issue at neondatabase/serverless#33). +The app uses `postgres` (postgres.js) to connect to PostgreSQL via standard TCP sockets. Any PostgreSQL-compatible database works (Supabase, local PostgreSQL, etc.). Set `DATABASE_URL` to a valid PostgreSQL connection string. The schema migration is at `scripts/01-create-schema.sql`, or hit `GET /api/setup/init-db` to initialize the DB via the app. ### Environment variables Copy `.env.example` to `.env.local`. Required variables: -- `DATABASE_URL` — Neon PostgreSQL connection string +- `DATABASE_URL` — Supabase (or any PostgreSQL) connection string - `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET` — GitHub OAuth App credentials - `NEXT_PUBLIC_APP_URL` — App URL (use the local dev server URL) - `OPENAI_API_KEY` — For AI analysis features @@ -53,5 +50,4 @@ The app uses GitHub OAuth. The middleware at `middleware.ts` blocks unauthentica - The landing page (`/`) works without any database or API credentials — it's a static page. - All dashboard routes require authentication cookies set by the GitHub OAuth flow. -- The `@neondatabase/serverless` driver's `neon()` function uses HTTP fetch (not TCP sockets), so standard `pg` connection strings to local PostgreSQL won't work directly — you need either a Neon database or the HTTP proxy. - The pnpm install may warn about ignored build scripts for `sharp` and `unrs-resolver`. This is fine and doesn't affect functionality. diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 26b2480..18d92ed 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -48,7 +48,7 @@ ┌──────────────────────────────────────────────────────────────────────┐ │ DATA LAYER │ │ ┌────────────────────────────────────────────────────────────────┐ │ -│ │ Neon PostgreSQL │ │ +│ │ Supabase PostgreSQL │ │ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ │ │ user_auth Table - GitHub OAuth users │ │ │ │ │ │ repositories Table - Tracked GitHub repos │ │ │ diff --git a/IMPLEMENTATION_SUMMARY.md b/IMPLEMENTATION_SUMMARY.md index af3b75f..f835566 100644 --- a/IMPLEMENTATION_SUMMARY.md +++ b/IMPLEMENTATION_SUMMARY.md @@ -2,7 +2,7 @@ ## ✅ Completed Architecture -### 1. Database Layer (Neon PostgreSQL) +### 1. Database Layer (Supabase PostgreSQL) - ✅ `user_auth` — GitHub OAuth user records - ✅ `repositories` — Tracked GitHub repositories - ✅ `repo_files` — Scanned files with AI metadata (JSONB fields) @@ -62,7 +62,7 @@ - UI primitives (Shadcn) /lib - - db.ts - Neon database client + - db.ts - Database client (postgres.js) - queries.ts - All database operations - utils.ts - cn() and other helpers @@ -83,7 +83,7 @@ ## 🔑 Key Technologies - **Framework**: Next.js 16 (App Router) -- **Database**: Neon PostgreSQL (`@neondatabase/serverless`) +- **Database**: Supabase PostgreSQL (`postgres` / postgres.js) - **AI**: Vercel AI SDK + OpenAI GPT-4 - **Auth**: Custom GitHub OAuth - **UI**: Shadcn UI + Tailwind CSS v4 diff --git a/QUICK_START.md b/QUICK_START.md index 2a69f89..828796b 100644 --- a/QUICK_START.md +++ b/QUICK_START.md @@ -3,7 +3,7 @@ ## Prerequisites - Node.js 20+ and pnpm -- A [Neon](https://neon.tech) PostgreSQL database +- A [Supabase](https://supabase.com) project (or any PostgreSQL database) - A GitHub OAuth App (for GitHub integration) - An OpenAI API key (for AI analysis) @@ -26,7 +26,7 @@ cp .env.example .env.local Edit `.env.local` with your values: ``` -DATABASE_URL=postgresql://... # From Neon dashboard +DATABASE_URL=postgresql://... # From Supabase dashboard (Settings → Database) GITHUB_CLIENT_ID=... # From GitHub OAuth App GITHUB_CLIENT_SECRET=... # From GitHub OAuth App NEXT_PUBLIC_APP_URL=http://localhost:3000 @@ -43,7 +43,7 @@ OPENAI_API_KEY=sk-... # From OpenAI dashboard ### 4. Set Up the Database -Run the migration in your Neon SQL Editor or with psql: +Run the migration in your Supabase SQL Editor or with psql: ```bash psql $DATABASE_URL -f scripts/01-create-schema.sql @@ -95,7 +95,7 @@ Navigate to **http://localhost:3000** to see the app. **Database connection error?** - Check `DATABASE_URL` is correct -- Verify your Neon project is active +- Verify your Supabase project is active (or your PostgreSQL server is running) **GitHub OAuth not working?** - Check `GITHUB_CLIENT_ID` and `GITHUB_CLIENT_SECRET` diff --git a/README.md b/README.md index 08d0111..2494a92 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ An AI-powered code intelligence platform that scans your GitHub repositories and ## Tech Stack - **Framework**: Next.js 16 with App Router -- **Database**: Neon PostgreSQL with connection pooling +- **Database**: Supabase PostgreSQL (or any PostgreSQL) - **AI**: Vercel AI SDK (OpenAI GPT-4) - **UI Components**: Shadcn UI with Radix primitives - **Styling**: Tailwind CSS v4 @@ -50,7 +50,7 @@ components/ ├── app-suggestions.tsx # App idea cards └── ui/ # Shadcn components lib/ -├── db.ts # Neon database client +├── db.ts # Database client (postgres.js) ├── queries.ts # Database queries └── utils.ts # Utility functions scripts/ @@ -117,7 +117,7 @@ cp .env.example .env.local ``` 4. **Set up the database** -Run the schema migration in your Neon console or with psql: +Run the schema migration in your Supabase SQL Editor or with psql: ```bash psql $DATABASE_URL -f scripts/01-create-schema.sql ``` diff --git a/VERCEL_SETUP.md b/VERCEL_SETUP.md index fd5b05a..71b29d3 100644 --- a/VERCEL_SETUP.md +++ b/VERCEL_SETUP.md @@ -10,7 +10,7 @@ Go to your Vercel project → **Settings** → **Environment Variables** and add | Variable | Environment | Description | |----------|-------------|-------------| -| `DATABASE_URL` | Production, Preview, Development | Neon PostgreSQL connection string | +| `DATABASE_URL` | Production, Preview, Development | Supabase PostgreSQL connection string | | `GITHUB_CLIENT_ID` | Production, Preview, Development | GitHub OAuth App client ID | | `GITHUB_CLIENT_SECRET` | Production, Preview, Development | GitHub OAuth App client secret | | `NEXT_PUBLIC_APP_URL` | Production | Your production URL (e.g. `https://codevault.vercel.app`) | @@ -48,7 +48,7 @@ The workflow pulls env vars from Vercel automatically via `vercel pull`. Set the | Variable | Description | |----------|-------------| -| `DATABASE_URL` | Neon PostgreSQL connection string | +| `DATABASE_URL` | Supabase PostgreSQL connection string | | `GITHUB_CLIENT_ID` | GitHub OAuth App client ID | | `GITHUB_CLIENT_SECRET` | GitHub OAuth App client secret | | `NEXT_PUBLIC_APP_URL` | Your production URL | @@ -68,7 +68,7 @@ Once deployed, update your GitHub OAuth App callback URL: ## Run Database Migration -Run the schema SQL in your Neon console: +Run the schema SQL in your Supabase SQL Editor: ```sql -- Paste contents of scripts/01-create-schema.sql @@ -84,7 +84,7 @@ psql $DATABASE_URL -f scripts/01-create-schema.sql **GitHub OAuth redirects fail** → Check `NEXT_PUBLIC_APP_URL` matches your Vercel URL exactly -**Database errors** → Verify `DATABASE_URL` is correct and Neon project is active +**Database errors** → Verify `DATABASE_URL` is correct and Supabase project is active **AI analysis fails** → Check `OPENAI_API_KEY` has sufficient credits diff --git a/lib/db.ts b/lib/db.ts index b7d45f8..c0e9fb9 100644 --- a/lib/db.ts +++ b/lib/db.ts @@ -1,17 +1,21 @@ -import { neon } from '@neondatabase/serverless' +import postgres from 'postgres' + +let sql: ReturnType | null = null export function getDb() { + if (sql) return sql + const databaseUrl = process.env.DATABASE_URL if (!databaseUrl) { throw new Error( 'DATABASE_URL environment variable is not set. ' + - 'Please configure your Neon database connection string in your environment variables.' + 'Please configure your Supabase (or any PostgreSQL) connection string in your environment variables.' ) } - return neon(databaseUrl) + sql = postgres(databaseUrl) + return sql } -// Export a validation function for startup checks export function validateDatabaseConnection() { try { getDb() diff --git a/lib/queries.ts b/lib/queries.ts index 826059a..fe2f6dd 100644 --- a/lib/queries.ts +++ b/lib/queries.ts @@ -66,8 +66,8 @@ export interface AppBlueprint { // Repository queries export async function getAllRepositories(): Promise { const sql = getDb() - const repos = await sql`SELECT * FROM repositories ORDER BY created_at DESC` - return repos as Repository[] + const repos = await sql`SELECT * FROM repositories ORDER BY created_at DESC` + return repos } export async function getRepositoryById(id: string): Promise { @@ -112,8 +112,8 @@ export async function deleteRepository(id: string): Promise { // File queries export async function getFilesByRepository(repoId: string): Promise { const sql = getDb() - const files = await sql`SELECT * FROM repo_files WHERE repository_id = ${repoId} ORDER BY path` - return files as RepoFile[] + const files = await sql`SELECT * FROM repo_files WHERE repository_id = ${repoId} ORDER BY path` + return files } export async function createRepoFile(data: { @@ -166,8 +166,8 @@ export async function updateFileAnalysis(id: string, data: { // Analysis queries export async function getAllAnalyses(): Promise { const sql = getDb() - const analyses = await sql`SELECT * FROM analyses ORDER BY created_at DESC` - return analyses as Analysis[] + const analyses = await sql`SELECT * FROM analyses ORDER BY created_at DESC` + return analyses } export async function getAnalysisById(id: string): Promise { @@ -217,19 +217,19 @@ export async function linkAnalysisToRepository(analysisId: string, repositoryId: export async function getRepositoriesForAnalysis(analysisId: string): Promise { const sql = getDb() - const repos = await sql` + const repos = await sql` SELECT r.* FROM repositories r JOIN analysis_repositories ar ON r.id = ar.repository_id WHERE ar.analysis_id = ${analysisId} ` - return repos as Repository[] + return repos } // Blueprint queries export async function getBlueprintsByAnalysis(analysisId: string): Promise { const sql = getDb() - const blueprints = await sql`SELECT * FROM app_blueprints WHERE analysis_id = ${analysisId} ORDER BY reuse_percentage DESC` - return blueprints as AppBlueprint[] + const blueprints = await sql`SELECT * FROM app_blueprints WHERE analysis_id = ${analysisId} ORDER BY reuse_percentage DESC` + return blueprints } export async function deleteBlueprintsByAnalysis(analysisId: string): Promise { diff --git a/next-env.d.ts b/next-env.d.ts index 9edff1c..c4b7818 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -import "./.next/types/routes.d.ts"; +import "./.next/dev/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/package.json b/package.json index 34d5033..638b7c5 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,6 @@ "dependencies": { "@anthropic-ai/sdk": "^0.82.0", "@hookform/resolvers": "^3.9.1", - "@neondatabase/serverless": "^0.9.1", "@radix-ui/react-accordion": "1.2.12", "@radix-ui/react-alert-dialog": "1.1.15", "@radix-ui/react-aspect-ratio": "1.1.8", @@ -53,6 +52,7 @@ "next": "16.1.6", "next-themes": "^0.4.6", "pg": "^8.11.3", + "postgres": "^3.4.9", "react": "19.2.4", "react-day-picker": "9.13.2", "react-dom": "19.2.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6497a4a..98c5fa9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,9 +14,6 @@ importers: '@hookform/resolvers': specifier: ^3.9.1 version: 3.10.0(react-hook-form@7.71.2(react@19.2.4)) - '@neondatabase/serverless': - specifier: ^0.9.1 - version: 0.9.5 '@radix-ui/react-accordion': specifier: 1.2.12 version: 1.2.12(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -140,6 +137,9 @@ importers: pg: specifier: ^8.11.3 version: 8.18.0 + postgres: + specifier: ^3.4.9 + version: 3.4.9 react: specifier: 19.2.4 version: 19.2.4 @@ -573,9 +573,6 @@ packages: '@napi-rs/wasm-runtime@0.2.12': resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} - '@neondatabase/serverless@0.9.5': - resolution: {integrity: sha512-siFas6gItqv6wD/pZnvdu34wEqgG3nSE6zWZdq5j2DEsa+VvX8i/5HXJOo06qrw5axPXn+lGCxeR+NLaSPIXug==} - '@next/env@16.1.6': resolution: {integrity: sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ==} @@ -1453,9 +1450,6 @@ packages: '@types/node@22.19.11': resolution: {integrity: sha512-BH7YwL6rA93ReqeQS1c4bsPpcfOmJasG+Fkr6Y59q83f9M1WcBRHR2vM+P9eOisYRcN3ujQoiZY8uk5W+1WL8w==} - '@types/pg@8.11.6': - resolution: {integrity: sha512-/2WmmBXHLsfRqzfHW7BNZ8SbYzE8OSk7i3WjFYvfgRHj7S1xj+16Je5fUKv3lVdVzk/zn9TXOqf+avFCFIE0yQ==} - '@types/react-dom@19.2.3': resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} peerDependencies: @@ -2707,9 +2701,6 @@ packages: resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} engines: {node: '>= 0.4'} - obuf@1.1.2: - resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} - optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -2751,10 +2742,6 @@ packages: resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} engines: {node: '>=4.0.0'} - pg-numeric@1.0.2: - resolution: {integrity: sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==} - engines: {node: '>=4'} - pg-pool@3.11.0: resolution: {integrity: sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w==} peerDependencies: @@ -2767,10 +2754,6 @@ packages: resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} engines: {node: '>=4'} - pg-types@4.1.0: - resolution: {integrity: sha512-o2XFanIMy/3+mThw69O8d4n1E5zsLhdO+OPqswezu7Z5ekP4hYDqlDjlmOpYMbzY2Br0ufCwJLdDIXeNVwcWFg==} - engines: {node: '>=10'} - pg@8.18.0: resolution: {integrity: sha512-xqrUDL1b9MbkydY/s+VZ6v+xiMUmOUk7SS9d/1kpyQxoJ6U9AO1oIJyUWVZojbfe5Cc/oluutcgFG4L9RDP1iQ==} engines: {node: '>= 16.0.0'} @@ -2813,37 +2796,22 @@ packages: resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} engines: {node: '>=4'} - postgres-array@3.0.4: - resolution: {integrity: sha512-nAUSGfSDGOaOAEGwqsRY27GPOea7CNipJPOA7lPbdEpx5Kg3qzdP0AaWC5MlhTWV9s4hFX39nomVZ+C4tnGOJQ==} - engines: {node: '>=12'} - postgres-bytea@1.0.1: resolution: {integrity: sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==} engines: {node: '>=0.10.0'} - postgres-bytea@3.0.0: - resolution: {integrity: sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==} - engines: {node: '>= 6'} - postgres-date@1.0.7: resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==} engines: {node: '>=0.10.0'} - postgres-date@2.1.0: - resolution: {integrity: sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==} - engines: {node: '>=12'} - postgres-interval@1.2.0: resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} engines: {node: '>=0.10.0'} - postgres-interval@3.0.0: - resolution: {integrity: sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==} + postgres@3.4.9: + resolution: {integrity: sha512-GD3qdB0x1z9xgFI6cdRD6xu2Sp2WCOEoe3mtnyB5Ee0XrrL5Pe+e4CCnJrRMnL1zYtRDZmQQVbvOttLnKDLnaw==} engines: {node: '>=12'} - postgres-range@1.1.4: - resolution: {integrity: sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==} - prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -3640,10 +3608,6 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true - '@neondatabase/serverless@0.9.5': - dependencies: - '@types/pg': 8.11.6 - '@next/env@16.1.6': {} '@next/eslint-plugin-next@16.2.4': @@ -4501,12 +4465,6 @@ snapshots: dependencies: undici-types: 6.21.0 - '@types/pg@8.11.6': - dependencies: - '@types/node': 22.19.11 - pg-protocol: 1.11.0 - pg-types: 4.1.0 - '@types/react-dom@19.2.3(@types/react@19.2.14)': dependencies: '@types/react': 19.2.14 @@ -5863,8 +5821,6 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 - obuf@1.1.2: {} - optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -5905,8 +5861,6 @@ snapshots: pg-int8@1.0.1: {} - pg-numeric@1.0.2: {} - pg-pool@3.11.0(pg@8.18.0): dependencies: pg: 8.18.0 @@ -5921,16 +5875,6 @@ snapshots: postgres-date: 1.0.7 postgres-interval: 1.2.0 - pg-types@4.1.0: - dependencies: - pg-int8: 1.0.1 - pg-numeric: 1.0.2 - postgres-array: 3.0.4 - postgres-bytea: 3.0.0 - postgres-date: 2.1.0 - postgres-interval: 3.0.0 - postgres-range: 1.1.4 - pg@8.18.0: dependencies: pg-connection-string: 2.11.0 @@ -5969,25 +5913,15 @@ snapshots: postgres-array@2.0.0: {} - postgres-array@3.0.4: {} - postgres-bytea@1.0.1: {} - postgres-bytea@3.0.0: - dependencies: - obuf: 1.1.2 - postgres-date@1.0.7: {} - postgres-date@2.1.0: {} - postgres-interval@1.2.0: dependencies: xtend: 4.0.2 - postgres-interval@3.0.0: {} - - postgres-range@1.1.4: {} + postgres@3.4.9: {} prelude-ls@1.2.1: {} diff --git a/scripts/setup-deployment.sh b/scripts/setup-deployment.sh index 9869ef4..5bcd122 100755 --- a/scripts/setup-deployment.sh +++ b/scripts/setup-deployment.sh @@ -83,7 +83,7 @@ prompt_secret VERCEL_TOKEN " Paste your Vercel token" echo "" info "Step 3/5 — App environment variables" -prompt_plain DATABASE_URL " DATABASE_URL (Neon PostgreSQL)" +prompt_plain DATABASE_URL " DATABASE_URL (Supabase PostgreSQL)" prompt_plain GITHUB_CLIENT_ID " GITHUB_CLIENT_ID" prompt_secret GITHUB_CLIENT_SECRET " GITHUB_CLIENT_SECRET" prompt_plain APP_URL " NEXT_PUBLIC_APP_URL (e.g. https://codevault.vercel.app)" From 1cd8c937c75dd39b55b073f9b2043537a85a58f8 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 30 Apr 2026 05:03:58 +0000 Subject: [PATCH 3/4] Redesign UI with professional look and emerald accent theme - New color palette: emerald/green primary accent replacing blue - Landing page: compelling narrative ('Your next product is already built'), gradient hero, refined metrics strip, feature cards with hover states, numbered steps section, and strong CTA - Dashboard header: compact, glass-morphism backdrop blur, active state highlighting with primary color - Dashboard overview: clean stat cards with primary-tinted icons, polished empty states, refined repo cards - Analyses list: streamlined cards, consistent primary accent usage - Repositories list: refined layout, improved spacing and visual hierarchy - All components use consistent design language: rounded-2xl cards, primary/8 and primary/10 tints, muted-foreground for secondary text Co-authored-by: Cole Collins --- app/dashboard/layout.tsx | 2 +- app/dashboard/page.tsx | 175 +++++++++-------- app/globals.css | 110 +++++------ app/page.tsx | 326 ++++++++++++++++++------------- components/analyses-list.tsx | 99 +++++----- components/dashboard-header.tsx | 45 +++-- components/repositories-list.tsx | 164 ++++++++-------- 7 files changed, 491 insertions(+), 430 deletions(-) diff --git a/app/dashboard/layout.tsx b/app/dashboard/layout.tsx index 26899f7..8e200a0 100644 --- a/app/dashboard/layout.tsx +++ b/app/dashboard/layout.tsx @@ -16,7 +16,7 @@ export default async function DashboardLayout({ return (
-
+
{children}
diff --git a/app/dashboard/page.tsx b/app/dashboard/page.tsx index d10aef1..ee13a40 100644 --- a/app/dashboard/page.tsx +++ b/app/dashboard/page.tsx @@ -1,7 +1,7 @@ import { getAllRepositories, getAllAnalyses, type Analysis, type Repository } from '@/lib/queries' import { Button } from '@/components/ui/button' import { Card } from '@/components/ui/card' -import { FolderGit2, Sparkles, Code2, Plus, ArrowRight } from 'lucide-react' +import { FolderGit2, Sparkles, Code2, Plus, ArrowRight, Layers } from 'lucide-react' import Link from 'next/link' export default async function DashboardPage() { @@ -19,129 +19,132 @@ export default async function DashboardPage() { return (
- {/* Header */} -
-

Dashboard

-

Discover what apps you can build from your existing code.

+
+

Dashboard

+

Your code intelligence at a glance.

- {/* Quick stats */} -
- + {/* Stats */} +
+
-

Repositories

-

{repositories.length}

+

Repositories

+

{repositories.length}

+
+
+
-
- +
-

Analyses

-

{analyses.length}

+

Analyses

+

{analyses.length}

+
+
+
-
- +
-

Apps Discovered

-

{completedAnalyses.length > 0 ? '—' : '0'}

+

Completed

+

{completedAnalyses.length}

+
+
+
-
{/* Quick Actions */} -
-

Get Started

- - {repositories.length === 0 ? ( - - -

No repositories yet

-

- Start by adding your GitHub repositories. We will scan all files and prepare them for AI analysis. + {repositories.length === 0 ? ( + +

+ +
+

Get started with CodeVault

+

+ Connect your GitHub repositories and let AI discover the products hiding in your code. +

+ +
+ ) : ( +
+ +
+
+ +
+ + {repositories.length} connected + +
+

Repositories

+

+ Manage your connected GitHub repositories.

-
- ) : ( -
- -
-
- -
- - {repositories.length} connected - -
-

Repositories

-

- Manage your connected GitHub repositories. -

- -
- -
-
- -
- - {completedAnalyses.length} complete - + +
+
+
-

Run Analysis

-

- Let AI discover what apps you can build. -

- - -
- )} -
+ + {completedAnalyses.length} complete + +
+

Run analysis

+

+ Discover what apps you can build from your code. +

+ + +
+ )} - {/* Recent Repositories */} + {/* Recent Repos */} {repositories.length > 0 && (
-

Recent Repositories

-
-
- {repositories.slice(0, 3).map((repo) => ( - +
+ {repositories.slice(0, 6).map((repo) => ( +
-
- +
+
-

{repo.name}

+

{repo.name}

{repo.full_name}

{repo.language && ( - + {repo.language} )} diff --git a/app/globals.css b/app/globals.css index c8483d8..50443b3 100644 --- a/app/globals.css +++ b/app/globals.css @@ -4,74 +4,74 @@ @custom-variant dark (&:is(.dark *)); :root { - --background: oklch(0.95 0 0); - --foreground: oklch(0.15 0 0); + --background: oklch(0.97 0.002 240); + --foreground: oklch(0.13 0.02 260); --card: oklch(1 0 0); - --card-foreground: oklch(0.15 0 0); + --card-foreground: oklch(0.13 0.02 260); --popover: oklch(1 0 0); - --popover-foreground: oklch(0.15 0 0); - --primary: oklch(0.52 0.194 258); + --popover-foreground: oklch(0.13 0.02 260); + --primary: oklch(0.55 0.17 155); --primary-foreground: oklch(1 0 0); - --secondary: oklch(0.95 0 0); - --secondary-foreground: oklch(0.15 0 0); - --muted: oklch(0.88 0 0); - --muted-foreground: oklch(0.45 0 0); - --accent: oklch(0.52 0.194 258); + --secondary: oklch(0.95 0.005 240); + --secondary-foreground: oklch(0.2 0.02 260); + --muted: oklch(0.93 0.005 240); + --muted-foreground: oklch(0.46 0.015 260); + --accent: oklch(0.55 0.17 155); --accent-foreground: oklch(1 0 0); --destructive: oklch(0.577 0.245 27.325); --destructive-foreground: oklch(1 0 0); - --border: oklch(0.9 0 0); - --input: oklch(0.95 0 0); - --ring: oklch(0.52 0.194 258); - --chart-1: oklch(0.52 0.194 258); - --chart-2: oklch(0.65 0.2 130); - --chart-3: oklch(0.58 0.19 42); - --chart-4: oklch(0.71 0.18 180); - --chart-5: oklch(0.68 0.19 300); + --border: oklch(0.91 0.005 240); + --input: oklch(0.93 0.005 240); + --ring: oklch(0.55 0.17 155); + --chart-1: oklch(0.55 0.17 155); + --chart-2: oklch(0.65 0.14 200); + --chart-3: oklch(0.58 0.16 280); + --chart-4: oklch(0.68 0.15 45); + --chart-5: oklch(0.6 0.16 320); --radius: 0.625rem; - --sidebar: oklch(0.95 0 0); - --sidebar-foreground: oklch(0.15 0 0); - --sidebar-primary: oklch(0.52 0.194 258); + --sidebar: oklch(0.97 0.002 240); + --sidebar-foreground: oklch(0.13 0.02 260); + --sidebar-primary: oklch(0.55 0.17 155); --sidebar-primary-foreground: oklch(1 0 0); - --sidebar-accent: oklch(0.88 0 0); - --sidebar-accent-foreground: oklch(0.15 0 0); - --sidebar-border: oklch(0.9 0 0); - --sidebar-ring: oklch(0.52 0.194 258); + --sidebar-accent: oklch(0.93 0.005 240); + --sidebar-accent-foreground: oklch(0.13 0.02 260); + --sidebar-border: oklch(0.91 0.005 240); + --sidebar-ring: oklch(0.55 0.17 155); } .dark { - --background: oklch(0.08 0 0); - --foreground: oklch(0.98 0 0); - --card: oklch(0.12 0 0); - --card-foreground: oklch(0.98 0 0); - --popover: oklch(0.12 0 0); - --popover-foreground: oklch(0.98 0 0); - --primary: oklch(0.98 0 0); - --primary-foreground: oklch(0.08 0 0); - --secondary: oklch(0.18 0 0); - --secondary-foreground: oklch(0.98 0 0); - --muted: oklch(0.18 0 0); - --muted-foreground: oklch(0.65 0 0); - --accent: oklch(0.18 0 0); - --accent-foreground: oklch(0.98 0 0); + --background: oklch(0.09 0.015 260); + --foreground: oklch(0.96 0.005 240); + --card: oklch(0.13 0.015 260); + --card-foreground: oklch(0.96 0.005 240); + --popover: oklch(0.13 0.015 260); + --popover-foreground: oklch(0.96 0.005 240); + --primary: oklch(0.7 0.19 155); + --primary-foreground: oklch(0.09 0.015 260); + --secondary: oklch(0.17 0.015 260); + --secondary-foreground: oklch(0.96 0.005 240); + --muted: oklch(0.17 0.015 260); + --muted-foreground: oklch(0.6 0.01 260); + --accent: oklch(0.17 0.015 260); + --accent-foreground: oklch(0.96 0.005 240); --destructive: oklch(0.55 0.2 25); - --destructive-foreground: oklch(0.98 0 0); - --border: oklch(0.22 0 0); - --input: oklch(0.18 0 0); - --ring: oklch(0.98 0 0); - --chart-1: oklch(0.7 0.15 150); - --chart-2: oklch(0.65 0.15 200); + --destructive-foreground: oklch(0.96 0.005 240); + --border: oklch(0.2 0.012 260); + --input: oklch(0.17 0.015 260); + --ring: oklch(0.7 0.19 155); + --chart-1: oklch(0.7 0.19 155); + --chart-2: oklch(0.65 0.14 200); --chart-3: oklch(0.6 0.15 280); - --chart-4: oklch(0.75 0.12 50); - --chart-5: oklch(0.7 0.15 320); - --sidebar: oklch(0.1 0 0); - --sidebar-foreground: oklch(0.98 0 0); - --sidebar-primary: oklch(0.98 0 0); - --sidebar-primary-foreground: oklch(0.08 0 0); - --sidebar-accent: oklch(0.18 0 0); - --sidebar-accent-foreground: oklch(0.98 0 0); - --sidebar-border: oklch(0.22 0 0); - --sidebar-ring: oklch(0.98 0 0); + --chart-4: oklch(0.72 0.14 50); + --chart-5: oklch(0.65 0.15 320); + --sidebar: oklch(0.11 0.015 260); + --sidebar-foreground: oklch(0.96 0.005 240); + --sidebar-primary: oklch(0.7 0.19 155); + --sidebar-primary-foreground: oklch(0.09 0.015 260); + --sidebar-accent: oklch(0.17 0.015 260); + --sidebar-accent-foreground: oklch(0.96 0.005 240); + --sidebar-border: oklch(0.2 0.012 260); + --sidebar-ring: oklch(0.7 0.19 155); } @theme inline { diff --git a/app/page.tsx b/app/page.tsx index fde5c59..a3cb7ce 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,6 +1,6 @@ import Link from 'next/link' import { Button } from '@/components/ui/button' -import { Github, Sparkles, Code2, Layers, ArrowRight, AlertCircle } from 'lucide-react' +import { Github, Sparkles, Layers, ArrowRight, AlertCircle, Rocket, ChevronRight, Eye, Puzzle, Zap } from 'lucide-react' const ERROR_MESSAGES: Record = { auth_required: 'You must sign in to access the dashboard.', @@ -24,177 +24,235 @@ export default async function HomePage({ searchParams }: { searchParams: Promise {errorMessage}
)} - {/* Header */} -
-
-
-
- + +
+
+
+
+
- CodeVault + CodeVault
-
- {/* Hero Section */} -
-
-
- - New - · - Maps what you already shipped to what you can ship next -
- -

- Discover Apps Hidden in Your Code -

- -

- Teams use CodeVault to surface products they have already mostly built — scattered across repos — - then ship them as one coherent app. Connect GitHub and turn existing files into concrete blueprints. -

- -
- - -
+
+ {/* Hero */} +
+
+
+
+
+ + AI-powered code intelligence +
-

- Read-only GitHub access. Your code stays yours — we analyze structure and patterns to suggest combinations, not to store your source. -

-
+

+ Your next product is +
+ already built. +

- {/* Social proof strip — established product feel */} -
-

- Built for builders who already have the hard parts -

-
-
-

12k+

-

repos scanned

-
-
-

4.1k

-

blueprints surfaced

-
-
-

38

-

stacks detected

-
-
-

New

-

cross-repo fusion engine

-
-
-
+

+ CodeVault scans your GitHub repositories and finds complete applications hiding in your existing code. + Stop rebuilding what you already have. +

+ +
+ + +
- {/* Feature Cards */} -
-
-
- +

+ Read-only access. We analyze structure and patterns — your source code is never stored. +

-

Connect Repositories

-

- Link your GitHub repos and we will scan all files to understand your codebase structure. -

+
-
-
- + {/* Metrics strip */} +
+
+
+
+

12k+

+

Repos scanned

+
+
+

4.1k

+

Apps discovered

+
+
+

73%

+

Avg. code reuse

+
+
+

38

+

Stacks supported

+
-

AI Analysis

-

- Our AI analyzes each file to identify its purpose, exports, and reusability potential. -

+
-
-
- + {/* Value proposition */} +
+
+
+

+ From scattered files to shipping products +

+

+ Most teams have already built 60-80% of their next product — it's just spread across different repositories. We find it. +

-

App Blueprints

-

- Get detailed blueprints showing what apps you can build and what files you need to add. -

-
-
- {/* How It Works */} -
-

How It Works

-
-
-
- 1 -
-
-

Add Your Repositories

-

- Enter your GitHub repository URLs or connect via OAuth to import multiple repos at once. +

+
+
+ +
+

See what you own

+

+ Connect your repositories and our AI maps every component, utility, hook, and API across your entire codebase.

-
-
-
- 2 +
+
+ +
+

Discover hidden apps

+

+ AI cross-references your files and surfaces complete product blueprints — showing exactly what you can ship today. +

-
-

AI Scans Your Code

-

- Our AI examines every file - components, utilities, hooks, APIs - identifying what each piece does and how reusable it is. + +

+
+ +
+

Ship in hours, not months

+

+ Get a build plan with reusable files, missing pieces to generate, and estimated effort. Go from blueprint to product fast.

+
+
-
-
- 3 + {/* How it works */} +
+
+
+

+ Three steps to your next launch +

+

+ Connect, scan, ship. CodeVault handles the heavy lifting. +

+
+ +
+
+
+
+
+ 1 +
+
+
+

Connect repos

+

+ Sign in with GitHub and import your repositories. We scan with read-only access — nothing is modified. +

+
+ +
+
+
+ 2 +
+
+
+

AI analysis

+

+ Our AI examines every file — components, utilities, APIs — and identifies reusable building blocks across all your repos. +

+
+ +
+
+
+ 3 +
+
+

Get blueprints

+

+ Receive detailed app blueprints showing what to reuse, what's missing, and a build plan ranked by ship-readiness. +

+
-
-

Discover App Possibilities

-

- See a list of applications you can build using your existing code. Each blueprint shows which files to reuse and what few extras you might need. -

+
+
+
+ + {/* CTA */} +
+
+
+
+ + Free to start
+

+ Stop building from scratch +

+

+ Connect your GitHub and discover the products you've already (mostly) built. Your first analysis is on us. +

+
-
+ - {/* Footer */} -