A web application that creates comprehensive intelligence profiles on people in your network by searching the web, analyzing social media, and building detailed dossiers powered by AI. Understand your contacts — who they are, what they post about, their interests, and what you have in common.
Live: dossier.certihomes.com
- Dossier Generation: AI-powered 8-section intelligence profiles with deep social media analysis
- Commonalities: Automatically finds shared interests, industries, and conversation starters between you and each contact
- Communication Guide: DISC-based personalized tips for how to approach each person
- Content Analysis: What they actually post about on LinkedIn, X, Instagram — not just their job title
- Multi-Source Import: Google Contacts, LinkedIn CSV, generic CSV, LinkedIn bookmarklet
- LinkedIn Auto-Import: Browser bookmarklet scrapes your connections page and imports with photos
- Social Handle Discovery: Per-contact or bulk Brave Search to find missing LinkedIn, X, Instagram, TikTok, Facebook profiles
- Disambiguation: When search results are ambiguous, shows multiple candidates with confidence scoring
- Profile Photos: Auto-download and store profile pictures from social platforms
- Tagging & Filtering: Color-coded tags, filter by dossier status, search contacts
- Conference Scanner: Paste an event URL → AI finds all speakers → imports them → discovers socials → auto-generates dossiers
- Event Tracking: Real-time status tracking (scraping → importing → enriching → generating dossiers)
- 6 OAuth Providers: Google, LinkedIn, Facebook, X/Twitter, Instagram, Apple
- Account Linking: Connect multiple social logins to one account
- Auto-Fill Profiles: Social handles are auto-populated when you connect each platform
- Your Own Profile: Add your social handles, then "Build My Dossier" to see what others can learn about you
- DISC Personality Quiz: Understand your communication style for better connection guides
- Frontend: Next.js 15 (App Router), React 19, Tailwind CSS 4, Zustand
- Backend: Next.js API Routes, Prisma ORM
- Database: PostgreSQL (port 5433)
- Auth: NextAuth.js v4 with 6 OAuth providers
- AI: Ollama/Qwen 2.5 14B (local, free) | Anthropic Claude API (paid) | Claude CLI Proxy (Max plan)
- Search: Brave Search API (primary) with Google Custom Search fallback
- Email: Nodemailer (SMTP)
- Node.js 18+
- PostgreSQL
- Google Cloud Console project (for OAuth)
- Brave Search API key (api-dashboard.search.brave.com)
- Ollama with Qwen 2.5 (optional, for local AI) or Anthropic API key
-
Clone the repository:
git clone https://github.com/tlcengine/dossier.git cd dossier -
Install dependencies:
npm install
-
Copy the environment file and fill in your values:
cp .env.example .env
-
Set up the database:
# Create the database (PostgreSQL on port 5433) sudo -u postgres psql -p 5433 -c "CREATE DATABASE dossier;" # Push schema to database npx prisma db push
-
Start the development server:
npm run dev
Set AI_PROVIDER in .env to choose your AI backend:
| Value | Cost | Description |
|---|---|---|
ollama |
Free | Local Qwen 2.5 14B via Ollama (default) |
claude-proxy |
Free (with Max plan) | Routes through Claude CLI proxy using your Max 5x subscription |
claude |
Pay-as-you-go | Direct Anthropic API (~$0.03/dossier) |
hybrid |
Mixed | Qwen for light tasks, Claude for deep analysis |
If you have a Claude Max plan, you can use it as a free API:
# Start the proxy (runs on port 11437)
pm2 start claude-proxy.mjs --name claude-proxy
# Set in .env
AI_PROVIDER="claude-proxy"| Variable | Required | Description |
|---|---|---|
DATABASE_URL |
Yes | PostgreSQL connection string (port 5433) |
NEXTAUTH_URL |
Yes | Application URL |
NEXTAUTH_SECRET |
Yes | Random secret for NextAuth session encryption |
GOOGLE_CLIENT_ID |
Yes | Google OAuth client ID |
GOOGLE_CLIENT_SECRET |
Yes | Google OAuth client secret |
BRAVE_SEARCH_API_KEY |
Yes | Brave Search API key (primary search provider) |
AI_PROVIDER |
No | AI backend: ollama, claude, claude-proxy, hybrid |
OLLAMA_URL |
No | Ollama API URL (default: http://localhost:11434) |
ANTHROPIC_API_KEY |
No | Anthropic API key (for claude/hybrid mode) |
CLAUDE_PROXY_URL |
No | Claude CLI proxy URL (default: http://127.0.0.1:11437) |
LINKEDIN_CLIENT_ID |
No | LinkedIn OAuth client ID |
LINKEDIN_CLIENT_SECRET |
No | LinkedIn OAuth client secret |
FACEBOOK_CLIENT_ID |
No | Facebook OAuth client ID |
FACEBOOK_CLIENT_SECRET |
No | Facebook OAuth client secret |
TWITTER_CLIENT_ID |
No | X/Twitter OAuth 2.0 client ID |
TWITTER_CLIENT_SECRET |
No | X/Twitter OAuth 2.0 client secret |
INSTAGRAM_CLIENT_ID |
No | Instagram OAuth client ID |
INSTAGRAM_CLIENT_SECRET |
No | Instagram OAuth client secret |
APPLE_ID |
No | Apple OAuth client ID |
APPLE_SECRET |
No | Apple OAuth client secret |
SMTP_HOST |
No | SMTP server host |
SMTP_PORT |
No | SMTP server port (default: 587) |
SMTP_USER |
No | SMTP username |
SMTP_PASS |
No | SMTP password |
SMTP_FROM |
No | From email address |
Each social login provider needs a callback URL:
https://dossier.certihomes.com/api/auth/callback/google
https://dossier.certihomes.com/api/auth/callback/linkedin
https://dossier.certihomes.com/api/auth/callback/facebook
https://dossier.certihomes.com/api/auth/callback/twitter
https://dossier.certihomes.com/api/auth/callback/instagram
https://dossier.certihomes.com/api/auth/callback/apple
The app is deployed on geo.tlcengine.com and accessible at dossier.certihomes.com.
- Nginx: reverse proxy from dossier.certihomes.com →
127.0.0.1:3006 - SSL: Let's Encrypt via Certbot (auto-configured)
- Process: PM2
npm run build # Build
PORT=3006 pm2 start npm --name dossier -- start # Start on port 3006
pm2 start claude-proxy.mjs --name claude-proxy # Start Claude proxy (optional)
pm2 save # Save PM2 configsrc/
├── app/
│ ├── api/
│ │ ├── auth/[...nextauth]/ # NextAuth handler
│ │ ├── contacts/ # Contact CRUD
│ │ │ └── [id]/find-socials/ # Social handle discovery
│ │ ├── contacts/enrich/ # Bulk social enrichment
│ │ ├── disc/ # DISC personality quiz
│ │ ├── dossier/ # Dossier generation & retrieval
│ │ ├── events/ # Event research pipeline
│ │ ├── import/
│ │ │ ├── csv/ # CSV upload (LinkedIn/generic)
│ │ │ ├── google/ # Google contacts import
│ │ │ └── linkedin-scrape/ # Bookmarklet data receiver
│ │ ├── profile/ # User profile & accounts
│ │ │ ├── accounts/ # Connected OAuth accounts
│ │ │ └── self-dossier/ # Self-dossier generation
│ │ └── tags/ # Tag management
│ ├── dashboard/ # Main dashboard page
│ ├── layout.tsx # Root layout with providers
│ └── page.tsx # Landing page (6 login providers)
├── components/
│ ├── ContactDetail.tsx # Contact view + SocialHub + EditForm
│ ├── EventResearch.tsx # Event speaker research UI
│ ├── MainHub.tsx # Landing hub with task cards
│ ├── Sidebar.tsx # Left panel contact list
│ └── WelcomeModal.tsx # First-time user onboarding
└── lib/
├── auth.ts # NextAuth config (6 providers)
├── email.ts # Email notification service
├── events.ts # Event research pipeline
├── prisma.ts # Prisma client singleton
├── research.ts # Web search + AI analysis engine
├── store.ts # Zustand state management
└── types.ts # TypeScript types
public/
├── avatars/ # Downloaded profile photos
└── bookmarklets/
└── linkedin-import.js # LinkedIn connections bookmarklet
claude-proxy.mjs # Claude CLI proxy server (Max plan)
npm run dev # Development server
npm run build # Production build
npm run db:push # Push schema to database
npm run db:studio # Open Prisma Studio
npm run db:generate # Regenerate Prisma clientPrivate - TLC Engine