initial setup
This commit is contained in:
714
docs/jobforge_mvp_architecture.md
Normal file
714
docs/jobforge_mvp_architecture.md
Normal file
@@ -0,0 +1,714 @@
|
||||
# JobForge MVP - Core Job Application Module
|
||||
|
||||
**Version:** 1.0.0 MVP
|
||||
**Status:** Development Phase 1
|
||||
**Date:** July 2025
|
||||
**Scope:** Core job application workflow with essential features
|
||||
**Target:** Personal use for concept validation and testing
|
||||
|
||||
---
|
||||
|
||||
## 📋 MVP Scope & Objectives
|
||||
|
||||
### Core Functionality
|
||||
- **User Authentication**: Basic login/signup system
|
||||
- **Job Application Creation**: Add new applications with job description and URL
|
||||
- **3-Phase AI Workflow**: Research → Resume → Cover Letter generation
|
||||
- **Document Management**: View and edit generated documents
|
||||
- **Navigation Interface**: Sidebar + top bar for seamless workflow navigation
|
||||
|
||||
### MVP Goals
|
||||
- Validate core AI workflow effectiveness
|
||||
- Test user experience with Dash + Mantine interface
|
||||
- Prove concept with personal job application journey
|
||||
- Establish foundation for Phase 2 (post-application features)
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ MVP Architecture
|
||||
|
||||
### System Overview
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "Frontend (Dash + Mantine)"
|
||||
UI[Main UI]
|
||||
SIDEBAR[Application Sidebar]
|
||||
TOPBAR[Navigation Top Bar]
|
||||
EDITOR[Document Editor]
|
||||
end
|
||||
|
||||
subgraph "Backend API (FastAPI)"
|
||||
AUTH[Authentication]
|
||||
APP[Application Service]
|
||||
AI[AI Orchestrator]
|
||||
DOC[Document Service]
|
||||
end
|
||||
|
||||
subgraph "AI Agents"
|
||||
RESEARCH[Research Agent]
|
||||
RESUME[Resume Optimizer]
|
||||
COVER[Cover Letter Generator]
|
||||
end
|
||||
|
||||
subgraph "Data Storage"
|
||||
PG[(PostgreSQL + pgvector)]
|
||||
FILES[Document Storage]
|
||||
end
|
||||
|
||||
subgraph "External AI"
|
||||
CLAUDE[Claude AI]
|
||||
OPENAI[OpenAI Embeddings]
|
||||
end
|
||||
|
||||
UI --> AUTH
|
||||
UI --> APP
|
||||
UI --> DOC
|
||||
APP --> AI
|
||||
AI --> RESEARCH
|
||||
AI --> RESUME
|
||||
AI --> COVER
|
||||
APP --> PG
|
||||
DOC --> FILES
|
||||
RESEARCH --> CLAUDE
|
||||
RESUME --> CLAUDE
|
||||
COVER --> CLAUDE
|
||||
AI --> OPENAI
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔐 User Authentication (MVP)
|
||||
|
||||
### Simple Authentication System
|
||||
```python
|
||||
class AuthenticationService:
|
||||
"""Basic user authentication for MVP"""
|
||||
|
||||
async def register_user(self, email: str, password: str, name: str) -> User:
|
||||
"""Register new user account"""
|
||||
|
||||
async def authenticate_user(self, email: str, password: str) -> AuthResult:
|
||||
"""Login user and return JWT token"""
|
||||
|
||||
async def verify_token(self, token: str) -> User:
|
||||
"""Verify JWT token and return user"""
|
||||
|
||||
async def logout_user(self, user_id: str) -> None:
|
||||
"""Logout user session"""
|
||||
```
|
||||
|
||||
### Database Schema (Users)
|
||||
```sql
|
||||
-- Basic user table for MVP
|
||||
CREATE TABLE users (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
email VARCHAR(255) UNIQUE NOT NULL,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
full_name VARCHAR(255) NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Enable basic row level security
|
||||
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Job Application Module
|
||||
|
||||
### Core Application Workflow
|
||||
```python
|
||||
class ApplicationService:
|
||||
"""Core job application management"""
|
||||
|
||||
async def create_application(self, user_id: str, job_data: JobApplicationData) -> Application:
|
||||
"""Create new job application with job description and URL"""
|
||||
|
||||
async def get_user_applications(self, user_id: str) -> List[Application]:
|
||||
"""Get all applications for user"""
|
||||
|
||||
async def get_application(self, user_id: str, app_id: str) -> Application:
|
||||
"""Get specific application with documents"""
|
||||
|
||||
async def update_application_status(self, user_id: str, app_id: str, status: str) -> None:
|
||||
"""Update application status through workflow phases"""
|
||||
```
|
||||
|
||||
### Application Data Model
|
||||
```python
|
||||
class JobApplicationData(BaseModel):
|
||||
"""Input data for creating new application"""
|
||||
job_url: Optional[str] = None
|
||||
job_description: str
|
||||
company_name: str
|
||||
role_title: str
|
||||
location: Optional[str] = None
|
||||
priority_level: str = "medium"
|
||||
additional_context: Optional[str] = None
|
||||
|
||||
class Application(BaseModel):
|
||||
"""Core application entity"""
|
||||
id: str
|
||||
user_id: str
|
||||
name: str # Auto-generated: company_role_YYYY_MM_DD
|
||||
company_name: str
|
||||
role_title: str
|
||||
job_url: Optional[str]
|
||||
job_description: str
|
||||
status: ApplicationStatus # draft, research_complete, resume_ready, cover_letter_ready
|
||||
|
||||
# Phase completion tracking
|
||||
research_completed: bool = False
|
||||
resume_optimized: bool = False
|
||||
cover_letter_generated: bool = False
|
||||
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
```
|
||||
|
||||
### Database Schema (Applications)
|
||||
```sql
|
||||
CREATE TABLE applications (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
company_name VARCHAR(255) NOT NULL,
|
||||
role_title VARCHAR(255) NOT NULL,
|
||||
job_url TEXT,
|
||||
job_description TEXT NOT NULL,
|
||||
location VARCHAR(255),
|
||||
priority_level VARCHAR(20) DEFAULT 'medium',
|
||||
status VARCHAR(50) DEFAULT 'draft',
|
||||
|
||||
-- Phase tracking
|
||||
research_completed BOOLEAN DEFAULT FALSE,
|
||||
resume_optimized BOOLEAN DEFAULT FALSE,
|
||||
cover_letter_generated BOOLEAN DEFAULT FALSE,
|
||||
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
ALTER TABLE applications ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
CREATE POLICY user_applications_policy ON applications
|
||||
FOR ALL TO application_user
|
||||
USING (user_id = current_setting('app.current_user_id')::UUID);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🤖 AI Processing Workflow
|
||||
|
||||
### 3-Phase AI Orchestrator
|
||||
```python
|
||||
class AIOrchestrator:
|
||||
"""Orchestrates the 3-phase AI workflow"""
|
||||
|
||||
def __init__(self, research_agent, resume_optimizer, cover_letter_generator):
|
||||
self.research_agent = research_agent
|
||||
self.resume_optimizer = resume_optimizer
|
||||
self.cover_letter_generator = cover_letter_generator
|
||||
|
||||
async def execute_research_phase(self, application_id: str) -> ResearchReport:
|
||||
"""Phase 1: Job analysis and company research"""
|
||||
|
||||
async def execute_resume_optimization(self, application_id: str) -> OptimizedResume:
|
||||
"""Phase 2: Resume optimization based on research"""
|
||||
|
||||
async def execute_cover_letter_generation(self, application_id: str, user_context: str) -> CoverLetter:
|
||||
"""Phase 3: Cover letter generation with user inputs"""
|
||||
```
|
||||
|
||||
### Phase 1: Research Agent
|
||||
```python
|
||||
class ResearchAgent:
|
||||
"""Job description analysis and company research"""
|
||||
|
||||
async def analyze_job_description(self, job_desc: str) -> JobAnalysis:
|
||||
"""Extract requirements, skills, and key information"""
|
||||
|
||||
async def research_company_info(self, company_name: str) -> CompanyIntelligence:
|
||||
"""Basic company research and insights"""
|
||||
|
||||
async def generate_strategic_positioning(self, job_analysis: JobAnalysis) -> StrategicPositioning:
|
||||
"""Determine optimal candidate positioning"""
|
||||
|
||||
async def create_research_report(self, job_desc: str, company_name: str) -> ResearchReport:
|
||||
"""Complete research phase output"""
|
||||
```
|
||||
|
||||
### Phase 2: Resume Optimizer
|
||||
```python
|
||||
class ResumeOptimizer:
|
||||
"""Resume optimization based on job requirements"""
|
||||
|
||||
async def analyze_resume_portfolio(self, user_id: str) -> ResumePortfolio:
|
||||
"""Load and analyze user's resume library"""
|
||||
|
||||
async def optimize_resume_for_job(self, portfolio: ResumePortfolio, research: ResearchReport) -> OptimizedResume:
|
||||
"""Create job-specific optimized resume"""
|
||||
|
||||
async def validate_resume_optimization(self, resume: OptimizedResume) -> ValidationReport:
|
||||
"""Ensure resume meets requirements and constraints"""
|
||||
```
|
||||
|
||||
### Phase 3: Cover Letter Generator
|
||||
```python
|
||||
class CoverLetterGenerator:
|
||||
"""Cover letter generation with user context"""
|
||||
|
||||
async def analyze_writing_style(self, user_id: str) -> WritingStyle:
|
||||
"""Analyze user's writing patterns from reference documents"""
|
||||
|
||||
async def generate_cover_letter(self, research: ResearchReport, resume: OptimizedResume,
|
||||
user_context: str, writing_style: WritingStyle) -> CoverLetter:
|
||||
"""Generate personalized cover letter"""
|
||||
|
||||
async def validate_cover_letter(self, cover_letter: CoverLetter) -> ValidationReport:
|
||||
"""Ensure cover letter quality and authenticity"""
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📄 Document Management
|
||||
|
||||
### Document Storage & Retrieval
|
||||
```python
|
||||
class DocumentService:
|
||||
"""Handle document storage and retrieval"""
|
||||
|
||||
async def save_document(self, user_id: str, app_id: str, doc_type: str, content: str) -> None:
|
||||
"""Save generated document (research, resume, cover letter)"""
|
||||
|
||||
async def get_document(self, user_id: str, app_id: str, doc_type: str) -> Document:
|
||||
"""Retrieve document for viewing/editing"""
|
||||
|
||||
async def update_document(self, user_id: str, app_id: str, doc_type: str, content: str) -> None:
|
||||
"""Update document after user editing"""
|
||||
|
||||
async def get_all_documents(self, user_id: str, app_id: str) -> ApplicationDocuments:
|
||||
"""Get all documents for an application"""
|
||||
```
|
||||
|
||||
### Document Models
|
||||
```python
|
||||
class Document(BaseModel):
|
||||
"""Base document model"""
|
||||
id: str
|
||||
application_id: str
|
||||
document_type: str # research_report, optimized_resume, cover_letter
|
||||
content: str
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
class ApplicationDocuments(BaseModel):
|
||||
"""All documents for an application"""
|
||||
research_report: Optional[Document] = None
|
||||
optimized_resume: Optional[Document] = None
|
||||
cover_letter: Optional[Document] = None
|
||||
```
|
||||
|
||||
### Database Schema (Documents)
|
||||
```sql
|
||||
CREATE TABLE documents (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
application_id UUID REFERENCES applications(id) ON DELETE CASCADE,
|
||||
document_type VARCHAR(50) NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
ALTER TABLE documents ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
CREATE POLICY user_documents_policy ON documents
|
||||
FOR ALL TO application_user
|
||||
USING (
|
||||
application_id IN (
|
||||
SELECT id FROM applications
|
||||
WHERE user_id = current_setting('app.current_user_id')::UUID
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Frontend Interface (Dash + Mantine)
|
||||
|
||||
### Main Application Layout
|
||||
```python
|
||||
class JobForgeApp:
|
||||
"""Main Dash application layout"""
|
||||
|
||||
def create_layout(self):
|
||||
return dmc.MantineProvider([
|
||||
dmc.AppShell([
|
||||
dmc.Navbar([
|
||||
ApplicationSidebar()
|
||||
], width={"base": 300}),
|
||||
dmc.Main([
|
||||
ApplicationTopBar(),
|
||||
MainContent()
|
||||
])
|
||||
])
|
||||
])
|
||||
```
|
||||
|
||||
### Application Sidebar
|
||||
```python
|
||||
class ApplicationSidebar:
|
||||
"""Sidebar with applications list and navigation"""
|
||||
|
||||
def render(self, user_id: str):
|
||||
return dmc.Stack([
|
||||
# New Application Button
|
||||
dmc.Button(
|
||||
"➕ New Application",
|
||||
id="new-app-btn",
|
||||
fullWidth=True,
|
||||
variant="filled"
|
||||
),
|
||||
|
||||
# Applications List
|
||||
dmc.Title("Applications", order=4),
|
||||
dmc.ScrollArea([
|
||||
ApplicationCard(app) for app in self.get_user_applications(user_id)
|
||||
]),
|
||||
|
||||
# Resume Library Section
|
||||
dmc.Divider(),
|
||||
dmc.Title("Resume Library", order=4),
|
||||
ResumeLibrarySection()
|
||||
])
|
||||
|
||||
class ApplicationCard:
|
||||
"""Individual application card in sidebar"""
|
||||
|
||||
def render(self, application: Application):
|
||||
return dmc.Card([
|
||||
dmc.Group([
|
||||
dmc.Text(application.company_name, weight=600),
|
||||
StatusBadge(application.status)
|
||||
]),
|
||||
dmc.Text(application.role_title, size="sm", color="dimmed"),
|
||||
dmc.Text(application.created_at.strftime("%Y-%m-%d"), size="xs")
|
||||
], id=f"app-card-{application.id}")
|
||||
```
|
||||
|
||||
### Application Top Bar Navigation
|
||||
```python
|
||||
class ApplicationTopBar:
|
||||
"""Top navigation bar for application phases"""
|
||||
|
||||
def render(self, application: Application):
|
||||
return dmc.Group([
|
||||
# Phase Navigation Buttons
|
||||
PhaseButton("Research", "research", application.research_completed),
|
||||
PhaseButton("Resume", "resume", application.resume_optimized),
|
||||
PhaseButton("Cover Letter", "cover_letter", application.cover_letter_generated),
|
||||
|
||||
# Application Actions
|
||||
dmc.Spacer(),
|
||||
dmc.ActionIcon(
|
||||
DashIconify(icon="tabler:settings"),
|
||||
id="app-settings-btn"
|
||||
)
|
||||
])
|
||||
|
||||
class PhaseButton:
|
||||
"""Navigation button for each phase"""
|
||||
|
||||
def render(self, label: str, phase: str, completed: bool):
|
||||
icon = "tabler:check" if completed else "tabler:clock"
|
||||
color = "green" if completed else "gray"
|
||||
|
||||
return dmc.Button([
|
||||
DashIconify(icon=icon),
|
||||
dmc.Text(label, ml="xs")
|
||||
],
|
||||
variant="subtle" if not completed else "filled",
|
||||
color=color,
|
||||
id=f"phase-{phase}-btn"
|
||||
)
|
||||
```
|
||||
|
||||
### Document Editor Interface
|
||||
```python
|
||||
class DocumentEditor:
|
||||
"""Markdown document editor with preview"""
|
||||
|
||||
def render(self, document: Document):
|
||||
return dmc.Container([
|
||||
dmc.Grid([
|
||||
# Editor Column
|
||||
dmc.Col([
|
||||
dmc.Title(f"Edit {document.document_type.replace('_', ' ').title()}", order=3),
|
||||
dmc.Textarea(
|
||||
value=document.content,
|
||||
placeholder="Document content...",
|
||||
minRows=20,
|
||||
autosize=True,
|
||||
id=f"editor-{document.document_type}"
|
||||
),
|
||||
dmc.Group([
|
||||
dmc.Button("Save Changes", id="save-btn"),
|
||||
dmc.Button("Cancel", variant="outline", id="cancel-btn")
|
||||
])
|
||||
], span=6),
|
||||
|
||||
# Preview Column
|
||||
dmc.Col([
|
||||
dmc.Title("Preview", order=3),
|
||||
dmc.Container([
|
||||
dcc.Markdown(document.content, id="preview-content")
|
||||
], style={"border": "1px solid #e0e0e0", "padding": "1rem", "minHeight": "500px"})
|
||||
], span=6)
|
||||
])
|
||||
])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🗄️ MVP Database Schema
|
||||
|
||||
### Complete Database Setup
|
||||
```sql
|
||||
-- Enable required extensions
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||
CREATE EXTENSION IF NOT EXISTS vector;
|
||||
|
||||
-- Users table
|
||||
CREATE TABLE users (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
email VARCHAR(255) UNIQUE NOT NULL,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
full_name VARCHAR(255) NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Applications table
|
||||
CREATE TABLE applications (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
company_name VARCHAR(255) NOT NULL,
|
||||
role_title VARCHAR(255) NOT NULL,
|
||||
job_url TEXT,
|
||||
job_description TEXT NOT NULL,
|
||||
location VARCHAR(255),
|
||||
priority_level VARCHAR(20) DEFAULT 'medium',
|
||||
status VARCHAR(50) DEFAULT 'draft',
|
||||
|
||||
research_completed BOOLEAN DEFAULT FALSE,
|
||||
resume_optimized BOOLEAN DEFAULT FALSE,
|
||||
cover_letter_generated BOOLEAN DEFAULT FALSE,
|
||||
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Documents table
|
||||
CREATE TABLE documents (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
application_id UUID REFERENCES applications(id) ON DELETE CASCADE,
|
||||
document_type VARCHAR(50) NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW(),
|
||||
|
||||
UNIQUE(application_id, document_type)
|
||||
);
|
||||
|
||||
-- Resume library table
|
||||
CREATE TABLE user_resumes (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
focus_area VARCHAR(100),
|
||||
is_primary BOOLEAN DEFAULT FALSE,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Basic vector embeddings (for future enhancement)
|
||||
CREATE TABLE document_embeddings (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
document_id UUID REFERENCES documents(id) ON DELETE CASCADE,
|
||||
embedding vector(1536),
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Row Level Security
|
||||
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE applications ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE documents ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE user_resumes ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- Security policies
|
||||
CREATE POLICY user_own_data ON applications FOR ALL USING (user_id = current_setting('app.current_user_id')::UUID);
|
||||
CREATE POLICY user_own_documents ON documents FOR ALL USING (
|
||||
application_id IN (SELECT id FROM applications WHERE user_id = current_setting('app.current_user_id')::UUID)
|
||||
);
|
||||
CREATE POLICY user_own_resumes ON user_resumes FOR ALL USING (user_id = current_setting('app.current_user_id')::UUID);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 MVP Development Plan
|
||||
|
||||
### Development Phases
|
||||
|
||||
#### **Week 1-2: Foundation Setup**
|
||||
- Docker development environment
|
||||
- PostgreSQL database with basic schema
|
||||
- FastAPI backend with authentication endpoints
|
||||
- Basic Dash + Mantine frontend structure
|
||||
|
||||
#### **Week 3-4: Core Application Module**
|
||||
- Application creation and listing
|
||||
- Database integration with user isolation
|
||||
- Basic sidebar and navigation UI
|
||||
- Application status tracking
|
||||
|
||||
#### **Week 5-6: AI Workflow Implementation**
|
||||
- Research Agent with Claude integration
|
||||
- Resume Optimizer with portfolio handling
|
||||
- Cover Letter Generator with user context
|
||||
- Document storage and retrieval system
|
||||
|
||||
#### **Week 7-8: Frontend Polish & Integration**
|
||||
- Document editor with markdown support
|
||||
- Real-time status updates during AI processing
|
||||
- Phase navigation and progress tracking
|
||||
- Error handling and user feedback
|
||||
|
||||
### MVP Success Criteria
|
||||
- ✅ User can register/login securely
|
||||
- ✅ User can create job applications with description/URL
|
||||
- ✅ AI generates research report automatically
|
||||
- ✅ AI optimizes resume based on job requirements
|
||||
- ✅ AI generates cover letter with user context
|
||||
- ✅ User can view and edit all generated documents
|
||||
- ✅ Smooth navigation between application phases
|
||||
- ✅ Data persisted securely with user isolation
|
||||
|
||||
---
|
||||
|
||||
## 🐳 Docker Development Setup
|
||||
|
||||
### Development Environment
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: pgvector/pgvector:pg16
|
||||
environment:
|
||||
POSTGRES_DB: jobforge_mvp
|
||||
POSTGRES_USER: jobforge_user
|
||||
POSTGRES_PASSWORD: jobforge_password
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
- ./database/init.sql:/docker-entrypoint-initdb.d/init.sql
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.backend
|
||||
ports:
|
||||
- "8000:8000"
|
||||
environment:
|
||||
- DATABASE_URL=postgresql+asyncpg://jobforge_user:jobforge_password@postgres:5432/jobforge_mvp
|
||||
- CLAUDE_API_KEY=${CLAUDE_API_KEY}
|
||||
- OPENAI_API_KEY=${OPENAI_API_KEY}
|
||||
volumes:
|
||||
- ./src:/app/src
|
||||
depends_on:
|
||||
- postgres
|
||||
command: uvicorn src.backend.main:app --host 0.0.0.0 --port 8000 --reload
|
||||
|
||||
frontend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.frontend
|
||||
ports:
|
||||
- "8501:8501"
|
||||
environment:
|
||||
- BACKEND_URL=http://backend:8000
|
||||
volumes:
|
||||
- ./src/frontend:/app/src/frontend
|
||||
depends_on:
|
||||
- backend
|
||||
command: python src/frontend/main.py
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📁 MVP Project Structure
|
||||
|
||||
```
|
||||
jobforge-mvp/
|
||||
├── docker-compose.yml
|
||||
├── Dockerfile.backend
|
||||
├── Dockerfile.frontend
|
||||
├── requirements-backend.txt
|
||||
├── requirements-frontend.txt
|
||||
├── .env.example
|
||||
├── database/
|
||||
│ └── init.sql
|
||||
├── src/
|
||||
│ ├── backend/
|
||||
│ │ ├── main.py
|
||||
│ │ ├── api/
|
||||
│ │ │ ├── auth.py
|
||||
│ │ │ ├── applications.py
|
||||
│ │ │ ├── documents.py
|
||||
│ │ │ └── processing.py
|
||||
│ │ ├── services/
|
||||
│ │ │ ├── auth_service.py
|
||||
│ │ │ ├── application_service.py
|
||||
│ │ │ ├── document_service.py
|
||||
│ │ │ └── ai_orchestrator.py
|
||||
│ │ ├── database/
|
||||
│ │ │ ├── connection.py
|
||||
│ │ │ └── models.py
|
||||
│ │ └── models/
|
||||
│ │ ├── requests.py
|
||||
│ │ └── responses.py
|
||||
│ ├── frontend/
|
||||
│ │ ├── main.py
|
||||
│ │ ├── components/
|
||||
│ │ │ ├── sidebar.py
|
||||
│ │ │ ├── topbar.py
|
||||
│ │ │ └── editor.py
|
||||
│ │ ├── pages/
|
||||
│ │ │ ├── login.py
|
||||
│ │ │ ├── dashboard.py
|
||||
│ │ │ └── application.py
|
||||
│ │ └── api_client/
|
||||
│ │ └── client.py
|
||||
│ ├── agents/
|
||||
│ │ ├── research_agent.py
|
||||
│ │ ├── resume_optimizer.py
|
||||
│ │ ├── cover_letter_generator.py
|
||||
│ │ └── claude_client.py
|
||||
│ └── helpers/
|
||||
│ ├── validators.py
|
||||
│ └── formatters.py
|
||||
└── user_data/
|
||||
└── resumes/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*This MVP architecture focuses on delivering the core job application workflow with essential features. It establishes the foundation for Phase 2 development while providing immediate value for personal job application management and concept validation.*
|
||||
Reference in New Issue
Block a user