AI-powered interview evaluation platform — upload a resume, get instant AI analysis, generate tailored interview questions, score candidates, and archive everything in one elegant app.
| Feature | Description |
|---|---|
| 🔐 Authentication | Register, Login, Forgot Password (email passcode) |
| 📁 Projects | Create/edit/delete projects with tech stack configuration |
| 👥 Roles | Define roles linked to projects |
| ❓ Questions | Build a reusable question bank linked to roles |
| 🤖 AI Evaluation | Upload resume → AI analysis → question generation → submit |
| 💾 Save Draft | Auto-save & resume evaluation progress at any step |
| 📂 Archives | Browse past evaluations, update status, download PDF reports |
| 🔒 Privacy Policy | Transparent data usage and privacy information |
| 📋 Terms & Conditions | Usage terms and acceptable use policy |
| 📤 Bulk Actions | Export/import projects, roles & questions as JSON for backup or sharing |
git clone https://github.com/nuthanm/lets-evaluate.git
cd lets-evaluate
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txtcp .env.example .envEdit .env with your values (see Configuration below).
streamlit run app.pyOpen http://localhost:8501 in your browser.
Copy .env.example to .env and fill in the values:
# ── OpenAI ────────────────────────────────────────────────────────────────────
OPENAI_API_KEY=your_openai_api_key_here
# ── Email (SMTP) ───────────────────────────────────────────────────────────────
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=your_email@gmail.com
SMTP_PASSWORD=your_app_password_here # NOT your regular password — see below
EMAIL_FROM=your_email@gmail.com
# ── App ────────────────────────────────────────────────────────────────────────
APP_SECRET_KEY=your_secret_key_here_change_this
DATABASE_URL=postgresql://user:password@host:5432/dbnameThe "Forgot Password" feature sends a 6-digit passcode via email. Use an App Password (not your normal login password).
- Enable 2-Step Verification: https://myaccount.google.com/security
- Go to Security → App Passwords (search "App passwords")
- Select Mail + Other (Custom name) → name it "Let's Evaluate"
- Copy the 16-character password and paste into
SMTP_PASSWORD - Set
SMTP_USERNAMEandEMAIL_FROMto your Gmail address
- Sign in at https://account.microsoft.com/security
- Go to Advanced security options → App passwords
- Create a new app password and copy it into
SMTP_PASSWORD - Set
SMTP_USERNAME= your full Outlook email address
- Sign in and go to Account Security: https://login.yahoo.com/account/security
- Enable Two-step verification then create an App Password
- Copy the generated password into
SMTP_PASSWORD - Set
SMTP_USERNAME= your Yahoo email address
⚠️ Important: Never commit your.envfile to version control. It is already listed in.gitignore.
PostgreSQL is required. The app will refuse to start without a valid DATABASE_URL pointing to a PostgreSQL instance.
DATABASE_URL=postgresql://user:password@host:5432/dbnameThe PostgreSQL driver (psycopg2-binary) is already included in requirements.txt — no extra install needed.
postgres://vspostgresql://— SQLAlchemy 2.0+ removed the olderpostgres://dialect alias. The app automatically normalises anypostgres://connection string topostgresql://at startup, so connection strings from Heroku, Neon, Supabase, and similar platforms work without any manual editing.
You do not need Docker or a locally-installed PostgreSQL server. All of the following providers offer a free PostgreSQL database that you can connect to from anywhere — including your local machine or Streamlit Community Cloud:
| Provider | Free tier | Setup time |
|---|---|---|
| Supabase | ✅ Generous free tier | ~2 min |
| Neon | ✅ Free serverless Postgres | ~2 min |
| Railway | ✅ Free starter plan | ~3 min |
Steps (using Supabase as an example):
- Go to https://supabase.com and create a free account
- Create a new project — choose any region
- Go to Project Settings → Database → Connection string and select the URI tab
- Copy the connection string — it will look like one of these:
- Direct:
postgresql://postgres:[PASSWORD]@db.[PROJECT-REF].supabase.co:5432/postgres - Pooler:
postgresql://postgres.[PROJECT-REF]:[PASSWORD]@aws-0-[REGION].pooler.supabase.com:6543/postgres(In the pooler formatpostgres.[PROJECT-REF]is the full username, not two separate fields.)
- Direct:
- Paste it as
DATABASE_URLin your.envfile (or Streamlit Cloud secrets)
⚠️ Common mistake: Supabase usespostgresas both the default username and the default database name. The hostname is different — it always contains dots (e.g.db.abcdef.supabase.co). Do not usepostgresas the hostname.
Yes — because all data lives in the external PostgreSQL database, completely independent of whether the Streamlit app is running, sleeping, or redeployed.
| Scenario | Data persists when app sleeps / restarts? |
|---|---|
DATABASE_URL=postgres://... |
✅ Yes (auto-corrected to postgresql://) |
DATABASE_URL=postgresql://... |
✅ Yes |
DATABASE_URL not set |
❌ App refuses to start — set it to a PostgreSQL URL |
Add DATABASE_URL under App settings → Secrets:
DATABASE_URL = "postgresql://user:password@host:5432/dbname"This app uses OpenAI GPT-4o-mini — the best balance of cost, speed, and quality for:
- Resume parsing & tech stack analysis
- Tailored interview question generation
- Structured JSON output reliability
Why GPT-4o-mini?
- ~95% as capable as GPT-4o for structured text tasks
- 10× cheaper per token vs GPT-4o
- Fast enough for real-time interaction
To switch to a more powerful model, edit utils/ai_utils.py:
return ChatOpenAI(model="gpt-4o", ...) # More capable, higher cost- Push repo to GitHub
- Go to https://share.streamlit.io
- Connect repo, set
app.pyas main file - Add secrets in the Streamlit Cloud dashboard (same keys as
.env) - Deploy — free forever with public repos
Set
DATABASE_URLto a Supabase PostgreSQL URL for persistent cloud storage.
- Create account at https://railway.app
- New Project → Deploy from GitHub
- Add environment variables in the Railway dashboard
- Add a PostgreSQL plugin for the database
- Free starter plan available
- Create account at https://render.com
- New Web Service → connect GitHub repo
- Build command:
pip install -r requirements.txt - Start command:
streamlit run app.py --server.port $PORT --server.address 0.0.0.0 - Free tier available (spins down after inactivity)
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8501
CMD ["streamlit", "run", "app.py", "--server.address", "0.0.0.0"]lets-evaluate/
├── app.py # Landing page (animated workflow)
├── requirements.txt
├── runtime.txt # Python version pin (python-3.12)
├── .env.example # Environment variable template
├── .streamlit/
│ └── config.toml # Theme & upload size config
├── pages/
│ ├── 1_Auth.py # Login / Register / Forgot Password
│ ├── 2_Dashboard.py # Stats & quick navigation
│ ├── 3_Projects.py # Projects CRUD
│ ├── 4_Roles.py # Roles CRUD
│ ├── 5_Questions.py # Questions CRUD
│ ├── 6_Evaluate_Candidate.py # 4-step AI evaluation wizard (with draft save)
│ ├── 7_Archives.py # Evaluation archive + PDF download
│ ├── 8_Privacy_Policy.py # Privacy policy page
│ ├── 9_Terms_Conditions.py # Terms & conditions page
│ └── 10_Bulk_Actions.py # Export / import projects, roles & questions (JSON)
└── utils/
├── database.py # SQLAlchemy models & CRUD helpers
├── auth.py # bcrypt auth + session helpers
├── email_utils.py # SMTP email (Gmail/Outlook/Yahoo)
├── ai_utils.py # OpenAI/LangChain integration
├── pdf_utils.py # ReportLab PDF generation
└── ui.py # Shared UI components (logo, sidebar, CSS)
| Library | Purpose |
|---|---|
streamlit |
Web UI framework |
langchain + langchain-openai + langchain-core |
LLM orchestration |
openai |
GPT-4o-mini API |
sqlalchemy |
Database ORM |
bcrypt |
Password hashing |
reportlab |
PDF report generation |
pillow |
Image processing (logo/favicon) |
python-dotenv |
Environment variable loading |
- Passwords are hashed with bcrypt (never stored in plain text)
- Password reset codes expire after 15 minutes and are single-use
- API keys are loaded from environment variables, never hardcoded
- The database is hosted externally (PostgreSQL), keeping credentials separate from the app
Animated workflow showcase with gradient hero, feature cards, and "Start Evaluate" CTA.
- Left panel: Sign In with email/password
- Right panel: Create Account
- Forgot Password: Two-step flow — enter email → receive 6-digit code → set new password
Stats cards (Projects / Roles / Questions / Evaluations) + quick-access navigation + recent evaluations table.
Grid of project cards with tech stack chips. Add/Edit/Delete with "type Delete to confirm" guard. Linked roles & questions are shown in the confirmation message.
Same as Projects. Roles can be linked to a project (optional). Delete shows linked questions.
Filterable question bank (by role, category, difficulty). Questions can be linked to roles.
4-step wizard:
- Select project + role, enter candidate details, upload resume (PDF/DOCX)
- AI analysis — tech match score, experience level, strengths, concerns, recommendation
- Generate standard questions (AI) + resume-based questions (AI)
- Add evaluator notes, set status, submit
Save Draft: Progress is saved automatically at any step via the 💾 Save Progress button. Drafts can be resumed from the Dashboard or by returning to the page with the draft_id query parameter.
Full evaluation history with filters. Update status per evaluation (Pending / Selected / Rejected / Hold). Download evaluation as a professional PDF.
Describes what data is collected, how it is used, stored, and protected. Accessible to both authenticated and unauthenticated users.
Outlines the acceptable use policy, user responsibilities, and limitations of liability. Accessible to both authenticated and unauthenticated users.
Export: Downloads a single JSON file containing all your projects, roles, and questions — useful for sharing with colleagues or keeping a backup.
Import: Uploads a previously exported JSON file and adds records in bulk.
- Duplicate detection automatically skips records that already exist.
- If a question references a role not yet present in your account, the role is auto-created and linked to that question.
flowchart TD
User(["👤 User (Browser)"])
subgraph StreamlitApp["☁️ Streamlit Application"]
direction TB
Landing["app.py\n🏠 Landing Page"]
subgraph Pages["📄 Pages"]
Auth["1_Auth\n🔐 Login / Register"]
Dashboard["2_Dashboard\n📊 Stats & Navigation"]
Projects["3_Projects\n📁 Projects CRUD"]
Roles["4_Roles\n👥 Roles CRUD"]
Questions["5_Questions\n❓ Question Bank"]
Evaluate["6_Evaluate_Candidate\n🤖 AI Evaluation Wizard"]
Archives["7_Archives\n📂 History & PDF"]
Privacy["8_Privacy_Policy\n🔒 Privacy"]
Terms["9_Terms_Conditions\n📋 Terms"]
BulkActions["10_Bulk_Actions\n📤 Export / Import"]
end
subgraph Utils["🛠️ Utils"]
DB["database.py\nSQLAlchemy ORM & CRUD"]
AuthUtil["auth.py\nbcrypt + session helpers"]
EmailUtil["email_utils.py\nSMTP email"]
AIUtil["ai_utils.py\nLangChain / OpenAI"]
PDFUtil["pdf_utils.py\nReportLab PDF"]
UIUtil["ui.py\nShared CSS & sidebar"]
end
end
subgraph External["🌐 External Services"]
OpenAI["🤖 OpenAI API\n(GPT-4o-mini)"]
SMTP["📧 SMTP Server\n(Gmail / Outlook / Yahoo)"]
PG["🐘 PostgreSQL\n(Supabase / Neon / Railway)"]
end
User -->|HTTP| Landing
Landing --> Pages
Pages --> Utils
AuthUtil --> PG
DB --> PG
AIUtil --> OpenAI
EmailUtil --> SMTP
Pull requests welcome! Please open an issue first to discuss any significant changes.
MIT