DevStack is an AI-powered developer portfolio generator that turns a GitHub username (and optionally a resume PDF) into:
- a metrics dashboard,
- personalized AI insights,
- and a polished portfolio page with highlighted projects.
The stack is a React + Vite frontend and a FastAPI backend that integrates GitHub and OpenAI.
- What It Does
- Architecture
- Tech Stack
- Project Structure
- Requirements
- Quick Start
- Environment Variables
- Run the App
- API Reference
- Frontend Route Map
- How Data Flows
- Scripts
- Troubleshooting
- Accepts a GitHub username and optional resume PDF.
- Fetches profile + repository data from GitHub.
- Computes aggregate language usage and star totals.
- Generates:
- AI strengths, growth areas, and suggestions.
- Portfolio bio + skill summary.
- Top highlighted projects by stars.
- Renders all of the above in a modern UI.
- Single-page app built with React and Vite.
- Uses React Router for route-driven workflow.
- Calls backend via Axios (
http://localhost:8000/api). - Stores fetched GitHub payload in
localStorage(devstack_github_data) to drive subsequent pages.
- FastAPI app with CORS enabled for local development.
- Exposes endpoints for:
- GitHub data fetch,
- AI suggestions,
- Portfolio content generation,
- Resume PDF text parsing.
- Uses Pydantic models for request/response validation.
- Uses OpenAI client when
OPENAI_API_KEYis present; otherwise returns sensible mock AI responses so app remains usable.
- React 18
- Vite 5
- Tailwind CSS 3
- React Router DOM 6
- Axios
- Lucide React
- Recharts
- Framer Motion
- Python
- FastAPI
- Uvicorn
- Requests
- OpenAI SDK
- Pydantic
- python-dotenv
- pypdf
devstack/
├── frontend/
│ ├── src/
│ │ ├── components/
│ │ ├── pages/
│ │ │ ├── LandingPage.jsx
│ │ │ ├── GithubInputPage.jsx
│ │ │ ├── DashboardPage.jsx
│ │ │ ├── AiInsightsPage.jsx
│ │ │ ├── PortfolioPage.jsx
│ │ │ └── AboutPage.jsx
│ │ ├── services/
│ │ │ └── api.js
│ │ ├── App.jsx
│ │ └── main.jsx
│ └── package.json
├── backend/
│ ├── app/
│ │ ├── main.py
│ │ ├── routes/
│ │ │ └── api.py
│ │ ├── services/
│ │ │ ├── github_service.py
│ │ │ └── ai_service.py
│ │ └── utils/
│ │ └── models.py
│ ├── requirements.txt
│ └── .env.example
└── README.md
- Node.js 18+ and npm
- Python 3.9+ (3.8 may work, but 3.9+ recommended)
- Internet access (for GitHub API and OpenAI API when key is configured)
git clone <your-repo-url>
cd devstackcd backend
python -m venv venvActivate the environment:
- Windows (PowerShell):
.\venv\Scripts\Activate.ps1
- macOS/Linux:
source venv/bin/activate
Install dependencies:
pip install -r requirements.txtCreate .env from .env.example and set your key:
OPENAI_API_KEY="your_openai_key_here"Open a second terminal:
cd frontend
npm installThe backend reads variables from backend/.env.
| Variable | Required | Description |
|---|---|---|
OPENAI_API_KEY |
No | Enables live OpenAI-generated suggestions and portfolio content. If omitted, backend falls back to mock AI output. |
From backend/ with venv activated:
uvicorn app.main:app --reload --port 8000Backend URLs:
- API base:
http://localhost:8000/api - Root health-style message:
http://localhost:8000/ - Interactive docs:
http://localhost:8000/docs
From frontend/:
npm run devFrontend URL:
http://localhost:5173
Base URL: http://localhost:8000/api
Fetches GitHub profile/repo metadata and aggregates.
Request:
{
"username": "octocat"
}Response includes:
user: GitHub profile summaryrepos: non-fork repos (up to 100 fetched/sorted by pushed date)languages: language => repo countlanguage_timeline: year-wise language usage maptotal_stars: sum of stars across included repos
Generates AI insights from portfolio data.
Request shape:
userreposlanguages- optional
resume_text
Response:
{
"strengths": ["..."],
"growth_areas": ["..."],
"suggestions": ["..."],
"visualization_ideas": ["..."]
}Generates portfolio copy and top highlighted projects.
Request shape:
userreposlanguages- optional
resume_text
Response:
{
"bio": "...",
"skill_summary": "...",
"highlighted_projects": [
{
"name": "...",
"description": "...",
"language": "...",
"stargazers_count": 0,
"html_url": "...",
"fork": false
}
]
}Parses uploaded PDF and returns extracted text.
- Content type:
multipart/form-data - Field name:
file - Constraint: file must end with
.pdf
Response:
{
"text": "parsed resume text..."
}| Route | Page | Purpose |
|---|---|---|
/ |
Landing | Product intro and CTA |
/input |
GitHub Input | Username input + optional resume upload |
/dashboard |
Dashboard | Profile stats + language overview |
/insights |
AI Insights | Strengths, growth areas, recommendations |
/portfolio |
Portfolio | Final generated portfolio page |
/about |
About | Product and stack description |
- User submits GitHub username (and optional PDF) on
/input. - Frontend calls:
/resume/parse(if file uploaded),/github/fetch.
- Combined payload is stored in
localStorage. /dashboardreads and visualizes base data./insightssends stored data to/ai/suggestions./portfoliosends stored data to/portfolio/generate.- Generated text + top repos are rendered as portfolio output.
npm run dev- Start Vite dev servernpm run build- Production buildnpm run preview- Preview built appnpm run lint- Run ESLint
No custom script aliases are defined. Run via Uvicorn directly:
uvicorn app.main:app --reload --port 8000-
Backend starts, frontend fails API calls
- Confirm backend is running on port
8000. - Confirm frontend uses
http://localhost:8000/apiinfrontend/src/services/api.js.
- Confirm backend is running on port
-
AI endpoints return fallback-like or generic content
- Check
OPENAI_API_KEYinbackend/.env. - Restart backend after editing
.env.
- Check
-
Resume upload fails
- Ensure file extension is
.pdf. - Try a text-based PDF (image-only scans may extract poorly).
- Ensure file extension is
-
GitHub fetch fails
- Verify username exists and is public.
- Check network connectivity and GitHub API availability.
-
CORS or mixed-origin issues in non-local deploy
- Replace permissive CORS (
allow_origins=["*"]) with explicit frontend domains in production.
- Replace permissive CORS (