ResuStack
README.md
# ResuStack
**ResuStack** is an AI resume builder. Import a PDF or your LinkedIn profile, pick one of 14 designs, and edit by form or by chat β in the browser, or straight from Claude through its MCP server. Every change is reversible, and the PDF you download is rendered from the same template as the live preview.
π **Live:** [resustackapp.com](https://resustackapp.com)
---
## β¨ Features
### Resume builder
- **PDF & LinkedIn import** β upload an existing resume or a LinkedIn PDF; AI extracts and structures it
- **Split-pane editor** β the form on the left, a live preview on the right, with page breaks where the PDF will break
- **14 designs on 6 layouts** β single column, banner, label gutter, header grid, left sidebar and right rail; ATS-safe designs are marked, and switching keeps your content
- **English and Turkish resumes** β headings, "Present", month names and degree phrasing print in the language the resume is written in
- **"What I'm working on"** β an optional section above Education, shown only when you tick it
- **PDF export** β rendered with WeasyPrint from the same template the preview uses
### AI
- **One-click enhance** β rewrites experience and project descriptions into stronger bullet points
- **Analyze and compare** β score a resume and see where it is weak, or compare two versions
- **Guided build** β build a resume step by step through questions
### Agentic mode
- **Edit by chatting** β *"Make my last role sound more senior"*; the agent uses tools, streams its progress and asks for approval before destructive actions
- **Template pane** β pick a design for the active resume without leaving the chat
- **Undo** β revert the last change from the conversation
### Change history
- A restore point before every save and every AI or MCP edit
- Diff any version against the current one, and restore it β on every plan
### Job applications
- **Match** a resume against a job posting and **tailor** a version for it
- **Track** applications, each with a snapshot of the exact resume you sent; clone a snapshot back into an editable resume
### Language versions
- Translate a resume in place, or create a translated copy linked to the original
---
## π€ Use ResuStack from Claude (MCP)
ResuStack is a [Model Context Protocol](https://modelcontextprotocol.io) server. Claude β or any MCP client with Streamable HTTP and custom headers β writes the resume; ResuStack stores it, versions it and renders it.
**1. Create a token.** Sign in, open **Profile β API token**, and create one. It is shown once; replacing it revokes the old one. The Profile page also shows the endpoint address to use.
**2. Add the server.** With Claude Code:
```bash
claude mcp add --transport http resustack https://resustackapp.com/mcp --header "Authorization: Bearer YOUR_TOKEN"
```
Authentication is a bearer token only; session cookies are not accepted on this endpoint.
**3. Ask.** *"List my resumes"*, *"Switch my CV to the Label Gutter design and give me the PDF"*, *"Fill What I'm working on from what we did this month."*
### Tools
| Tool | What it does |
|---|---|
| `list_resumes` | Resumes on the account: id, title, language, template |
| `get_resume` | The full stored content of one resume |
| `create_resume` | Create a resume from structured content |
| `update_resume` | Replace a resume's content (read it first β this is a replace, not a merge) |
| `set_focus_areas` | Set only the "What I'm working on" section; the rest of the resume is untouched |
| `list_templates` | The designs, with a description and whether each is ATS-safe |
| `set_template` | Change a resume's design |
| `render_pdf` | A download link for the PDF β single use, expires in 10 minutes |
| `check_quota` | What the account has left this month |
### Prompts
| Prompt | What it does |
|---|---|
| `focus_areas_from_my_work` | Has the client's model summarise the work you have actually done β from the conversations it can see β into a few lines, show them to you, and save them with `set_focus_areas` only after you approve |
### Safety rules
- Every write takes a restore point first; you can undo it on the website
- There is no delete tool β removing a resume stays on the website, where a person clicks
- Every query is scoped to the token's owner
- Rate limited per account
### Listing in the MCP Registry
`server.json` at the repository root describes the server for the [official MCP Registry](https://modelcontextprotocol.io/registry/about) as `com.resustackapp/resustack`. Publishing under that name requires proving ownership of `resustackapp.com` with a file served at `/.well-known/mcp-registry-auth`:
1. Generate a key pair locally. Never commit `key.pem` (it is in `.gitignore`):
```bash
openssl genpkey -algorithm Ed25519 -out key.pem
```
2. Print the proof record and set it as the `MCP_REGISTRY_AUTH` environment variable in Dokploy, then redeploy:
```bash
echo "v=MCPv1; k=ed25519; p=$(openssl pkey -in key.pem -pubout -outform DER | tail -c 32 | base64)"
```
3. Check it is live:
```bash
curl https://resustackapp.com/.well-known/mcp-registry-auth
```
4. Log in and publish from the repository root:
```bash
mcp-publisher login http --domain resustackapp.com --private-key "$(openssl pkey -in key.pem -noout -text | grep -A3 'priv:' | tail -n +2 | tr -d ' :\n')"
```
```bash
mcp-publisher publish
```
Bump `version` in `server.json` (and `SERVER_INFO` in `mcp_server/protocol.py`) for each new listing.
---
## πΈ Screenshots
### Editor β form, live preview and the template pane

### Choosing a design

### Agentic mode

### Dashboard

---
## π³ Plans
Free to start. Pro is a **one-time purchase for a period** β no subscription.
| Free plan | Limit |
|---|---|
| Resumes | 3 |
| PDF or LinkedIn imports | 2 / month |
| AI enhancements | 10 / month |
| PDF downloads | 5 / month |
| Agent chat messages | 10 / month |
| Tracked applications | 3 |
| Restore points per resume | 5 |
Pro removes these limits. Current prices are on the [pricing page](https://resustackapp.com/pricing/). Limits live in `FREE_TIER_LIMITS` in `core/settings.py`.
---
## π Running locally
### Prerequisites
- Docker & Docker Compose
- An OpenAI API key
### 1. Clone and configure
```bash
git clone https://github.com/koksalkapucuoglu/resume-enhance.git
```
```bash
cd resume-enhance && cp .env.example .env
```
| Variable | Description | Example |
|---|---|---|
| `OPENAI_API_KEY` | OpenAI API key | `sk-proj-...` |
| `SECRET_KEY` | Django secret key | any long random string |
| `DEBUG` | Debug mode | `True` |
| `ALLOWED_HOSTS` | Allowed hosts | `localhost,127.0.0.1` |
| `POSTGRES_DB` / `POSTGRES_USER` / `POSTGRES_PASSWORD` | Database credentials | `postgres` |
| `POSTGRES_HOST` / `POSTGRES_PORT` | Database address | `db` / `5432` |
| `EMAIL_HOST_USER` / `EMAIL_HOST_PASSWORD` | SMTP for password reset (optional) | |
| `DOWNLOAD_LINK_MAX_AGE` | Seconds a signed PDF link stays valid (optional) | `600` |
| `MCP_REGISTRY_AUTH` | MCP Registry domain proof served at `/.well-known/mcp-registry-auth` (optional, public key only) | `v=MCPv1; k=ed25519; p=...` |
| `PAYMENT_STATUS` | `coming_soon` shows plans without taking payment; `live` enables checkout | `coming_soon` |
| `PAYMENT_PROVIDER`, `PAYMENT_WEBHOOK_SECRET`, `CHECKOUT_URL_*`, `PRODUCT_ID_*` | Payment provider settings (optional) | |
### 2. Start
```bash
docker compose up --build
```
The app runs at [http://localhost:8000](http://localhost:8000).
### 3. Run the tests
```bash
docker compose exec web python manage.py test resume mcp_server
```
WeasyPrint and OpenAI are mocked in the unit tests; no API calls are made.
---
## βοΈ Deployment
Production runs on **[Dokploy](https://dokploy.com)**. Every push to `main` triggers a deploy through a GitHub webhook: Dokploy builds the `Dockerfile`, and `entrypoint.sh` runs `migrate` and `collectstatic` before starting Gunicorn. Traefik handles HTTPS.
Setting it up on a new server:
1. Install Dokploy: `curl -sSL https://dokploy.com/install.sh | sh`
2. Open `http://YOUR_SERVER_IP:3000` and create an admin account
3. Create a project β add an **Application** β connect this GitHub repository
4. Add a **PostgreSQL** service in the same project
5. Set the environment variables (see `.env.prod.example`) and the domain, then deploy
Notes:
- Leave Dokploy's **Run Command** empty β the Dockerfile's `ENTRYPOINT` does everything
- Behind Cloudflare's proxy, set Dokploy's domain encryption to **None** and Cloudflare SSL to **Full**
- The image installs the fonts the resume designs use; nothing is fetched at render time
`docker-compose.prod.yml` and the `Caddyfile` are kept for self-hosting without Dokploy; they are not what production uses.
---
## π Privacy
What ResuStack collects, who processes it (including OpenAI for AI features) and how to delete it: [resustackapp.com/privacy](https://resustackapp.com/privacy/). The Turkish version, written as the KVKK information notice, is at [resustackapp.com/gizlilik](https://resustackapp.com/gizlilik/). Users can delete their account and all its data from the Profile page.
---
## ποΈ Architecture
Monolithic Django: views, DRF API, an MCP endpoint, WeasyPrint for PDFs, OpenAI for parsing and writing. Resume content is a single `JSONField`; every design comes from one catalogue in `resume/resume_templates.py`. The full guide β conventions, patterns and pitfalls β is in [`.claude/CLAUDE.md`](.claude/CLAUDE.md).
---
## πΊοΈ Roadmap
- [x] Multiple resume designs (14)
- [x] Job description matching and application tracking
- [x] Agentic mode with tool calling, approvals and undo
- [x] Change history with diff and restore
- [x] MCP server for Claude and other clients
- [x] English and Turkish resumes
- [ ] Listing in MCP registries
- [ ] OAuth for MCP clients, alongside tokens
- [ ] Payments going live
---
## License
Open Source.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues