Skip to content

Latest commit

 

History

8 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Evergreen — Fission Labs Resume Builder

Evergreen is Fission Labs' internal resume builder. Employees maintain their professional profile in small pieces — projects, skills, certifications — as their work happens, and generate a Fission-Labs template-perfect Word document on demand. AI assist polishes bullets, drafts STAR-style accomplishments from a rough description, and auto-categorizes new skills. Stack: Spring Boot 3.2 / Java 21 backend, React + Vite + Tailwind frontend, PostgreSQL via Flyway, Apache POI for .docx generation, optional Anthropic Claude (claude-sonnet-4-5) integration that gracefully degrades to deterministic stubs without a key.

Stack

  • Backend — Spring Boot 3.2, Java 21, PostgreSQL 16, JPA, Flyway, Apache POI 5.2, JJWT
  • Frontend — React 18, Vite 5, TypeScript, Tailwind CSS, react-router-dom, axios
  • Auth — email/password (bcrypt) + stateless JWT (HS384)
  • AI — Anthropic Claude (claude-sonnet-4-5) via Spring RestClient; deterministic stub responses when no API key is set

Quick start

cp .env.example .env       # adjust if you want (ANTHROPIC_API_KEY is optional)
docker compose up --build

The DB host port is 5433, not 5432, so it coexists with a developer's locally-installed Postgres. The backend container talks to db:5432 inside the docker network.

Fonts

The Fission Labs template uses Poppins. Install it system-wide so the generated .docx renders correctly:

Without Poppins, Word substitutes another sans-serif and the brand look breaks (colors, sizes, layout are still correct).

Architecture

See docs/architecture.md for component, sequence, and entity-relationship diagrams (Mermaid; renders inline on GitHub).

Repository layout

evergreen/
├── backend/                                  Spring Boot service
│   ├── pom.xml                               Java 21, Spring Boot 3.2.5
│   └── src/main/
│       ├── java/com/fissionlabs/evergreen/   auth, user, education, skill,
│       │                                     company, project, certification,
│       │                                     resume (docx generator), ai,
│       │                                     upload, common, config
│       └── resources/
│           ├── application.yml               JWT, Anthropic, upload config
│           ├── db/migration/V1__…sql         Flyway schema
│           └── templates/                    runtime assets
│               └── images/{logo,watermark}.png
├── frontend/                                 Vite + React + Tailwind
│   └── src/{auth,api,components,pages,lib}
├── templates/Fission_Labs_Resume_format.odt  visual source of truth
├── docker-compose.yml
└── README.md

Generated resume — visual reference

A standalone sample (no DB needed) can be produced via:

cd backend
mvn test -Dtest=ResumeDocxGeneratorTest
open target/sample-resume.docx

Open it side-by-side with templates/Fission_Labs_Resume_format.odt — they should look like they came from the same template.

The full app produces the same output through POST /api/resume/generate once a user has filled in their profile.

REST API surface

All authenticated endpoints require Authorization: Bearer <jwt>.

POST   /api/auth/signup                          {name,email,password}
POST   /api/auth/login                           {email,password}

GET    /api/users/me                             current profile
PUT    /api/users/me                             {name?,currentRole?,majorStack?,highlights?}
POST   /api/users/me/photo                       multipart/form-data file=...

GET    /api/users/me/educations
POST   /api/users/me/educations
PUT    /api/users/me/educations/{id}
DELETE /api/users/me/educations/{id}

GET    /api/users/me/skills
POST   /api/users/me/skills                      {name,category}
PUT    /api/users/me/skills/{id}
DELETE /api/users/me/skills/{id}

GET    /api/users/me/companies
POST   /api/users/me/companies                   {name,startDate,endDate?,current}
PUT    /api/users/me/companies/{id}
DELETE /api/users/me/companies/{id}

GET    /api/users/me/companies/{companyId}/projects
POST   /api/users/me/companies/{companyId}/projects   {name,role?,description?,bullets,techUsed,startDate,endDate?}
PUT    /api/users/me/companies/{companyId}/projects/{id}
DELETE /api/users/me/companies/{companyId}/projects/{id}

GET    /api/users/me/certifications
POST   /api/users/me/certifications              {name,issuer?,month?,year?,credentialId?}
PUT    /api/users/me/certifications/{id}
DELETE /api/users/me/certifications/{id}

POST   /api/resume/preview                       {profileNumber?,selected*Ids?}  -> ResumeData JSON
POST   /api/resume/generate                      {profileNumber?,selected*Ids?}  -> .docx download

POST   /api/ai/polish-bullet                     {text}        -> {polished}
POST   /api/ai/bullets-from-text                 {description} -> {bullets}
POST   /api/ai/categorize-skill                  {skillName}   -> {category}

Running pieces independently

If you want hot reload during development:

# 1. Postgres only
docker compose up -d db

# 2. Backend on host (uses host:5433 to reach the docker DB)
cd backend
SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5433/evergreen \
SPRING_DATASOURCE_USERNAME=evergreen \
SPRING_DATASOURCE_PASSWORD=evergreen \
JWT_SECRET=replace-with-a-long-random-string-of-at-least-32-chars \
UPLOAD_DIR=$(pwd)/uploads \
mvn spring-boot:run

# 3. Frontend on host
cd frontend
npm install
npm run dev    # http://localhost:5173

Data model

  • users — name, email, password_hash, role_title, major_stack, photo_url, highlights (text[])
  • educations — degree, institution, year, score
  • skills — name, category (10-value enum); unique per (user, name)
  • companies — name, start_date, end_date?, is_current (partial unique index ensures ≤1 current company per user)
  • projects — name, role, description, bullets (jsonb), tech_used (text[]), start_date, end_date?
  • certifications — name, issuer, month, year, credential_id

current_role is a SQL reserved word in PostgreSQL, so the column is named role_title; the JSON field stays currentRole.

About

Stop rewriting your resume every quarter. Add experience as it happens; download a brand-consistent Word resume whenever HR asks.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages