mirror of
http://88.130.71.182:3000/BlitTech/contexta_be.git
synced 2026-06-12 23:23:21 +00:00
463 lines
13 KiB
Markdown
463 lines
13 KiB
Markdown
# Contexta — AI Chatbot SaaS Platform
|
|
|
|
A full-stack SaaS platform that lets businesses build custom AI chatbots from their documents, publish them to a marketplace, and optionally export self-hostable code.
|
|
|
|
---
|
|
|
|
## Architecture at a Glance
|
|
|
|
```
|
|
contexta_be/ → FastAPI backend (Python 3.11)
|
|
contexta_fe/ → React + TypeScript frontend (Vite)
|
|
```
|
|
|
|
**Key tech stack:**
|
|
- **Backend**: FastAPI, Supabase (auth + DB), Qdrant (vectors), LangChain
|
|
- **Frontend**: React 18, TypeScript, Tailwind CSS, TanStack Query, Zustand
|
|
- **AI**: Fireworks AI (free tier), OpenAI, Anthropic, Google Gemini
|
|
- **Payments**: Stripe
|
|
- **Infra**: Docker, Railway/Vercel-ready
|
|
|
|
---
|
|
|
|
## Prerequisites
|
|
|
|
| Tool | Version | Purpose |
|
|
|------|---------|---------|
|
|
| Python | 3.11+ | Backend runtime |
|
|
| Node.js | 18+ | Frontend build |
|
|
| Git | any | Version control |
|
|
|
|
**External services you need to set up (all have free tiers):**
|
|
|
|
| Service | What for | Free tier? |
|
|
|---------|----------|------------|
|
|
| [Supabase](https://supabase.com) | Database + Auth | ✅ Yes |
|
|
| [Qdrant Cloud](https://cloud.qdrant.io) | Vector search | ✅ Yes (1GB) |
|
|
| [Fireworks AI](https://fireworks.ai) | LLM (free models) | ✅ Yes |
|
|
| [OpenAI](https://platform.openai.com) | Embeddings + GPT-4 | Pay-per-use |
|
|
| [Stripe](https://stripe.com) | Payments | ✅ Test mode |
|
|
|
|
---
|
|
|
|
## Part 1: Supabase Setup (Database + Auth)
|
|
|
|
### 1.1 Create a Supabase project
|
|
|
|
1. Go to [supabase.com](https://supabase.com) → New project
|
|
2. Save your **Project URL** and both keys (anon + service_role)
|
|
|
|
### 1.2 Run the database schema
|
|
|
|
1. In your Supabase dashboard → **SQL Editor**
|
|
2. Open `contexta_be/supabase_schema.sql`
|
|
3. Paste the entire file → Run
|
|
|
|
This creates all tables, RLS policies, and triggers.
|
|
|
|
### 1.3 Enable Email Auth
|
|
|
|
1. In Supabase → **Authentication** → **Providers**
|
|
2. Ensure "Email" is enabled
|
|
3. Optionally disable "Confirm email" for faster testing
|
|
|
|
---
|
|
|
|
## Part 2: Qdrant Setup (Vector Database)
|
|
|
|
### Option A: Qdrant Cloud (recommended)
|
|
|
|
1. Go to [cloud.qdrant.io](https://cloud.qdrant.io) → Create cluster (free tier)
|
|
2. Get your **Cluster URL** and **API Key**
|
|
|
|
### Option B: Local Qdrant (for development)
|
|
|
|
```bash
|
|
docker run -p 6333:6333 qdrant/qdrant
|
|
```
|
|
|
|
Then set `QDRANT_URL=http://localhost:6333` and leave `QDRANT_API_KEY` empty.
|
|
|
|
---
|
|
|
|
## Part 3: Backend Setup (`contexta_be`)
|
|
|
|
### 3.1 Clone and configure
|
|
|
|
```bash
|
|
cd contexta_be
|
|
cp .env.example .env
|
|
```
|
|
|
|
Edit `.env` with your credentials:
|
|
|
|
```env
|
|
# App
|
|
APP_ENV=development
|
|
APP_SECRET_KEY=change-this-to-a-random-string-in-production
|
|
ALLOWED_ORIGINS=http://localhost:5173,http://localhost:3000
|
|
|
|
# Supabase (from your project settings)
|
|
SUPABASE_URL=https://your-project.supabase.co
|
|
SUPABASE_ANON_KEY=eyJ...
|
|
SUPABASE_SERVICE_ROLE_KEY=eyJ...
|
|
|
|
# Qdrant
|
|
QDRANT_URL=https://your-cluster.qdrant.io
|
|
QDRANT_API_KEY=your-key-here
|
|
|
|
# LLM - MINIMUM REQUIRED: OpenAI (for embeddings)
|
|
OPENAI_API_KEY=sk-...
|
|
|
|
# LLM - Optional but recommended
|
|
FIREWORKS_API_KEY=fw_... # Free models for starter plan
|
|
ANTHROPIC_API_KEY=sk-ant-... # Claude models
|
|
GOOGLE_API_KEY=AIza... # Gemini models
|
|
|
|
# Stripe (use test keys for development)
|
|
STRIPE_SECRET_KEY=sk_test_...
|
|
STRIPE_WEBHOOK_SECRET=whsec_...
|
|
STRIPE_STARTER_PRICE_ID=price_...
|
|
STRIPE_PRO_PRICE_ID=price_...
|
|
```
|
|
|
|
### 3.2 Create virtual environment and install
|
|
|
|
```bash
|
|
python -m venv venv
|
|
source venv/bin/activate # On Windows: venv\Scripts\activate
|
|
pip install -r requirements.txt
|
|
```
|
|
|
|
### 3.3 Start the backend
|
|
|
|
```bash
|
|
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
|
|
```
|
|
|
|
The API will be available at:
|
|
- **API**: http://localhost:8000
|
|
- **Swagger docs**: http://localhost:8000/docs
|
|
- **Health check**: http://localhost:8000/health
|
|
|
|
### 3.4 Docker alternative
|
|
|
|
```bash
|
|
# Copy and edit .env first
|
|
cp .env.example .env
|
|
# Edit .env...
|
|
|
|
# Start with Docker (includes Qdrant locally)
|
|
docker-compose up -d
|
|
```
|
|
|
|
---
|
|
|
|
## Part 4: Frontend Setup (`contexta_fe`)
|
|
|
|
### 4.1 Install dependencies
|
|
|
|
```bash
|
|
cd contexta_fe
|
|
npm install
|
|
```
|
|
|
|
### 4.2 Configure environment
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
`.env` content:
|
|
```env
|
|
VITE_API_URL=http://localhost:8000
|
|
VITE_APP_NAME=Contexta
|
|
```
|
|
|
|
### 4.3 Start the frontend
|
|
|
|
```bash
|
|
npm run dev
|
|
```
|
|
|
|
Frontend available at: http://localhost:5173
|
|
|
|
---
|
|
|
|
## Part 5: Stripe Setup (Payments)
|
|
|
|
### 5.1 Create Stripe products
|
|
|
|
1. Go to [dashboard.stripe.com](https://dashboard.stripe.com) → Products
|
|
2. Create **Starter** product → Add price → $39/month recurring
|
|
3. Create **Pro** product → Add price → $119/month recurring
|
|
4. Copy the **Price IDs** (start with `price_`) → paste into backend `.env`
|
|
|
|
### 5.2 Set up webhook (for local testing)
|
|
|
|
Install Stripe CLI:
|
|
```bash
|
|
# Mac
|
|
brew install stripe/stripe-cli/stripe
|
|
|
|
# Others: https://stripe.com/docs/stripe-cli
|
|
```
|
|
|
|
Forward webhooks to local:
|
|
```bash
|
|
stripe listen --forward-to localhost:8000/api/v1/billing/webhook
|
|
```
|
|
|
|
Copy the webhook signing secret → paste into `STRIPE_WEBHOOK_SECRET` in `.env`
|
|
|
|
### 5.3 Test a subscription
|
|
|
|
Use Stripe test card: `4242 4242 4242 4242` with any future expiry and any CVC.
|
|
|
|
---
|
|
|
|
## Part 6: Testing the Full Flow
|
|
|
|
### 6.1 Create an account
|
|
|
|
1. Open http://localhost:5173
|
|
2. Click "Get started free" or go to http://localhost:5173/signup
|
|
3. Fill in company name, email, password
|
|
|
|
### 6.2 Create a chatbot
|
|
|
|
1. After login → **Dashboard** → **New Chatbot**
|
|
2. Enter a name and configure settings
|
|
3. Click **Save**
|
|
|
|
### 6.3 Upload documents
|
|
|
|
1. In the chatbot builder → **Documents** tab
|
|
2. Drag and drop a PDF, DOCX, or CSV file
|
|
3. Wait for processing (status changes to "completed" with chunk count)
|
|
|
|
> ⚠️ Document processing requires a valid OpenAI API key for embeddings and a working Qdrant instance.
|
|
|
|
### 6.4 Test in preview mode
|
|
|
|
1. In the chatbot builder → **Preview** tab
|
|
2. Type a question related to your uploaded document
|
|
3. The chatbot should answer based on the document content
|
|
|
|
### 6.5 Publish to marketplace (requires paid plan)
|
|
|
|
1. Subscribe to Starter or Pro (Stripe checkout)
|
|
2. Back in Dashboard → click **Publish** on your chatbot
|
|
3. Visit http://localhost:5173/marketplace to see it listed
|
|
|
|
### 6.6 Export code (Pro plan)
|
|
|
|
In the chatbot builder → click **Export Code** button → downloads a ZIP containing:
|
|
- `backend/` — Complete FastAPI app with your vectors
|
|
- `frontend/` — React TypeScript chat widget
|
|
- `setup.py` — Interactive setup wizard
|
|
- `QUICK_START.md` — 5-minute deployment guide
|
|
|
|
---
|
|
|
|
## API Reference
|
|
|
|
The complete API is documented via Swagger at http://localhost:8000/docs when the backend is running.
|
|
|
|
### Key endpoints
|
|
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| POST | `/api/v1/auth/signup` | Create account |
|
|
| POST | `/api/v1/auth/login` | Login |
|
|
| GET | `/api/v1/auth/me` | Current user |
|
|
| GET | `/api/v1/chatbots` | List your chatbots |
|
|
| POST | `/api/v1/chatbots` | Create chatbot |
|
|
| PUT | `/api/v1/chatbots/{id}` | Update chatbot |
|
|
| POST | `/api/v1/chatbots/{id}/publish` | Publish to marketplace |
|
|
| POST | `/api/v1/chatbots/{id}/export` | Download code export (Pro) |
|
|
| POST | `/api/v1/chatbots/{chatbot_id}/documents` | Upload document |
|
|
| POST | `/api/v1/chat/{chatbot_id}` | Send chat message |
|
|
| GET | `/api/v1/marketplace/chatbots` | Browse marketplace |
|
|
| POST | `/api/v1/billing/checkout` | Create Stripe checkout |
|
|
|
|
---
|
|
|
|
## Deployment
|
|
|
|
### Backend → Railway
|
|
|
|
```bash
|
|
# Install Railway CLI
|
|
npm i -g @railway/cli
|
|
|
|
cd contexta_be
|
|
railway login
|
|
railway init
|
|
railway up
|
|
```
|
|
|
|
Set all environment variables in Railway dashboard → Variables tab.
|
|
|
|
### Frontend → Vercel
|
|
|
|
```bash
|
|
npm i -g vercel
|
|
|
|
cd contexta_fe
|
|
vercel
|
|
```
|
|
|
|
Set `VITE_API_URL` to your Railway backend URL in Vercel environment variables.
|
|
|
|
### Update CORS
|
|
|
|
Once deployed, update `ALLOWED_ORIGINS` in backend to include your Vercel domain:
|
|
```
|
|
ALLOWED_ORIGINS=https://your-app.vercel.app
|
|
```
|
|
|
|
---
|
|
|
|
## Minimal Setup (Testing Only, No Real AI)
|
|
|
|
If you want to test the UI without real API keys, you can:
|
|
|
|
1. Run only the frontend
|
|
2. Mock the API responses
|
|
|
|
For the quickest backend test without Qdrant/OpenAI, comment out the vector store initialization in startup and the RAG processing in document upload. The chat will still work but won't return relevant answers.
|
|
|
|
---
|
|
|
|
## Environment Variables Reference
|
|
|
|
### Backend (`contexta_be/.env`)
|
|
|
|
| Variable | Required | Description |
|
|
|----------|----------|-------------|
|
|
| `SUPABASE_URL` | ✅ | Supabase project URL |
|
|
| `SUPABASE_ANON_KEY` | ✅ | Supabase anon key |
|
|
| `SUPABASE_SERVICE_ROLE_KEY` | ✅ | Supabase service role key |
|
|
| `QDRANT_URL` | ✅ | Qdrant cluster URL |
|
|
| `QDRANT_API_KEY` | ⚠️ | Required for Qdrant Cloud |
|
|
| `OPENAI_API_KEY` | ✅ | Required for embeddings |
|
|
| `FIREWORKS_API_KEY` | ⚠️ | For free-tier Llama/Mixtral models |
|
|
| `ANTHROPIC_API_KEY` | ⚠️ | For Claude models (Pro plan) |
|
|
| `GOOGLE_API_KEY` | ⚠️ | For Gemini models (Pro plan) |
|
|
| `STRIPE_SECRET_KEY` | ⚠️ | For billing (use test key in dev) |
|
|
| `STRIPE_WEBHOOK_SECRET` | ⚠️ | For Stripe webhooks |
|
|
| `STRIPE_STARTER_PRICE_ID` | ⚠️ | Stripe price ID for Starter plan |
|
|
| `STRIPE_PRO_PRICE_ID` | ⚠️ | Stripe price ID for Pro plan |
|
|
| `ALLOWED_ORIGINS` | ✅ | Comma-separated CORS origins |
|
|
| `APP_SECRET_KEY` | ✅ | Random secret for production |
|
|
|
|
### Frontend (`contexta_fe/.env`)
|
|
|
|
| Variable | Required | Description |
|
|
|----------|----------|-------------|
|
|
| `VITE_API_URL` | ✅ | Backend API URL |
|
|
|
|
---
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
contexta_be/
|
|
├── app/
|
|
│ ├── main.py # FastAPI app + router registration
|
|
│ ├── config.py # Settings + plan limits
|
|
│ ├── database.py # Supabase client
|
|
│ ├── models.py # Pydantic models
|
|
│ ├── dependencies.py # Auth middleware
|
|
│ ├── routers/
|
|
│ │ ├── auth.py # Signup, login, me
|
|
│ │ ├── chatbots.py # CRUD + publish + export
|
|
│ │ ├── documents.py # File upload + processing
|
|
│ │ ├── chat.py # RAG chat endpoint
|
|
│ │ ├── marketplace.py # Public chatbot listing
|
|
│ │ └── billing.py # Stripe checkout + webhooks
|
|
│ └── services/
|
|
│ ├── vector_store.py # Qdrant operations
|
|
│ ├── embeddings.py # OpenAI embeddings
|
|
│ ├── document_processor.py # PDF/DOCX/CSV parsing
|
|
│ ├── llm.py # Multi-provider LLM routing
|
|
│ ├── rag.py # RAG pipeline
|
|
│ └── code_export.py # ZIP code generation
|
|
├── supabase_schema.sql # Database schema (run once)
|
|
├── requirements.txt
|
|
├── Dockerfile
|
|
└── docker-compose.yml
|
|
|
|
contexta_fe/
|
|
├── src/
|
|
│ ├── main.tsx # Entry point
|
|
│ ├── App.tsx # Router + routes
|
|
│ ├── index.css # Tailwind + global styles
|
|
│ ├── types/index.ts # TypeScript interfaces
|
|
│ ├── services/api.ts # API client (axios)
|
|
│ ├── store/authStore.ts # Zustand auth state
|
|
│ ├── lib/utils.ts # Helpers + constants
|
|
│ ├── components/
|
|
│ │ ├── ui.tsx # Reusable UI (Button, Input, Card...)
|
|
│ │ ├── Layout.tsx # App shell with sidebar
|
|
│ │ └── ChatInterface.tsx # Chat UI with sources
|
|
│ └── pages/
|
|
│ ├── LandingPage.tsx
|
|
│ ├── AuthPages.tsx # Login + Signup
|
|
│ ├── DashboardPage.tsx
|
|
│ ├── ChatbotBuilderPage.tsx # Builder + docs + preview
|
|
│ ├── MarketplacePage.tsx
|
|
│ ├── PricingPage.tsx
|
|
│ └── SettingsPage.tsx
|
|
├── package.json
|
|
├── vite.config.ts
|
|
└── tailwind.config.js
|
|
```
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### "CORS error" in browser
|
|
→ Check `ALLOWED_ORIGINS` in backend `.env` includes your frontend URL
|
|
|
|
### "Could not connect to Qdrant"
|
|
→ Check `QDRANT_URL` is correct and the cluster is running
|
|
→ For local Docker: ensure the qdrant service is started
|
|
|
|
### "Invalid or expired token" on API calls
|
|
→ The Supabase JWT has expired. Log out and log back in.
|
|
→ Check `SUPABASE_SERVICE_ROLE_KEY` is correct
|
|
|
|
### Document processing stuck on "processing"
|
|
→ Check OpenAI API key is valid
|
|
→ Check Qdrant connection
|
|
→ Check backend logs: `docker logs contexta-api` or terminal output
|
|
|
|
### "Upgrade to publish" even after Stripe payment
|
|
→ Ensure Stripe webhook is configured and received the `checkout.session.completed` event
|
|
→ Check backend logs for webhook processing
|
|
→ For local testing, use `stripe listen --forward-to localhost:8000/api/v1/billing/webhook`
|
|
|
|
### Chat returns "I don't have information about that"
|
|
→ Document processing may have failed — check document status in builder
|
|
→ The uploaded content may not be relevant to the question
|
|
→ Try re-uploading the document
|
|
|
|
---
|
|
|
|
## Development Tips
|
|
|
|
- **Backend hot reload**: `uvicorn app.main:app --reload` watches for file changes
|
|
- **Frontend hot reload**: `npm run dev` automatically reloads
|
|
- **API testing**: Use http://localhost:8000/docs (Swagger UI)
|
|
- **Database inspection**: Supabase dashboard → Table Editor
|
|
- **Vector inspection**: Qdrant dashboard at http://localhost:6333/dashboard (local only)
|
|
|
|
---
|
|
|
|
## License
|
|
|
|
MIT — build freely, use commercially.
|