Skip to content

Dharm3112/IntelliCircle

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

119 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

✨ IntelliCircle ✨

The real-time, location-aware watercooler for local professional networking.

Features β€’ Architecture β€’ Getting Started β€’ Folder Structure β€’ Design Philosophy β€’ Troubleshooting


πŸ“– Product Overview

IntelliCircle is a modern, real-time networking and chat application designed to digitally map users to hyper-localized professional groups. We remove the friction of traditional networking by providing spontaneous, hyper-local chat environments. IntelliCircle calculates physical proximity to instantly drop users into curated professional hubs based entirely on shared interests.

While platforms like LinkedIn serve as a global, asynchronous resume repository, IntelliCircle serves as the synchronous, location-aware watercooler. Stop swiping. Start meeting.


πŸš€ Key Features

  • 🌍 Location-Based Discovery: Automatically detects your city and calculates real-time distances to active chat rooms using PostGIS native geospatial indexes.
  • ⚑ Ultra-Low Latency Messaging: Sub-50ms native WebSocket broadcasting powered by ws and scaled horizontally via Redis Pub/Sub.
  • 🎯 Frictionless Zero-Click Entry: Users can join local rooms immediately with temporary aliases. No lengthy signup walls required.
  • πŸ€– AI-Powered Context: Integrates with Google Gemini Flash 2.5 (via BullMQ background jobs) to automatically summarize missed conversations in active rooms.
  • πŸ”’ Enterprise-Grade Security: Fully asymmetric JWT authentication (RS256), Zod payload validation across the entire stack, CSRF protection, and strict rate limiting.

πŸ—οΈ Architecture & Tech Stack

IntelliCircle leverages a cutting-edge decoupled Client-Server architecture utilizing an npm Workspaces Monorepo. This allows for strict type-sharing while maintaining isolated execution environments.

Frontend (@intellicircle/client)

Built for SEO, speed, and seamless UX.

  • Framework: Next.js 14 (App Router)
  • UI & Styling: Tailwind CSS, Shadcn UI, and highly-optimized Framer Motion micro-interactions.
  • State Management: Zustand (Client Global State) + TanStack Query/React Query (Server State).
  • Infinite Scrolling: react-virtuoso for rendering massive chat logs without frame drops.

Backend (@intellicircle/server)

High-throughput, real-time processing engine.

  • Framework: Fastify for maximum JSON parsing speed.
  • WebSockets: @fastify/websocket binding native Node.js ws to the HTTP instance.
  • Queue System: BullMQ (Redis) for heavy async jobs (Email dispatch, AI Summarization).
  • AI Integration: @google/generative-ai for intelligent room summaries.

Database Layer

  • Primary Database: PostgreSQL with the PostGIS extension for ST_DWithin spatial queries.
  • ORM: Drizzle ORM, the fastest TypeScript ORM available.
  • Broker & Caching: Redis (Upstash) serving as the WebSocket Pub/Sub backplane, rate-limit store, and job queue.

Universal Validation (@intellicircle/shared)

  • Zod: Ensures type safety across the network boundary, strictly typing DB schemas, WS payloads, and REST APIs.

πŸ“‚ Project Structure

IntelliCircle/
β”œβ”€β”€ legacy
β”‚   β”œβ”€β”€ client
β”‚   β”‚   β”œβ”€β”€ index.html
β”‚   β”‚   └── src
β”‚   β”‚       β”œβ”€β”€ App.tsx
β”‚   β”‚       β”œβ”€β”€ components
β”‚   β”‚       β”‚   β”œβ”€β”€ ui
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ accordion.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ alert-dialog.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ alert.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ aspect-ratio.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ avatar.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ badge.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ breadcrumb.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ button.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ calendar.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ card.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ carousel.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ chart.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ checkbox.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ collapsible.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ command.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ context-menu.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ dialog.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ drawer.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ dropdown-menu.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ form.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ hover-card.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ input-otp.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ input.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ label.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ menubar.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ navigation-menu.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ pagination.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ popover.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ progress.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ radio-group.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ resizable.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ scroll-area.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ select.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ separator.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ sheet.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ sidebar.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ skeleton.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ slider.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ switch.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ table.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ tabs.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ textarea.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ toast.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ toaster.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ toggle-group.tsx
β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ toggle.tsx
β”‚   β”‚       β”‚   β”‚   └── tooltip.tsx
β”‚   β”‚       β”‚   └── waitlist-form.tsx
β”‚   β”‚       β”œβ”€β”€ hooks
β”‚   β”‚       β”‚   β”œβ”€β”€ use-mobile.tsx
β”‚   β”‚       β”‚   └── use-toast.ts
β”‚   β”‚       β”œβ”€β”€ index.css
β”‚   β”‚       β”œβ”€β”€ lib
β”‚   β”‚       β”‚   β”œβ”€β”€ queryClient.ts
β”‚   β”‚       β”‚   └── utils.ts
β”‚   β”‚       β”œβ”€β”€ main.tsx
β”‚   β”‚       └── pages
β”‚   β”‚           β”œβ”€β”€ chat.tsx
β”‚   β”‚           β”œβ”€β”€ discover.tsx
β”‚   β”‚           β”œβ”€β”€ home.tsx
β”‚   β”‚           β”œβ”€β”€ not-found.tsx
β”‚   β”‚           └── profile.tsx
β”‚   β”œβ”€β”€ server
β”‚   β”‚   β”œβ”€β”€ db.ts
β”‚   β”‚   β”œβ”€β”€ index.ts
β”‚   β”‚   β”œβ”€β”€ routes.ts
β”‚   β”‚   β”œβ”€β”€ storage.ts
β”‚   β”‚   └── vite.ts
β”‚   └── shared
β”‚       └── schema.ts
β”œβ”€β”€ packages
β”‚   β”œβ”€β”€ client
β”‚   β”‚   β”œβ”€β”€ lint.log
β”‚   β”‚   β”œβ”€β”€ next-env.d.ts
β”‚   β”‚   β”œβ”€β”€ next.config.mjs
β”‚   β”‚   β”œβ”€β”€ package.json
β”‚   β”‚   β”œβ”€β”€ postcss.config.js
β”‚   β”‚   β”œβ”€β”€ src
β”‚   β”‚   β”‚   β”œβ”€β”€ app
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ (app)
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ chat
β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ [id]
β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   └── page.tsx
β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   └── page.tsx
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ dashboard
β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   └── page.tsx
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ discover
β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   └── page.tsx
β”‚   β”‚   β”‚   β”‚   β”‚   └── profile
β”‚   β”‚   β”‚   β”‚   β”‚       └── page.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ (marketing)
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ about
β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   └── page.tsx
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ contact
β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   └── page.tsx
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ privacy
β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   └── page.tsx
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ terms
β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   └── page.tsx
β”‚   β”‚   β”‚   β”‚   β”‚   └── waitlist
β”‚   β”‚   β”‚   β”‚   β”‚       └── page.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ auth
β”‚   β”‚   β”‚   β”‚   β”‚   └── page.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ globals.css
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ layout.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ not-found.tsx
β”‚   β”‚   β”‚   β”‚   └── page.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ components
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ CreateRoomModal.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ auth-modal.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ footer.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ header.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ mobile-drawer.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ page-transition.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ posthog-provider.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ providers.tsx
β”‚   β”‚   β”‚   β”‚   └── upgrade-modal.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ hooks
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ useGeolocation.ts
β”‚   β”‚   β”‚   β”‚   └── useSocket.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ lib
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ api.ts
β”‚   β”‚   β”‚   β”‚   └── utils.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ middleware.ts
β”‚   β”‚   β”‚   └── store
β”‚   β”‚   β”‚       β”œβ”€β”€ authStore.ts
β”‚   β”‚   β”‚       └── index.ts
β”‚   β”‚   β”œβ”€β”€ tailwind.config.ts
β”‚   β”‚   β”œβ”€β”€ tsconfig.json
β”‚   β”‚   β”œβ”€β”€ tsconfig.tsbuildinfo
β”‚   β”‚   └── typescript-errors.log
β”‚   β”œβ”€β”€ server
β”‚   β”‚   β”œβ”€β”€ .env
β”‚   β”‚   β”œβ”€β”€ .env.keys
β”‚   β”‚   β”œβ”€β”€ Dockerfile
β”‚   β”‚   β”œβ”€β”€ check-logs.ts
β”‚   β”‚   β”œβ”€β”€ check_db.ts
β”‚   β”‚   β”œβ”€β”€ drizzle.config.ts
β”‚   β”‚   β”œβ”€β”€ inject_nearby.txt
β”‚   β”‚   β”œβ”€β”€ inject_nearby_fixed.txt
β”‚   β”‚   β”œβ”€β”€ inject_out.txt
β”‚   β”‚   β”œβ”€β”€ migrations
β”‚   β”‚   β”‚   β”œβ”€β”€ 0000_fantastic_shriek.sql
β”‚   β”‚   β”‚   β”œβ”€β”€ 0001_youthful_ser_duncan.sql
β”‚   β”‚   β”‚   β”œβ”€β”€ 0002_steady_xavin.sql
β”‚   β”‚   β”‚   └── meta
β”‚   β”‚   β”‚       β”œβ”€β”€ 0000_snapshot.json
β”‚   β”‚   β”‚       β”œβ”€β”€ 0001_snapshot.json
β”‚   β”‚   β”‚       β”œβ”€β”€ 0002_snapshot.json
β”‚   β”‚   β”‚       └── _journal.json
β”‚   β”‚   β”œβ”€β”€ package.json
β”‚   β”‚   β”œβ”€β”€ src
β”‚   β”‚   β”‚   β”œβ”€β”€ app.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ config
β”‚   β”‚   β”‚   β”‚   └── env.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ db
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ enable-postgis.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ index.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ redis.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ run-migrations.ts
β”‚   β”‚   β”‚   β”‚   └── seed.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ index.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ jobs
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ deadRoomCleanup.ts
β”‚   β”‚   β”‚   β”‚   └── summarizeRoom.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ plugins
β”‚   β”‚   β”‚   β”œβ”€β”€ routes
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ auth.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ health.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ rooms.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ test-db.ts
β”‚   β”‚   β”‚   β”‚   └── waitlist.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ services
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ geocoding.ts
β”‚   β”‚   β”‚   β”‚   └── queue.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ test_inject.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ utils
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ auth.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ logger.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ metrics.ts
β”‚   β”‚   β”‚   β”‚   └── response.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ websocket
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ pubsub.ts
β”‚   β”‚   β”‚   β”‚   └── wsHandler.ts
β”‚   β”‚   β”‚   └── worker.ts
β”‚   β”‚   β”œβ”€β”€ test_inject.ts
β”‚   β”‚   β”œβ”€β”€ test_ws.ts
β”‚   β”‚   └── tsconfig.json
β”‚   └── shared
β”‚       β”œβ”€β”€ package.json
β”‚       β”œβ”€β”€ src
β”‚       β”‚   β”œβ”€β”€ index.d.ts
β”‚       β”‚   β”œβ”€β”€ index.js
β”‚       β”‚   β”œβ”€β”€ index.ts
β”‚       β”‚   β”œβ”€β”€ schema.d.ts
β”‚       β”‚   β”œβ”€β”€ schema.js
β”‚       β”‚   └── schema.ts
β”‚       β”œβ”€β”€ test_schema.ts
β”‚       β”œβ”€β”€ test_zod_bug.ts
β”‚       └── tsconfig.json
β”œβ”€β”€ .env.example
β”œβ”€β”€ .gitignore
β”œβ”€β”€ .nvmrc
β”œβ”€β”€ CONTRIBUTING.md
β”œβ”€β”€ LICENSE
β”œβ”€β”€ README.md
β”œβ”€β”€ deploy.md
β”œβ”€β”€ netlify.toml
β”œβ”€β”€ package-lock.json
β”œβ”€β”€ package.json
β”œβ”€β”€ docker-compose.yml
β”œβ”€β”€ drizzle.config.ts
β”œβ”€β”€ generate-keys.js
β”œβ”€β”€ generated-icon.png
β”œβ”€β”€ postcss.config.js
β”œβ”€β”€ render.yaml
β”œβ”€β”€ replit.md
β”œβ”€β”€ tailwind.config.ts
β”œβ”€β”€ test_api.js
β”œβ”€β”€ theme.json
β”œβ”€β”€ tsconfig.json
└── vite.config.ts

πŸ› οΈ Getting Started Locally

Because IntelliCircle is a strictly defined monorepo, running npm run dev in the root folder will fail. You must run the Client and Server as separate, concurrent processes.

Prerequisites

  1. Node.js v20+
  2. PostgreSQL instance with PostGIS installed.
  3. Redis instance (Local or Upstash Serverless).
  4. Environment variables configured properly (See .env.example in both client and server packages).

Step 1: Start the Backend Layer

The Fastify server builds the DB connection pool and spins up the WebSocket server on port 8080.

# Terminal 1
cd packages/server
npm i
npm run db:push     # Synchronize Drizzle schema to PostgreSQL
npm run dev         # Starts Fastify on http://localhost:8080

Note: To test AI and background jobs, you may also need to start the BullMQ worker in an adjacent terminal using npm run worker.

Step 2: Start the Frontend UI

The Next.js client runs on port 3000 and proxys to the backend.

# Terminal 2
cd packages/client
npm i
npm run dev         # Starts Next.js on http://localhost:3000

Open http://localhost:3000 in your browser. Upon clicking "Find Nearby Rooms", you will be prompted for Location access by your browser.


πŸ—„οΈ Database Management (Drizzle ORM)

Our single source of truth for all schemas lives in packages/shared/src/schema.ts. This ensures that frontend forms and backend queries use the exact same Zod validation objects.

When modifying the database structure in schema.ts, apply changes to your PostgreSQL instance by navigating to packages/server and running:

npm run db:generate   # Generates SQL migration files
npm run db:push       # Pushes migrations to the DB

Note: Depending on your config, some projects rely solely on db:push for rapid prototyping.


🎨 Design & UX

IntelliCircle heavily relies on specific UX principles to convert casual browsers into engaged community members:

  1. Dark, Deep Palette: A high-contrast #0A0A0A background layered with electric indigo (#4F46E5) neon accents creates a secure, tech-forward environment.
  2. Product-Led Growth (PLG): The application delays account creation until after a user has engaged in a chat, bypassing traditional signup walls and significantly boosting conversion.
  3. Typography: We use Inter for hyper-legible chat interfaces and stark formatting.

(See Design Doc.md for our complete design system details).


πŸ› Troubleshooting

  • "Error: Cannot find module '@intellicircle/shared'" Ensure you ran npm install at the root of the monorepo first so NPM links the workspaces.
  • "Port 3000 / 8080 is already in use" You likely have an orphaned Node process.
    • Windows: Get-Process node -ErrorAction SilentlyContinue | Stop-Process -Force
    • Mac/Linux: pkill -f node
  • "Discover Page: 400 Bad Request" Your browser must have Geolocation enabled. If testing locally, ensure you aren't blocking location API requests.
  • "WebSocket Reconnecting..." The Fastify server requires a valid Redis connection string in the .env to bind the Pub/Sub network. Validate your Redis URI.

🀝 Contributing

When contributing to IntelliCircle, please ensure your changes respect the shared boundaries. If you alter the database, update the Zod schemas; the Next.js client and Fastify server will instantly inherit these validation rules.

Designed with 🩡 for local networking.

About

IntelliCircle is a location-based professional networking platform built with React and Express that facilitates real-time connections through interest-based chat rooms powered by WebSockets.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors