JadeAI: a self-hosted resume builder with AI parsing, JD matching and mock interviews
AI-Powered Smart Resume Builder — 50+ professional templates, PDF/image parsing, AI optimization, JD match analysis, multi-format export. Open source & free, one-click Docker deployment.
At a glance
- What is it?
- JadeAI is a TypeScript and Next.js resume builder that runs from a Docker image or a desktop installer, with 50 templates, PDF and image parsing, and per-user AI keys. The interesting part is the PDF export pipeline and the SQLite default, not the template count.
- Who is it for?
- Adopt JadeAI if you want a resume builder you can run yourself, keep on SQLite, and point at your own OpenAI, Anthropic or OpenAI-compatible key, and if you accept that PDF export depends on Chromium inside the container. Do not adopt it if you need a hosted service with no server to run, or if you expect the README to tell you how to roll a deployment back.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 17 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 19, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What JadeAI actually replaces
The project is a resume builder with an editor, a template gallery and an export pipeline, plus a set of AI features layered on top: generation from a job title, parsing of an uploaded PDF or image, job description match analysis, cover letter generation, grammar checking and translation across 10 languages. The README also documents a mock interview mode with six preset interviewer roles and a per-question report.
That is a wide surface for one repository, and the width is the point. The people who benefit are those who already have a resume in some format, want it in a template they control, and do not want to paste their employment history into a third-party web app. Because the AI provider is configured per user in the application, the operator of an instance does not have to supply a key at all. The README states that OpenAI, Anthropic and any OpenAI-compatible endpoint are supported, and names OrcaRouter as an example endpoint.
The template count (50) and the ATS-friendly category matter less than they sound. A resume builder's real cost is the export, and that is where this project has the most documented engineering.
Architecture: Next.js standalone, Drizzle, SQLite or Postgres
The stack is Next.js 16 with React 19 and TypeScript 5, built with pnpm. The Dockerfile builds in three stages and copies `.next/standalone` into the runner image, so the production container runs a Node server rather than a full source tree. Migration files from `drizzle/` are copied in as well, which the Dockerfile comment describes as being there for auto-migration on startup.
The database choice is a runtime decision, not a build-time one. `.env.example` sets `DB_TYPE=sqlite` as the default and `SQLITE_PATH=./data/jade.db`, with `DATABASE_URL` used when `DB_TYPE=postgresql`. The repository ships both `drizzle.config.ts` and `drizzle-pg.config.ts`, matching the two backends. The `/app/data` directory is declared as a volume in the Dockerfile, so the SQLite file survives container replacement if you mount it.
Authentication is also a runtime flag. `AUTH_ENABLED=false` is the default in `.env.example`, and Google OAuth is configured through `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET`. A separate `JADE_RUNTIME` variable, when set to `desktop`, skips fingerprinting and NextAuth entirely and collapses the database to a single user with id `local`. That single variable explains the desktop build: same code, different runtime assumptions.
Installing JadeAI with Docker and running a first export
The README points at a published image, `twwch/jadeai`, and the repository includes a `docker_run_local.sh` script for local runs. The environment file is the starting point: copy `.env.example` to `.env` and, for a single-user local instance, leave the defaults alone. `AUTH_ENABLED=false` and `DB_TYPE=sqlite` mean no login screen and no external database.
cp .env.example .envThe `--init` flag is not decoration. The Dockerfile comment documents that each PDF export launches a Chromium whose helper processes are re-parented to PID 1, and that a Node process at PID 1 never calls `wait()` on children it did not create. The comment records five exports leaving 20 zombies with parent PID 1, and the same five exports leaving zero under `docker run --init`. The image installs `tini` for exactly this reason. The Dockerfile installs `chromium`, `nss`, `freetype`, `harfbuzz`, `ca-certificates`, `ttf-freefont`, `font-noto-cjk` and `tini`, and sets `CHROME_PATH=/usr/bin/chromium-browser` so that the export code uses the system Chromium. If you run the image without `--init`, expect exports to start failing once the PID table fills, and to recover only after a restart.
Once the container is up, the workflow is: open the editor, pick a template, fill or paste content, then export. The README lists PDF, HTML and DOCX export pipelines, and states that all three read their colors from `src/lib/brand-constants.ts`. For a first real use, generate a resume from a job title and skills using the AI generation feature, then export to PDF and confirm the file renders with the CJK fonts. The Dockerfile installs `font-noto-cjk` alongside Chromium specifically so that non-Latin characters do not come out as boxes.
The PDF export failure mode is the project's most honest documentation
Most resume builders say nothing about how they render PDFs. JadeAI's Dockerfile contains a paragraph explaining the zombie-process bug that made PDF export fail after a container had been running for a while, referencing issue #95. The fix is `tini` in the image plus `--init` at run time.
The trade-off is real: PDF export depends on a full Chromium inside the container. That is why the runner stage installs `chromium`, `nss`, `freetype`, `harfbuzz`, `ca-certificates`, `ttf-freefont` and `font-noto-cjk`, and why `CHROME_PATH=/usr/bin/chromium-browser` is set. It is also why the dependency list includes `@sparticuz/chromium-min`. You get accurate HTML-to-PDF rendering at the cost of a much larger image and a process model you have to get right. On a platform where you cannot pass `--init`, or where the container runtime reaps differently, this is the part to test before you commit.
A second boundary is the desktop build. The README describes macOS (Apple Silicon and Intel) and Windows x64 installers as zero config with data staying local, and the package scripts confirm `dist:mac` and `dist:win` targets via electron-builder. There is no Linux desktop target in the documented scripts.
AI features depend on a key you supply, and on a provider that behaves
The AI surface is large: chat assistant with persistent multi-session history, resume generation, PDF and image parsing, JD match analysis with keyword matching and an ATS score, cover letter generation with formal, friendly and confident tones, grammar checking with a quality score and auto-fix, translation, and the mock interview module. All of it routes through the AI SDK packages listed in `package.json`: `@ai-sdk/openai`, `@ai-sdk/anthropic`, `@ai-sdk/google` and `ai`.
The design decision worth noting is that each user configures their own key in the app. For a team instance that is a clean separation: the operator runs the server and the database, the user owns the API spend and the data sent to the model. It also means the AI features are inert until someone pastes a key. Nothing in the README suggests a bundled model or a local inference option, so an air-gapped deployment gets the editor, the templates and the exports, and none of the AI.
Parsing deserves a caution. The README advertises PDF and image parsing, and the screenshots include an animated image-parsing demo. Extraction quality from a scanned or heavily designed resume is not something the README quantifies, and it does not describe a correction workflow beyond editing the parsed result in the canvas. Treat parsing as a draft generator, not an import.
How it differs from Reactive Resume and YAML-based resume tools
The closest well-known alternative is Reactive Resume, a self-hostable resume builder that also ships templates and PDF export. The difference in approach is the AI layer: Reactive Resume is a builder, while JadeAI bundles generation, parsing, JD matching, grammar checking and mock interviews into the same application. If you want a resume builder and nothing else, Reactive Resume is the smaller surface to operate.
A second category is YAML-driven resume tooling, where the resume is a text file in version control and a CLI renders it. That approach wins on diffability: you can review a resume change the way you review code. JadeAI stores resumes in SQLite or PostgreSQL and edits them through a drag-and-drop canvas, so a resume change is a database row, not a patch. If your priority is keeping your resume in git next to your projects, this is the wrong shape of tool.
The mock interview module has no obvious equivalent in either category. It is a separate product bolted into the same repository, and it is the feature that most clearly signals the project is aimed at job seekers rather than at engineers who want a rendering pipeline.
Licence, maintenance and upgrade cost
JadeAI is Apache-2.0, which permits commercial use, modification and redistribution provided the licence and notices are preserved, and it includes a patent grant. It is not a copyleft licence, so running a modified instance as a service does not oblige you to publish your changes. That is a general description of the licence text, not legal advice; read the LICENSE file in the repository for the terms that bind you.
On maintenance, the last push to the default branch was on 2026-09-03, and the most recent release listed is v0.7.0 on 2026-08-27, after v0.6.0 on 2026-08-22 and v0.5.1 on 2026-08-15. The cadence across August 2026 is roughly weekly. The repository is not archived.
Upgrade cost concentrates in three places. Drizzle migrations are copied into the image and the Dockerfile comment says they run on startup, so a schema change lands the first time you boot the new image; back up the SQLite file or the PostgreSQL database before you pull. The `NEXT_PUBLIC_*` to runtime environment variable migration in v0.3.2 and the `NEXT_PUBLIC_AUTH_ENABLED` to `AUTH_ENABLED` change in v0.3.1 mean older `.env` files will silently keep the wrong variable names. And the brand token work in v0.3.4 touched export pipelines, so custom themes are worth re-checking after an upgrade. The README does not document a rollback procedure for a failed migration.
Editorial conclusion
Adopt JadeAI if you want a resume builder you can run yourself, keep on SQLite, and point at your own OpenAI, Anthropic or OpenAI-compatible key, and if you accept that PDF export depends on Chromium inside the container. Do not adopt it if you need a hosted service with no server to run, or if you expect the README to tell you how to roll a deployment back. Before trusting it with a real resume, verify three things: that DB_TYPE matches the database you intend to back up, that your reverse proxy forwards the share-link routes, and that repeated PDF exports still work after the container has been up for a while.
Frequently asked questions
What is JadeAI?
JadeAI is an open source, AI-powered resume builder written in TypeScript and licensed under Apache-2.0. It combines a drag-and-drop editor, 50 templates, PDF and image parsing, job description match analysis, multi-format export and a mock interview module, and it can run from a Docker image or as a desktop client.
Does JadeAI need an API key to work?
Yes for the AI features. The README states that each user configures their own key in the app, and that OpenAI, Anthropic and any OpenAI-compatible endpoint are supported. Without a key the editor, templates and exports still work, but generation, parsing, JD matching and the interview module do not.
Which database does JadeAI use by default?
SQLite. The example environment file sets DB_TYPE=sqlite with SQLITE_PATH=./data/jade.db, and the Dockerfile declares /app/data as a volume. Setting DB_TYPE=postgresql switches to PostgreSQL using DATABASE_URL, with a separate Drizzle config for that backend.
Why does PDF export stop working after JadeAI has been running for a while?
The Dockerfile documents that Chromium helper processes are re-parented to PID 1 after each export, and that Node at PID 1 never reaps them, so the PID table eventually fills and Chromium can no longer fork. The image installs tini and the documented fix is running the container with --init.
Community notes