An open API service indexing awesome lists of open source software.

https://github.com/augustosc-eu/globalcv

A CV/Resume creation tool.
https://github.com/augustosc-eu/globalcv

cv free resume tool typescript vercel

Last synced: 3 months ago
JSON representation

A CV/Resume creation tool.

Awesome Lists containing this project

README

          

# GlobalCV

**Free, privacy-first CV and resume builder for the global job market.**

Built by [Bagalinis Consulting](https://bagalinis.com). No account required. No data leaves your browser.

---

## What it does

GlobalCV generates professional CVs and resumes tailored to the conventions of eight major job markets. Each market has its own templates, fields, labels, and formatting rules โ€” so your CV looks like it was built by someone who knows the local standards, not a generic online tool.

**Supported markets:**

| Market | Page size | Templates | Language |
|---|---|---|---|
| ๐Ÿ‡บ๐Ÿ‡ธ United States | Letter | Classic, Modern | English |
| ๐Ÿ‡ฌ๐Ÿ‡ง United Kingdom | A4 | Classic CV, Modern CV | English |
| ๐Ÿ‡ฆ๐Ÿ‡บ Australia & NZ | A4 | Classic, Modern | English |
| ๐Ÿ‡ฎ๐Ÿ‡ณ India | A4 | Classic CV, Modern CV | English |
| ๐Ÿ‡ช๐Ÿ‡บ European Union | A4 | Europass, Modern | English |
| ๐ŸŒŽ Latin America | Letter | Traditional, Modern | Spanish |
| ๐Ÿ‡ง๐Ÿ‡ท Brasil | A4 | Tradicional, Moderno | Portuguese |
| ๐Ÿ‡ฏ๐Ÿ‡ต Japan | A4 | ๅฑฅๆญดๆ›ธ (Rirekisho), ่ทๅ‹™็ตŒๆญดๆ›ธ (Shokumu) | Japanese |

**Market conventions enforced per locale:**

| Market | Photo | DOB | Nationality | Marital status | Page limit |
|---|---|---|---|---|---|
| ๐Ÿ‡บ๐Ÿ‡ธ US | Hidden (discrimination law) | Hidden | Hidden | Hidden | 1 |
| ๐Ÿ‡ฌ๐Ÿ‡ง GB | Hidden (equality law) | Hidden | Hidden | Hidden | 2 |
| ๐Ÿ‡ฆ๐Ÿ‡บ AU | Hidden | Hidden | Hidden | Hidden | 3 |
| ๐Ÿ‡ฎ๐Ÿ‡ณ IN | Optional | Optional | Optional | Optional | 2 |
| ๐Ÿ‡ช๐Ÿ‡บ EU | Optional | Optional | Optional | Hidden | 2 |
| ๐ŸŒŽ LATAM | Required | Required | Required | Required | 2 |
| ๐Ÿ‡ง๐Ÿ‡ท BR | Optional | Optional | Optional | Optional | 2 |
| ๐Ÿ‡ฏ๐Ÿ‡ต JP | Required | Required | Required | Optional | โ€” |

---

## Features

### Editing
- **Market-aware fields** โ€” US hides date of birth and photo (anti-discrimination); Latam requires them; Japan requires a ่จผๆ˜Žๅ†™็œŸ, ็”Ÿๅนดๆœˆๆ—ฅ, ้€šๅ‹คๆ™‚้–“, and more
- **Multiple templates per market** โ€” 2 layouts per market with distinct visual styles
- **6 color themes per market** โ€” Swap accent colors in the header (desktop) or in the Template step (mobile)
- **Undo / Redo** โ€” 20-snapshot history with Cmd/Ctrl+Z / Y keyboard shortcuts; history is preserved for 2 seconds after each change
- **Inline form validation** โ€” Required fields, email format, and date range errors shown on blur

### Preview & Export
- **Live preview** โ€” Zoomable (40โ€“150%) side panel with page-count estimate
- **Page limit warning** โ€” Amber badge when content is estimated to exceed the market's recommended page count
- **PDF export** โ€” Downloads a print-ready PDF matching the selected template exactly, with correct page breaks and multi-page sidebars
- **Mobile preview** โ€” Full-screen preview modal accessible on small screens via a floating button

### Import & Backup
- **CV text import** โ€” Paste any CV text (English or Spanish); the parser detects sections, dates, name, email, phone, and LinkedIn automatically
- **Import warnings** โ€” Shows which fields weren't detected and warns if the 30-skill cap is hit
- **JSON backup** โ€” Download your full CV as a `.json` file; restore it later with the Restore button
- **Copy to market** โ€” Copy all CV content to a different market's slot (preserves target market's template and theme defaults)

### Sharing & Sync
- **Share link** โ€” Generates a compressed URL with your full CV data (photo excluded) โ€” share or bookmark it
- **Long-URL warning** โ€” Warns before copying a link over 2,000 characters with a character count and privacy notice
- **Cross-tab sync** โ€” If another browser tab saves the same market's CV, a banner prompts you to reload

### Privacy & Safety
- **Privacy Mode** โ€” Blurs all PII fields in the UI; toggle in the header
- **Photo compression** โ€” Uploaded photos are automatically resized to 800 px max (JPEG 85%) before storage; files over 8 MB are rejected
- **Error boundary** โ€” Catches render crashes with a "Reload page" fallback so a broken CV doesn't leave you stuck
- **No backend** โ€” All data stays in your browser (localStorage + URL state). Nothing is sent to a server
- **No account** โ€” Open the app, fill in your details, export your PDF

### ATS (US market)
- **ATS suggestions panel** โ€” 10-point checklist (name, email, phone, LinkedIn, summary length, work entries, description length, quantified achievements, education, skills count) with a score bar and per-check tips

---

## Privacy

> **Your CV never leaves your device.**

GlobalCV is a fully client-side app. No data is collected, stored on a server, or shared with third parties. See the full [Privacy Policy](/privacy) and [Terms of Service](/terms) inside the app.

Hosting is provided by [Vercel](https://vercel.com). No analytics or tracking scripts are used.

The share link embeds CV content (except photos) as LZ-compressed plain text in the URL โ€” anyone with the link can read your data. You are warned before copying.

---

## Tech Stack

| | |
|---|---|
| Framework | Next.js 16 (App Router, Turbopack) |
| UI | React 19, Tailwind CSS 3, Radix UI |
| State | Zustand 4 + Immer |
| Forms | react-hook-form 7 |
| Drag & drop | @dnd-kit/core + sortable |
| PDF generation | @react-pdf/renderer 4 |
| Share URL compression | lz-string |
| Icons | lucide-react |
| Language | TypeScript 5.9 |

---

## Getting Started

```bash
git clone https://github.com/augustosc-eu/globalcv.git
cd globalcv
npm install
npm run dev # http://localhost:3000
npm run build # production build
npm run lint # ESLint
```

Open [http://localhost:3000](http://localhost:3000) and select a market to begin.

**Requirements:** Node.js 18+

---

## Project Structure

```
src/
โ”œโ”€โ”€ app/
โ”‚ โ”œโ”€โ”€ page.tsx # Market selector landing page
โ”‚ โ”œโ”€โ”€ [market]/
โ”‚ โ”‚ โ”œโ”€โ”€ layout.tsx # Market validation + ErrorBoundary + PrivacyBanner
โ”‚ โ”‚ โ””โ”€โ”€ page.tsx # Renders WizardShell for the market
โ”‚ โ”œโ”€โ”€ privacy/page.tsx
โ”‚ โ””โ”€โ”€ terms/page.tsx
โ”‚
โ”œโ”€โ”€ types/
โ”‚ โ”œโ”€โ”€ cv.types.ts # CVData, PersonalInfo, WorkExperience, โ€ฆ
โ”‚ โ””โ”€โ”€ market.types.ts # MarketConfig shape
โ”‚
โ”œโ”€โ”€ lib/
โ”‚ โ”œโ”€โ”€ markets/
โ”‚ โ”‚ โ”œโ”€โ”€ us.config.ts # US market config
โ”‚ โ”‚ โ”œโ”€โ”€ eu.config.ts # EU market config
โ”‚ โ”‚ โ”œโ”€โ”€ latam.config.ts # Latam market config
โ”‚ โ”‚ โ”œโ”€โ”€ jp.config.ts # Japan market config
โ”‚ โ”‚ โ”œโ”€โ”€ ui.ts # Shared UI label helpers
โ”‚ โ”‚ โ””โ”€โ”€ index.ts # getMarketConfig(), isValidMarket()
โ”‚ โ”œโ”€โ”€ parser/
โ”‚ โ”‚ โ””โ”€โ”€ cvParser.ts # Paste-import parser โ†’ ParseResult { data, warnings }
โ”‚ โ”œโ”€โ”€ pdf/
โ”‚ โ”‚ โ””โ”€โ”€ CVPDFDocument.tsx # All PDF layouts (Classic, Modern, Europass, Shokumu, โ€ฆ)
โ”‚ โ”œโ”€โ”€ sharing/
โ”‚ โ”‚ โ””โ”€โ”€ shareUrl.ts # encodeCVToURL / decodeCVFromURL (lz-string)
โ”‚ โ”œโ”€โ”€ storage/
โ”‚ โ”‚ โ””โ”€โ”€ localStorage.ts # saveCV / loadCV / clearCV โ€” versioned + migration
โ”‚ โ””โ”€โ”€ utils/
โ”‚ โ”œโ”€โ”€ cn.ts # Tailwind class merge helper
โ”‚ โ”œโ”€โ”€ dateFormat.ts # Wareki + locale date formatting
โ”‚ โ””โ”€โ”€ theme.ts # Color theme utilities
โ”‚
โ”œโ”€โ”€ store/
โ”‚ โ””โ”€โ”€ cvStore.ts # Zustand store โ€” state, autosave, undo/redo, restoreCV
โ”‚
โ”œโ”€โ”€ hooks/
โ”‚ โ””โ”€โ”€ usePDFExport.ts # PDF generation state machine (idle/generating/done/error)
โ”‚
โ””โ”€โ”€ components/
โ”œโ”€โ”€ form-fields/
โ”‚ โ”œโ”€โ”€ DateRangePicker.tsx # Start/end date + "present" toggle + validation
โ”‚ โ””โ”€โ”€ PhotoUpload.tsx # Canvas compression + 8 MB limit
โ”‚
โ”œโ”€โ”€ preview/
โ”‚ โ”œโ”€โ”€ PreviewPane.tsx # Zoomable preview with page-count warning
โ”‚ โ””โ”€โ”€ renderers/
โ”‚ โ”œโ”€โ”€ USClassicRenderer.tsx
โ”‚ โ”œโ”€โ”€ USModernRenderer.tsx
โ”‚ โ”œโ”€โ”€ EUEuropassRenderer.tsx
โ”‚ โ”œโ”€โ”€ EUModernRenderer.tsx
โ”‚ โ”œโ”€โ”€ LatamTraditionalRenderer.tsx
โ”‚ โ”œโ”€โ”€ LatamModernRenderer.tsx
โ”‚ โ”œโ”€โ”€ JapanRirekishoRenderer.tsx
โ”‚ โ””โ”€โ”€ JapanShokumuRenderer.tsx
โ”‚
โ”œโ”€โ”€ shared/
โ”‚ โ”œโ”€โ”€ AppHeader.tsx # Save status, undo/redo, import, share, backup, PDF export
โ”‚ โ”œโ”€โ”€ ATSSuggestionsPanel.tsx # 10-point ATS score with tips (US market)
โ”‚ โ”œโ”€โ”€ CopyToMarketModal.tsx # Copy CV content to another market
โ”‚ โ”œโ”€โ”€ CrossTabSyncBanner.tsx # Reload prompt when another tab saves the same market
โ”‚ โ”œโ”€โ”€ ErrorBoundary.tsx # React error boundary with reload fallback
โ”‚ โ”œโ”€โ”€ PasteImportModal.tsx # 3-step paste โ†’ preview โ†’ apply import flow
โ”‚ โ”œโ”€โ”€ PrivacyBanner.tsx # Top-of-page privacy notice
โ”‚ โ”œโ”€โ”€ ShareButton.tsx # Copy share link with long-URL warning modal
โ”‚ โ””โ”€โ”€ ThemeSelector.tsx # Color theme picker
โ”‚
โ””โ”€โ”€ wizard/
โ”œโ”€โ”€ WizardShell.tsx # Main layout: sidebar nav + form area + preview pane
โ”œโ”€โ”€ WizardProgress.tsx # Step list with completion indicators
โ”œโ”€โ”€ WizardNavigation.tsx # Prev / Next buttons
โ”œโ”€โ”€ StepRouter.tsx # Maps step key โ†’ step component
โ””โ”€โ”€ steps/
โ”œโ”€โ”€ PersonalInfoStep.tsx # Name, contact, photo, address (validated)
โ”œโ”€โ”€ ObjectiveStep.tsx # Summary / objective text
โ”œโ”€โ”€ WorkExperienceStep.tsx # DnD-sortable work entries
โ”œโ”€โ”€ EducationStep.tsx # DnD-sortable education entries
โ”œโ”€โ”€ SkillsStep.tsx # Tag-based skills with proficiency level
โ”œโ”€โ”€ LanguagesStep.tsx # Language + CEFR proficiency
โ”œโ”€โ”€ CertificationsStep.tsx
โ”œโ”€โ”€ ReferencesStep.tsx
โ”œโ”€โ”€ TemplatePickerStep.tsx # Template + theme picker + ATS panel (US)
โ”œโ”€โ”€ JapanSpecificStep.tsx # ้€šๅ‹คๆ™‚้–“, ๆ‰ถ้คŠๅฎถๆ—, ้…ๅถ่€…, ่‡ชๅทฑPR, ๅฟ—ๆœ›ๅ‹•ๆฉŸ
โ””โ”€โ”€ StepHeader.tsx # Shared step title/description
```

---

## Architecture Notes

### Config-over-code
Every market's wizard steps, fields, validation rules, UI labels, and PDF layout are driven by `MarketConfig`. Components read the config at runtime โ€” no market-specific `if` branches in shared components. To change what a market shows, edit its config file.

### Data model
`CVData` is a single flat object shared across all markets. Market-specific optional fields (`nearestStation`, `commuteTime`, `selfPromotion`, `reasonForApplication`, etc.) are declared as optional on the shared type. The config controls which fields are rendered.

### Storage
CV data is stored in `localStorage` under versioned keys (`cv_maker_v1_{market}`). A migration function handles schema upgrades. The store autosaves on every change (debounced) and tracks `lastSaved`.

### Undo / Redo
A Zustand subscriber (outside React) captures CV snapshots every 2 seconds when the store is dirty. History is capped at 20 entries. The redo future is dropped on any new edit.

### PDF generation
`@react-pdf/renderer` v4 runs in a Web Worker. `wrap={false}` on entry ``s prevents mid-entry page breaks. The ModernPDF sidebar uses `minHeight: '100%'` on the outer flex row with `backgroundColor` directly on the sidebar `` so it extends correctly across multiple pages.

### Import parser
`parseRawCV(text, market)` returns `{ data: Partial, warnings: string[] }`. It detects sections by heading patterns, extracts contact info from the first 15 lines, and parses date ranges in many formats: ISO `YYYY-MM`, `MMM YYYY`, `MMM-YYYY`, `MM/YYYY`, Spanish month names, and plain year. Skills are capped at 30 with a warning.

### Share URL
CV data (minus the photo) is JSON-serialized, LZ-compressed, and base64-encoded into the URL query string. URLs over 2,000 characters trigger a warning modal before copying.

---

## Adding a New Market

1. Create `src/lib/markets/{market}.config.ts` implementing `MarketConfig`
2. Register it in `src/lib/markets/index.ts`
3. Add the market to the `Market` union in `src/types/cv.types.ts`
4. Add HTML preview renderers to `src/components/preview/renderers/`
5. Add PDF components to `src/lib/pdf/CVPDFDocument.tsx`
6. Add the market to `validMarkets` in `src/app/[market]/layout.tsx`

---

## Deploying

The app is fully static-compatible. Deploy on [Vercel](https://vercel.com) with zero configuration:

1. Fork or clone the repo
2. Import into Vercel โ€” auto-detects Next.js
3. Deploy

Optional environment variables:

- `ENABLE_POST_JOB=true` and `NEXT_PUBLIC_ENABLE_POST_JOB=true` to enable the job submission module
- `RESEND_API_KEY` to enable server-side email delivery for `/post-job` submissions
- `RESEND_FROM` to control sender identity (default: `GlobalCV Jobs `)

For Jobs source compliance hardening, you can optionally gate higher-risk providers:

- `JOBS_SAFE_MODE=false` and `NEXT_PUBLIC_JOBS_SAFE_MODE=false` to disable strict safe mode (not recommended for public launch)
- `ENABLE_ARBEITNOW_SOURCE=true` and `NEXT_PUBLIC_ENABLE_ARBEITNOW_SOURCE=true` to allow Arbeitnow while safe mode is on
- `ENABLE_4DAYWEEK_SOURCE=true` and `NEXT_PUBLIC_ENABLE_4DAYWEEK_SOURCE=true`
- `ENABLE_THEMUSE_SOURCE=true` and `NEXT_PUBLIC_ENABLE_THEMUSE_SOURCE=true`

By default, safe mode is ON and uncertain sources stay disabled.

---

## Security

- CV builder data is not sent to a server; optional `/post-job` submissions are sent to the backend and emailed via Resend
- All CV data is stored in `localStorage` and/or encoded in the share URL (LZ-compressed)
- **Privacy Mode** keeps everything in memory โ€” nothing written to disk
- Security headers enforced via `next.config.mjs`: `X-Frame-Options`, `X-Content-Type-Options`, `Strict-Transport-Security`, `Permissions-Policy`, and a Content Security Policy
- See [SECURITY.md](SECURITY.md) for the full security policy and vulnerability reporting

---

## License

MIT โ€” free to use, modify, and distribute.

---

*Made with care by [Bagalinis Consulting](https://bagalinis.com)*