- TypeScript 81%
- CSS 16.2%
- JavaScript 2.7%
|
Some checks are pending
CI / Build with 20.x (push) Waiting to run
CI / Build with 22.6 (push) Waiting to run
CI / Run all tests (push) Waiting to run
CI / GitHub PR synchronize with Crowdin (push) Blocked by required conditions
Crowdin Action / Synchronize with Crowdin (push) Waiting to run
|
||
|---|---|---|
| .codegraph | ||
| .cursor | ||
| .github | ||
| .husky | ||
| .pglite | ||
| .storybook | ||
| .vscode | ||
| data | ||
| doc | ||
| docker/postgres/init | ||
| docs | ||
| migrations | ||
| public | ||
| scripts | ||
| src | ||
| tests | ||
| .dockerignore | ||
| .env | ||
| .env.docker.example | ||
| .env.production | ||
| .gitignore | ||
| AGENTS.md | ||
| CHANGELOG.md | ||
| checkly.config.ts | ||
| codecov.yml | ||
| commitlint.config.ts | ||
| components.json | ||
| crowdin.yml | ||
| DESIGN.md | ||
| docker-compose.yml | ||
| Dockerfile | ||
| drizzle.config.ts | ||
| eslint.config.mjs | ||
| LICENSE | ||
| lint-staged.config.js | ||
| next-env.d.ts | ||
| next.config.mjs | ||
| package-lock.json | ||
| package.json | ||
| playwright.config.ts | ||
| postcss.config.js | ||
| prd.md | ||
| README.md | ||
| sentry.client.config.ts | ||
| tailwind.config.ts | ||
| tsconfig.json | ||
| vitest-setup.ts | ||
| vitest.config.mts | ||
RaiseSpy
RaiseSpy is a self-hosted SaaS app for founders, operators, accelerators, and studios that need a focused way to find, rank, save, contact, and track investors.
The app sells prepaid access to curated investor intelligence, ranks investors with PitchMatch, supports AI-generated outreach emails, and gives users lightweight Pipeline collections for saving and exporting shortlists. Admin users can manage users, investors, subscriptions, scripts, audit logs, and data-access risk from the built-in admin area.
Tech Stack
- Next.js App Router monolith with React and TypeScript.
- Tailwind CSS and local shadcn/Radix-style UI primitives in
src/components/ui. - Better Auth for passwordless authentication.
- Drizzle ORM with PostgreSQL in production and PGlite fallback for local/test use.
- Stripe Checkout for prepaid access plans.
- Nodemailer-compatible SMTP for transactional email.
- Vitest, React Testing Library, and Playwright for tests.
Repository Layout
src/app: App Router pages, layouts, API routes, and server actions.src/app/[locale]/(auth)/investors: authenticated investor workspace, search, detail, Pipeline, and AI email UI.src/app/[locale]/admin: admin dashboard, admin queries, and admin server actions.src/app/api: API routes for investors, saved lists, billing, auth, exports, and AI email generation.src/components/ui: reusable UI primitives.src/libs: shared app logic for auth, database access, PitchMatch, saved lists, Pipeline, email, rate limits, and scraping protection.src/models/Schema.ts: Drizzle schema source of truth.migrations: SQL migrations generated from Drizzle schema changes.scripts: import and maintenance scripts.docs: architecture, database schema, task, user-flow, and Docker notes.prd.md: canonical product requirements.DESIGN.md: design system and architecture guidance for product work.
Requirements
- Node.js 20+.
- npm.
- Docker and Docker Compose for the full local stack or container deployment.
- PostgreSQL for production.
- SMTP credentials for auth and transactional email.
- Stripe keys for billing flows.
Local Development
Install dependencies:
npm ci
Create a local environment file such as .env.local with the required values from the environment section below. Development can use placeholder Stripe values and Mailpit SMTP values if you are running Docker locally.
Start the full local developer process:
npm run dev
This runs the Next.js app and local Spotlight sidecar. Open http://localhost:3000.
To run only Next.js:
npm run dev:next
If DATABASE_URL is not set in development or tests, the app can use its PGlite fallback. Use PostgreSQL when working on database behavior that must match production.
Local Docker Stack
The Docker stack runs the app, PostgreSQL, NocoDB, and Mailpit:
docker compose up --build
Open:
- App:
http://localhost:3000 - NocoDB:
http://localhost:8080 - Mailpit inbox:
http://localhost:8025 - PostgreSQL:
localhost:5432
To override ports, database names, or local secrets:
cp .env.docker.example .env.docker
docker compose --env-file .env.docker up --build
The app container waits for Postgres, runs npm run db:migrate:docker, and starts Next.js. More local Docker notes are in docs/docker-local.md.
Useful Docker commands:
# Start in the background
docker compose up --build -d
# View app logs
docker compose logs -f app
# Run migrations manually inside the app container
docker compose exec app npm run db:migrate:docker
# Open a Postgres shell
docker compose exec postgres psql -U postgres -d capital_connector
# Stop containers but keep volumes
docker compose down
# Stop containers and remove local database/NocoDB volumes
docker compose down -v
Environment Variables
The runtime environment is validated in src/libs/Env.ts. Do not commit real secrets.
Required for normal runtime:
DATABASE_URL=postgresql://user:password@host:5432/database
BETTER_AUTH_SECRET=replace-with-a-long-random-secret
BETTER_AUTH_URL=http://localhost:3000
BILLING_PLAN_ENV=dev
STRIPE_SECRET_KEY=sk_test_replace_me
STRIPE_WEBHOOK_SECRET=whsec_replace_me
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_replace_me
SMTP_HOST=localhost
SMTP_PORT=1025
SMTP_USER=local
SMTP_PASS=local
SMTP_FROM=no-reply@example.com
NEXT_PUBLIC_APP_URL=http://localhost:3000
Common optional values:
ADMIN_PRIMARY_EMAIL=founder@example.com
ENABLE_ANONYMOUS_AUTH=true
STRIPE_FUNDRAISING_SPRINT_PRICE_ID=price_...
STRIPE_ANNUAL_MEMBERSHIP_PRICE_ID=price_...
STRIPE_ACCELERATOR_STUDIO_PRICE_ID=price_...
ANTHROPIC_API_KEY=sk-ant-...
ANTHROPIC_MODEL=claude-...
OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-...
NEXT_PUBLIC_PLAUSIBLE_DOMAIN=example.com
LOGTAIL_SOURCE_TOKEN=...
Production validation is stricter:
DATABASE_URLis required.STRIPE_SECRET_KEYmust be a live or restricted live key.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYmust be a live publishable key.STRIPE_WEBHOOK_SECRETmust be a Stripe webhook signing secret.- Self-serve plan price IDs must use Stripe
price_...identifiers. BILLING_PLAN_ENVmust beprod.BETTER_AUTH_URLandNEXT_PUBLIC_APP_URLshould use the production HTTPS URL.
Deploy To Production
The intended production shape is a lean single-VPS deployment with PostgreSQL, HTTPS, SMTP, Stripe webhooks, and cron-managed jobs.
-
Provision the server.
- Install Docker, Docker Compose, Node.js 20 if deploying without Docker, and a reverse proxy such as Caddy or Nginx.
- Point the production domain at the server.
- Configure HTTPS before enabling production auth and Stripe webhook URLs.
-
Provision PostgreSQL.
- Create a dedicated database and database user.
- Store the connection string in
DATABASE_URL. - Keep backups outside the app container.
-
Configure production secrets.
- Set
NODE_ENV=production. - Set the required environment variables listed above.
- Use live Stripe keys and production Stripe price IDs.
- Configure Stripe webhooks to point to the app's webhook route.
- Configure SMTP with the production mail server.
- Set
-
Build and migrate.
npm ci
npm run build
npm run db:migrate
- Start the app.
npm run start
-
Put the app behind the reverse proxy.
- Forward HTTPS traffic to the app on port
3000. - Set the production origin in
BETTER_AUTH_URLandNEXT_PUBLIC_APP_URL. - Restart the app after environment changes.
- Forward HTTPS traffic to the app on port
-
Verify the deployment.
- Load the public site.
- Request and consume a magic link.
- Complete onboarding.
- Confirm Stripe checkout works in live mode.
- Confirm admin access for the configured admin user.
- Confirm transactional emails are delivered.
- Check app logs for environment validation, migration, auth, billing, and email errors.
Docker Deployment Option
The included Dockerfile builds the Next.js app and starts it with:
npm run db:migrate:docker && npm run start
For production Docker usage, provide production environment variables at container runtime and use a real PostgreSQL volume or external managed PostgreSQL instance. Replace all local placeholder secrets from docker-compose.yml or .env.docker.example before exposing the app publicly.
Editing The App
Read prd.md, DESIGN.md, and AGENTS.md before non-trivial product, UI, auth, billing, database, admin, scraping-protection, or architecture changes.
Common editing paths:
- Public and authenticated pages: edit route files under
src/app. - Investor workspace UI: edit
src/app/[locale]/(auth)/investors. - Admin UI and mutations: edit
src/app/[locale]/admin. - API behavior: edit route handlers under
src/app/api. - Shared business logic: edit
src/libs. - Reusable UI primitives: edit
src/components/ui. - Product copy and localized strings: edit
src/locales. - Database tables and relations: edit
src/models/Schema.ts, then generate a migration.
When changing database schema:
npm run db:generate
Then review the generated SQL in migrations, apply it in the right environment, and update docs/database-schema.md.
When changing product behavior or user/admin flows, update the relevant docs in docs/tasks.md, docs/architecture.md, or docs/user-flows.md.
Data Import And Maintenance
Investor data imports use:
npx tsx scripts/import-investors.ts
Run import and maintenance scripts against a confirmed target database. Do not run destructive or production-affecting data commands without a backup and rollback plan.
Subscription expiry maintenance can be run with:
npm run jobs:expire-subscriptions
Verification Commands
Use these before opening a PR or deploying:
npm run lint
npm run check-types
npm run test
npm run build
For Playwright E2E tests:
npx playwright install
npm run test:e2e
For focused Vitest runs:
npm run test -- path/to/file.test.ts
Development Rules
- Keep investor list responses summary-safe; use detail, contact, and export flows for sensitive data.
- Keep PitchMatch scoring centralized in
src/libs/PitchMatch.ts. - Keep Pipeline state in
saved_listsandsaved_list_items. - Use existing UI primitives and semantic Tailwind tokens.
- Validate mutating server actions and API routes.
- Add focused tests for new API routes, non-trivial server actions, schema behavior, auth checks, and rate-limit behavior.
- Do not commit
.envvalues, production credentials, API keys, or imported private data.
License
See LICENSE.