{"id":50126376,"url":"https://github.com/mdfarhankc/resumecraft","last_synced_at":"2026-05-23T20:04:30.925Z","repository":{"id":348488840,"uuid":"1198314750","full_name":"mdfarhankc/resumecraft","owner":"mdfarhankc","description":"ResumeCraft - Generate professional resumes from JSON with DOCX/PDF export, custom styling, and web framework support.","archived":false,"fork":false,"pushed_at":"2026-05-11T10:04:40.000Z","size":920,"stargazers_count":1,"open_issues_count":6,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-13T15:15:55.186Z","etag":null,"topics":["career","cli","cv","cv-builder","django","docx","fastapi","flask","json","pdf","pydantic-v2","pypi","python","resume","resume-builder","resume-generator","word-document"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mdfarhankc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-01T10:01:20.000Z","updated_at":"2026-04-25T17:45:31.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mdfarhankc/resumecraft","commit_stats":null,"previous_names":["mdfarhankc/resumecraft"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/mdfarhankc/resumecraft","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdfarhankc%2Fresumecraft","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdfarhankc%2Fresumecraft/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdfarhankc%2Fresumecraft/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdfarhankc%2Fresumecraft/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mdfarhankc","download_url":"https://codeload.github.com/mdfarhankc/resumecraft/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdfarhankc%2Fresumecraft/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33410355,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T18:09:33.147Z","status":"ssl_error","status_checked_at":"2026-05-23T18:09:31.380Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["career","cli","cv","cv-builder","django","docx","fastapi","flask","json","pdf","pydantic-v2","pypi","python","resume","resume-builder","resume-generator","word-document"],"created_at":"2026-05-23T20:04:00.330Z","updated_at":"2026-05-23T20:04:30.914Z","avatar_url":"https://github.com/mdfarhankc.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ResumeCraft\n\n[![PyPI version](https://img.shields.io/pypi/v/resumecraft.svg)](https://pypi.org/project/resumecraft/)\n[![Python versions](https://img.shields.io/pypi/pyversions/resumecraft.svg)](https://pypi.org/project/resumecraft/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Downloads](https://static.pepy.tech/badge/resumecraft/month)](https://pepy.tech/project/resumecraft)\n\n**Build professional Word (`.docx`) and PDF resumes from a JSON or YAML file.**\n\nResumeCraft is a Python resume/CV generator that takes JSON or YAML input and produces a polished Word document or PDF. Use it as a library, a CLI tool, or drop it into a web app (FastAPI, Flask, Django).\n\nSee the [generated PDF](examples/output/sample_resume.pdf) (built from [`sample_resume.json`](examples/sample_resume.json)) to get a feel for the formatting. Set `style.ats = true` for ATS-friendly output.\n\n## Features\n\n- Single JSON or YAML file as input (easy to version control)\n- Auto-bolds keywords across all bullet points\n- Right-aligned dates using proper tab stops\n- Clickable hyperlinks for email, LinkedIn, GitHub, and project URLs\n- Keeps section headings from getting orphaned at page breaks\n- Pydantic-validated input with strict mode (typos in field names raise instead of silently failing)\n- Custom section ordering and renamed headings\n- Sections: summary, experience, projects (with multi-link support), skills, education, certifications, awards, languages\n- Style presets: 7 fonts, 6 color themes, 3 spacing options, plus an ATS-friendly mode\n- Watch mode with PDF output for live preview\n- Optional PDF export via `docx2pdf`\n- Multiple factory methods (`from_jsonfile`, `from_yamlfile`, `from_bytes`, `from_dict`, …) for clean web framework integration\n- In-memory exports (`to_docx_bytes()`, `to_pdf_bytes()`) for streaming responses\n- JSON schema for editor autocomplete via `$schema`\n\n## Installation\n\n```bash\npip install resumecraft              # library + CLI\npip install resumecraft[pdf]         # + PDF export\npip install resumecraft[pdf,watch]   # + PDF export + watch mode\npip install resumecraft[all]         # everything\n\n# Install the CLI globally\npipx install resumecraft\nuv tool install resumecraft\n\n# Or run without installing\nuvx resumecraft build my-resume.json\nuvx \"resumecraft[all]\" build my-resume.json --open\n```\n\n## Quick Start\n\n```bash\n# 1. Generate a template\nresumecraft init -o my-resume.json\n\n# 2. Edit my-resume.json with your details\n\n# 3. Build your resume (docx)\nresumecraft build my-resume.json\n\n# 4. Build a PDF with the same filename (my-resume.pdf)\nresumecraft build my-resume.json --pdf\n\n# 5. Build and open immediately\nresumecraft build my-resume.json --pdf --open\n\n# 6. Validate without building\nresumecraft validate my-resume.json\n\n# 7. Watch for changes and rebuild automatically (defaults to PDF)\nresumecraft watch my-resume.json --open\n```\n\n## CLI Reference\n\n```\nresumecraft --help                                Show all commands\nresumecraft --version                             Show version\nresumecraft init -o FILE                          Generate a blank JSON template\nresumecraft build FILE [-o FILE] [--pdf] [--open]  Build .docx or .pdf from JSON\nresumecraft validate FILE                         Validate JSON without building\nresumecraft watch FILE [-o FILE] [--open]         Watch and rebuild on file changes\n```\n\nWhen `-o` is omitted from `build`, the output is named after the input file with a timestamp, e.g., `my-resume_2026-04-01_03-45pm.docx`.\n\nWhen `-o` is omitted from `watch`, the output defaults to `\u003cinput-name\u003e.pdf`. PDF viewers don't lock files, so changes appear instantly.\n\n## Use as a Library\n\n```python\nfrom resumecraft import ResumeCraft\n\n# Load from anywhere\nrc = ResumeCraft.from_jsonfile(\"my-resume.json\")\nrc = ResumeCraft.from_yamlfile(\"my-resume.yaml\")      # needs: pip install resumecraft[yaml]\nrc = ResumeCraft.from_json('{\"name\": \"John\", ...}')   # JSON string\nrc = ResumeCraft.from_yaml(\"name: John\\n...\")         # YAML string\nrc = ResumeCraft.from_bytes(uploaded_bytes)           # raw bytes (uploads, request body)\nrc = ResumeCraft.from_dict({\"name\": \"John\", ...})     # dict\n\n# Export\nrc.to_docx(\"resume.docx\")            # save .docx\nrc.to_pdf(\"resume.pdf\")              # save .pdf  (needs: pip install resumecraft[pdf])\nrc.to_docx_bytes()                   # docx as bytes (for streaming)\nrc.to_pdf_bytes()                    # pdf as bytes\nrc.to_dict()                         # back to a dict\n\n# Discover the schema\nResumeCraft.sample()                 # sample dict with all fields\nResumeCraft.json_schema()            # JSON schema (for editor autocomplete)\n```\n\n### FastAPI example\n\n```python\nimport io\nfrom fastapi import FastAPI, UploadFile\nfrom fastapi.responses import Response, StreamingResponse\n\nfrom resumecraft import ResumeCraft\n\napp = FastAPI()\n\n\n@app.post(\"/resume/docx\")\ndef generate_docx(data: dict):\n    rc = ResumeCraft.from_dict(data)\n    return StreamingResponse(\n        io.BytesIO(rc.to_docx_bytes()),\n        media_type=\"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n        headers={\"Content-Disposition\": \"attachment; filename=resume.docx\"},\n    )\n\n\n@app.post(\"/resume/pdf\")\ndef generate_pdf(data: dict):\n    return Response(\n        ResumeCraft.from_dict(data).to_pdf_bytes(),\n        media_type=\"application/pdf\",\n    )\n\n\n@app.post(\"/resume/upload\")\nasync def from_upload(file: UploadFile):\n    rc = ResumeCraft.from_bytes(await file.read())\n    return Response(rc.to_pdf_bytes(), media_type=\"application/pdf\")\n```\n\n### Flask example\n\n```python\nimport io\nfrom flask import Flask, request, send_file\n\nfrom resumecraft import ResumeCraft\n\napp = Flask(__name__)\n\n\n@app.post(\"/resume/docx\")\ndef generate_docx():\n    rc = ResumeCraft.from_dict(request.json)\n    return send_file(\n        io.BytesIO(rc.to_docx_bytes()),\n        mimetype=\"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n        download_name=\"resume.docx\",\n    )\n\n\n@app.post(\"/resume/pdf\")\ndef generate_pdf():\n    pdf = ResumeCraft.from_dict(request.json).to_pdf_bytes()\n    return send_file(io.BytesIO(pdf), mimetype=\"application/pdf\", download_name=\"resume.pdf\")\n```\n\nSee the [examples/](examples/) folder for runnable examples (`library.py`, `web.py`).\n\n### Advanced usage\n\nThe Pydantic model and the renderer are available for power users who need more control:\n\n```python\nimport json\nfrom pathlib import Path\nfrom resumecraft.models import Resume\nfrom resumecraft.builder import DocxBuilder\n\ndata = json.loads(Path(\"my-resume.json\").read_text())\nresume = Resume.model_validate(data)\nDocxBuilder(resume).save(\"resume.docx\")\n```\n\n## JSON Structure\n\nRun `resumecraft init` to generate a full template. Here's the structure:\n\n```json\n{\n  \"$schema\": \"https://raw.githubusercontent.com/mdfarhankc/resumecraft/main/schema.json\",\n  \"name\": \"Your Name\",\n  \"contact\": {\n    \"location\": \"City, Country\",\n    \"email\": \"your@email.com\",\n    \"phone\": \"+1-234-567-8900\",\n    \"links\": [\n      { \"label\": \"LinkedIn\", \"url\": \"https://linkedin.com/in/you\" },\n      { \"label\": \"GitHub\", \"url\": \"https://github.com/you\" }\n    ]\n  },\n  \"summary\": \"A brief professional summary...\",\n  \"bold_keywords\": [\"FastAPI\", \"React\", \"PostgreSQL\"],\n  \"experience\": [\n    {\n      \"company\": \"Company Name\",\n      \"location\": \"City, Country\",\n      \"title\": \"Your Title\",\n      \"duration\": \"JAN 2023 - PRESENT\",\n      \"bullets\": [\"What you did and the impact it had.\"]\n    }\n  ],\n  \"projects\": [\n    {\n      \"name\": \"Project Name\",\n      \"subtitle\": \"| Description\",\n      \"tech_stack\": \"Python, FastAPI\",\n      \"link\": null,\n      \"bullets\": [\"What you built.\"]\n    }\n  ],\n  \"professional_projects\": [\n    {\n      \"name\": \"Project Name\",\n      \"subtitle\": \"| Location | Type\",\n      \"tech_stack\": \"FastAPI, React, PostgreSQL\",\n      \"link\": null,\n      \"bullets\": [\"What you built.\"]\n    }\n  ],\n  \"personal_projects\": [\n    {\n      \"name\": \"Side Project\",\n      \"subtitle\": \"| Personal Project\",\n      \"tech_stack\": null,\n      \"links\": [\n        { \"label\": \"GitHub\", \"url\": \"https://github.com/you/project\" },\n        { \"label\": \"Live Demo\", \"url\": \"https://project.example.com\" }\n      ],\n      \"bullets\": [\"What you built and why.\"]\n    }\n  ],\n  \"skills\": [\n    { \"category\": \"Backend\", \"items\": \"Python (FastAPI, Django), Node.js\" },\n    { \"category\": \"Frontend\", \"items\": \"React, TypeScript\" }\n  ],\n  \"education\": [\n    {\n      \"institution\": \"University Name\",\n      \"degree\": \"Bachelor of Computer Science\",\n      \"duration\": \"2019 - 2023\"\n    }\n  ],\n  \"certifications\": [\n    {\n      \"name\": \"AWS Certified Developer\",\n      \"issuer\": \"Amazon Web Services\",\n      \"date\": \"2024\",\n      \"link\": { \"label\": \"Verify\", \"url\": \"https://aws.amazon.com/verify\" }\n    }\n  ],\n  \"awards\": [\n    {\n      \"title\": \"Employee of the Year\",\n      \"issuer\": \"Acme Corp\",\n      \"date\": \"2024\",\n      \"description\": \"Recognized for outstanding contributions.\"\n    }\n  ],\n  \"languages\": \"English - Native  |  Hindi - Professional\",\n  \"style\": {\n    \"font\": \"calibri\",\n    \"color\": \"black\",\n    \"spacing\": \"normal\"\n  },\n  \"section_order\": [\n    \"summary\",\n    \"experience\",\n    \"professional_projects\",\n    \"personal_projects\",\n    \"skills\",\n    \"education\",\n    \"certifications\",\n    \"awards\",\n    \"languages\"\n  ]\n}\n```\n\n### Field Reference\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `name` | string | Yes | Full name displayed at the top |\n| `contact` | object | Yes | Location, email, phone, and links |\n| `summary` | string | Yes | Professional summary paragraph |\n| `bold_keywords` | string[] | No | Words to auto-bold in all bullet points |\n| `experience` | object[] | No | Work experience entries |\n| `projects` | object[] | No | Single unified projects section |\n| `professional_projects` | object[] | No | Client/employer projects (use with `personal_projects` for split sections) |\n| `personal_projects` | object[] | No | Side projects and open source work |\n| `skills` | object[] | No | Categorized skill lists |\n| `education` | object[] | No | Degrees and institutions |\n| `certifications` | object[] | No | Professional certifications with issuer, date, and optional verification link |\n| `awards` | object[] | No | Awards and achievements with title, issuer, date, and optional description |\n| `languages` | string | No | Language proficiencies |\n| `section_order` | string[] | No | Custom order of sections (omit for default). Only listed sections are rendered. |\n| `headings` | object | No | Custom section headings (e.g., `{\"summary\": \"ABOUT ME\"}`) |\n| `style` | object | No | Styling options (font, color, spacing, ats) |\n| `$schema` | string | No | Editor autocomplete hint, ignored at runtime |\n| `_version` | string | No | Library version that produced the file, ignored at runtime |\n\n### Style Options\n\nAdd a `style` object to customize the look of your resume:\n\n```json\n{\n  \"style\": {\n    \"font\": \"garamond\",\n    \"color\": \"navy\",\n    \"spacing\": \"compact\"\n  }\n}\n```\n\n| Option | Choices | Default |\n|--------|---------|---------|\n| `font` | `calibri`, `arial`, `times`, `garamond`, `georgia`, `helvetica`, `cambria` | `calibri` |\n| `color` | `black`, `navy`, `forest`, `maroon`, `slate`, `royal` | `black` |\n| `spacing` | `compact`, `normal`, `relaxed` | `normal` |\n| `ats` | `true`, `false` | `false` |\n\nSet `\"ats\": true` to strip tab stops, colored tech lines, and heading borders for cleaner parsing by applicant tracking systems.\n\n### Available sections for `section_order`\n\n`summary`, `experience`, `projects`, `professional_projects`, `personal_projects`, `skills`, `education`, `certifications`, `awards`, `languages`\n\n### Custom headings\n\nOverride any section's heading text:\n\n```json\n{\n  \"headings\": {\n    \"summary\": \"ABOUT ME\",\n    \"experience\": \"CAREER\",\n    \"awards\": \"HONORS\"\n  }\n}\n```\n\n### Editor autocomplete (JSON schema)\n\nReference the schema in your JSON for autocomplete and validation in VS Code, IntelliJ, etc.:\n\n```json\n{\n  \"$schema\": \"https://raw.githubusercontent.com/mdfarhankc/resumecraft/main/schema.json\",\n  \"name\": \"Your Name\",\n  ...\n}\n```\n\n\u003e **Note:** Use either `projects` for a single section, or `professional_projects` + `personal_projects` for two separate sections. If you use `projects`, include it in `section_order` - it's not part of the default order.\n\n## Project Structure\n\n```\nresumecraft/\n├── pyproject.toml\n├── README.md\n├── CHANGELOG.md\n├── LICENSE\n├── Makefile\n├── schema.json                 # JSON schema (regenerate with: make schema)\n├── examples/\n│   ├── library.py              # Library usage\n│   ├── web.py                  # FastAPI/Flask/Django pattern\n│   ├── sample_resume.json\n│   └── output/sample_resume.pdf\n├── src/resumecraft/\n│   ├── __init__.py\n│   ├── craft.py                # ResumeCraft (entry point)\n│   ├── cli.py                  # CLI commands\n│   ├── builder.py              # DocxBuilder (slim, drives the rendering)\n│   ├── sections.py             # Section classes + SECTION_REGISTRY\n│   ├── render.py               # RenderContext + paragraph helpers\n│   ├── models.py               # Pydantic data models\n│   ├── styles.py               # font/color/spacing maps\n│   └── utils.py                # low-level docx helpers (hyperlinks, borders)\n└── tests/\n    ├── fixtures/sample.json\n    ├── test_models.py\n    ├── test_builder.py\n    ├── test_craft.py\n    ├── test_cli.py\n    └── test_utils.py\n```\n\n## Development\n\n```bash\ngit clone https://github.com/mdfarhankc/resumecraft.git\ncd resumecraft\nuv sync --extra dev\n```\n\n### Run tests\n\n```bash\nuv run pytest\n```\n\n### Build\n\n```bash\nuv build\n```\n\nThis creates `dist/resumecraft-x.x.x.tar.gz` and `dist/resumecraft-x.x.x-py3-none-any.whl`.\n\n### Publish to PyPI\n\nTag a GitHub release (e.g. `v0.6.0`) and the CI workflow will publish to PyPI automatically via trusted publishing.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdfarhankc%2Fresumecraft","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmdfarhankc%2Fresumecraft","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdfarhankc%2Fresumecraft/lists"}