{"id":47593751,"url":"https://github.com/augustosc-eu/globalcv","last_synced_at":"2026-04-01T17:49:11.873Z","repository":{"id":345387518,"uuid":"1185701662","full_name":"augustosc-eu/globalcv","owner":"augustosc-eu","description":"A CV/Resume creation tool.","archived":false,"fork":false,"pushed_at":"2026-03-29T02:51:31.000Z","size":3035,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-29T03:10:36.202Z","etag":null,"topics":["cv","free","resume","tool","typescript","vercel"],"latest_commit_sha":null,"homepage":"https://globalcv.augustosc.com","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/augustosc-eu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","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-03-18T21:26:28.000Z","updated_at":"2026-03-29T02:51:35.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/augustosc-eu/globalcv","commit_stats":null,"previous_names":["augustosc-eu/globalcv"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/augustosc-eu/globalcv","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/augustosc-eu%2Fglobalcv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/augustosc-eu%2Fglobalcv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/augustosc-eu%2Fglobalcv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/augustosc-eu%2Fglobalcv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/augustosc-eu","download_url":"https://codeload.github.com/augustosc-eu/globalcv/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/augustosc-eu%2Fglobalcv/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31290618,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: 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":["cv","free","resume","tool","typescript","vercel"],"created_at":"2026-04-01T17:49:11.411Z","updated_at":"2026-04-01T17:49:11.859Z","avatar_url":"https://github.com/augustosc-eu.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GlobalCV\n\n**Free, privacy-first CV and resume builder for the global job market.**\n\nBuilt by [Bagalinis Consulting](https://bagalinis.com). No account required. No data leaves your browser.\n\n---\n\n## What it does\n\nGlobalCV 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.\n\n**Supported markets:**\n\n| Market | Page size | Templates | Language |\n|---|---|---|---|\n| 🇺🇸 United States | Letter | Classic, Modern | English |\n| 🇬🇧 United Kingdom | A4 | Classic CV, Modern CV | English |\n| 🇦🇺 Australia \u0026 NZ | A4 | Classic, Modern | English |\n| 🇮🇳 India | A4 | Classic CV, Modern CV | English |\n| 🇪🇺 European Union | A4 | Europass, Modern | English |\n| 🌎 Latin America | Letter | Traditional, Modern | Spanish |\n| 🇧🇷 Brasil | A4 | Tradicional, Moderno | Portuguese |\n| 🇯🇵 Japan | A4 | 履歴書 (Rirekisho), 職務経歴書 (Shokumu) | Japanese |\n\n**Market conventions enforced per locale:**\n\n| Market | Photo | DOB | Nationality | Marital status | Page limit |\n|---|---|---|---|---|---|\n| 🇺🇸 US | Hidden (discrimination law) | Hidden | Hidden | Hidden | 1 |\n| 🇬🇧 GB | Hidden (equality law) | Hidden | Hidden | Hidden | 2 |\n| 🇦🇺 AU | Hidden | Hidden | Hidden | Hidden | 3 |\n| 🇮🇳 IN | Optional | Optional | Optional | Optional | 2 |\n| 🇪🇺 EU | Optional | Optional | Optional | Hidden | 2 |\n| 🌎 LATAM | Required | Required | Required | Required | 2 |\n| 🇧🇷 BR | Optional | Optional | Optional | Optional | 2 |\n| 🇯🇵 JP | Required | Required | Required | Optional | — |\n\n---\n\n## Features\n\n### Editing\n- **Market-aware fields** — US hides date of birth and photo (anti-discrimination); Latam requires them; Japan requires a 証明写真, 生年月日, 通勤時間, and more\n- **Multiple templates per market** — 2 layouts per market with distinct visual styles\n- **6 color themes per market** — Swap accent colors in the header (desktop) or in the Template step (mobile)\n- **Undo / Redo** — 20-snapshot history with Cmd/Ctrl+Z / Y keyboard shortcuts; history is preserved for 2 seconds after each change\n- **Inline form validation** — Required fields, email format, and date range errors shown on blur\n\n### Preview \u0026 Export\n- **Live preview** — Zoomable (40–150%) side panel with page-count estimate\n- **Page limit warning** — Amber badge when content is estimated to exceed the market's recommended page count\n- **PDF export** — Downloads a print-ready PDF matching the selected template exactly, with correct page breaks and multi-page sidebars\n- **Mobile preview** — Full-screen preview modal accessible on small screens via a floating button\n\n### Import \u0026 Backup\n- **CV text import** — Paste any CV text (English or Spanish); the parser detects sections, dates, name, email, phone, and LinkedIn automatically\n- **Import warnings** — Shows which fields weren't detected and warns if the 30-skill cap is hit\n- **JSON backup** — Download your full CV as a `.json` file; restore it later with the Restore button\n- **Copy to market** — Copy all CV content to a different market's slot (preserves target market's template and theme defaults)\n\n### Sharing \u0026 Sync\n- **Share link** — Generates a compressed URL with your full CV data (photo excluded) — share or bookmark it\n- **Long-URL warning** — Warns before copying a link over 2,000 characters with a character count and privacy notice\n- **Cross-tab sync** — If another browser tab saves the same market's CV, a banner prompts you to reload\n\n### Privacy \u0026 Safety\n- **Privacy Mode** — Blurs all PII fields in the UI; toggle in the header\n- **Photo compression** — Uploaded photos are automatically resized to 800 px max (JPEG 85%) before storage; files over 8 MB are rejected\n- **Error boundary** — Catches render crashes with a \"Reload page\" fallback so a broken CV doesn't leave you stuck\n- **No backend** — All data stays in your browser (localStorage + URL state). Nothing is sent to a server\n- **No account** — Open the app, fill in your details, export your PDF\n\n### ATS (US market)\n- **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\n\n---\n\n## Privacy\n\n\u003e **Your CV never leaves your device.**\n\nGlobalCV 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.\n\nHosting is provided by [Vercel](https://vercel.com). No analytics or tracking scripts are used.\n\nThe 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.\n\n---\n\n## Tech Stack\n\n| | |\n|---|---|\n| Framework | Next.js 16 (App Router, Turbopack) |\n| UI | React 19, Tailwind CSS 3, Radix UI |\n| State | Zustand 4 + Immer |\n| Forms | react-hook-form 7 |\n| Drag \u0026 drop | @dnd-kit/core + sortable |\n| PDF generation | @react-pdf/renderer 4 |\n| Share URL compression | lz-string |\n| Icons | lucide-react |\n| Language | TypeScript 5.9 |\n\n---\n\n## Getting Started\n\n```bash\ngit clone https://github.com/augustosc-eu/globalcv.git\ncd globalcv\nnpm install\nnpm run dev      # http://localhost:3000\nnpm run build    # production build\nnpm run lint     # ESLint\n```\n\nOpen [http://localhost:3000](http://localhost:3000) and select a market to begin.\n\n**Requirements:** Node.js 18+\n\n---\n\n## Project Structure\n\n```\nsrc/\n├── app/\n│   ├── page.tsx                  # Market selector landing page\n│   ├── [market]/\n│   │   ├── layout.tsx            # Market validation + ErrorBoundary + PrivacyBanner\n│   │   └── page.tsx              # Renders WizardShell for the market\n│   ├── privacy/page.tsx\n│   └── terms/page.tsx\n│\n├── types/\n│   ├── cv.types.ts               # CVData, PersonalInfo, WorkExperience, …\n│   └── market.types.ts           # MarketConfig shape\n│\n├── lib/\n│   ├── markets/\n│   │   ├── us.config.ts          # US market config\n│   │   ├── eu.config.ts          # EU market config\n│   │   ├── latam.config.ts       # Latam market config\n│   │   ├── jp.config.ts          # Japan market config\n│   │   ├── ui.ts                 # Shared UI label helpers\n│   │   └── index.ts              # getMarketConfig(), isValidMarket()\n│   ├── parser/\n│   │   └── cvParser.ts           # Paste-import parser → ParseResult { data, warnings }\n│   ├── pdf/\n│   │   └── CVPDFDocument.tsx     # All PDF layouts (Classic, Modern, Europass, Shokumu, …)\n│   ├── sharing/\n│   │   └── shareUrl.ts           # encodeCVToURL / decodeCVFromURL (lz-string)\n│   ├── storage/\n│   │   └── localStorage.ts       # saveCV / loadCV / clearCV — versioned + migration\n│   └── utils/\n│       ├── cn.ts                 # Tailwind class merge helper\n│       ├── dateFormat.ts         # Wareki + locale date formatting\n│       └── theme.ts              # Color theme utilities\n│\n├── store/\n│   └── cvStore.ts                # Zustand store — state, autosave, undo/redo, restoreCV\n│\n├── hooks/\n│   └── usePDFExport.ts           # PDF generation state machine (idle/generating/done/error)\n│\n└── components/\n    ├── form-fields/\n    │   ├── DateRangePicker.tsx   # Start/end date + \"present\" toggle + validation\n    │   └── PhotoUpload.tsx       # Canvas compression + 8 MB limit\n    │\n    ├── preview/\n    │   ├── PreviewPane.tsx       # Zoomable preview with page-count warning\n    │   └── renderers/\n    │       ├── USClassicRenderer.tsx\n    │       ├── USModernRenderer.tsx\n    │       ├── EUEuropassRenderer.tsx\n    │       ├── EUModernRenderer.tsx\n    │       ├── LatamTraditionalRenderer.tsx\n    │       ├── LatamModernRenderer.tsx\n    │       ├── JapanRirekishoRenderer.tsx\n    │       └── JapanShokumuRenderer.tsx\n    │\n    ├── shared/\n    │   ├── AppHeader.tsx            # Save status, undo/redo, import, share, backup, PDF export\n    │   ├── ATSSuggestionsPanel.tsx  # 10-point ATS score with tips (US market)\n    │   ├── CopyToMarketModal.tsx    # Copy CV content to another market\n    │   ├── CrossTabSyncBanner.tsx   # Reload prompt when another tab saves the same market\n    │   ├── ErrorBoundary.tsx        # React error boundary with reload fallback\n    │   ├── PasteImportModal.tsx     # 3-step paste → preview → apply import flow\n    │   ├── PrivacyBanner.tsx        # Top-of-page privacy notice\n    │   ├── ShareButton.tsx          # Copy share link with long-URL warning modal\n    │   └── ThemeSelector.tsx        # Color theme picker\n    │\n    └── wizard/\n        ├── WizardShell.tsx          # Main layout: sidebar nav + form area + preview pane\n        ├── WizardProgress.tsx       # Step list with completion indicators\n        ├── WizardNavigation.tsx     # Prev / Next buttons\n        ├── StepRouter.tsx           # Maps step key → step component\n        └── steps/\n            ├── PersonalInfoStep.tsx    # Name, contact, photo, address (validated)\n            ├── ObjectiveStep.tsx       # Summary / objective text\n            ├── WorkExperienceStep.tsx  # DnD-sortable work entries\n            ├── EducationStep.tsx       # DnD-sortable education entries\n            ├── SkillsStep.tsx          # Tag-based skills with proficiency level\n            ├── LanguagesStep.tsx       # Language + CEFR proficiency\n            ├── CertificationsStep.tsx\n            ├── ReferencesStep.tsx\n            ├── TemplatePickerStep.tsx  # Template + theme picker + ATS panel (US)\n            ├── JapanSpecificStep.tsx   # 通勤時間, 扶養家族, 配偶者, 自己PR, 志望動機\n            └── StepHeader.tsx          # Shared step title/description\n```\n\n---\n\n## Architecture Notes\n\n### Config-over-code\nEvery 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.\n\n### Data model\n`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.\n\n### Storage\nCV 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`.\n\n### Undo / Redo\nA 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.\n\n### PDF generation\n`@react-pdf/renderer` v4 runs in a Web Worker. `wrap={false}` on entry `\u003cView\u003e`s prevents mid-entry page breaks. The ModernPDF sidebar uses `minHeight: '100%'` on the outer flex row with `backgroundColor` directly on the sidebar `\u003cView\u003e` so it extends correctly across multiple pages.\n\n### Import parser\n`parseRawCV(text, market)` returns `{ data: Partial\u003cCVData\u003e, 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.\n\n### Share URL\nCV 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.\n\n---\n\n## Adding a New Market\n\n1. Create `src/lib/markets/{market}.config.ts` implementing `MarketConfig`\n2. Register it in `src/lib/markets/index.ts`\n3. Add the market to the `Market` union in `src/types/cv.types.ts`\n4. Add HTML preview renderers to `src/components/preview/renderers/`\n5. Add PDF components to `src/lib/pdf/CVPDFDocument.tsx`\n6. Add the market to `validMarkets` in `src/app/[market]/layout.tsx`\n\n---\n\n## Deploying\n\nThe app is fully static-compatible. Deploy on [Vercel](https://vercel.com) with zero configuration:\n\n1. Fork or clone the repo\n2. Import into Vercel — auto-detects Next.js\n3. Deploy\n\nOptional environment variables:\n\n- `ENABLE_POST_JOB=true` and `NEXT_PUBLIC_ENABLE_POST_JOB=true` to enable the job submission module\n- `RESEND_API_KEY` to enable server-side email delivery for `/post-job` submissions\n- `RESEND_FROM` to control sender identity (default: `GlobalCV Jobs \u003chello@augustosc.com\u003e`)\n\nFor Jobs source compliance hardening, you can optionally gate higher-risk providers:\n\n- `JOBS_SAFE_MODE=false` and `NEXT_PUBLIC_JOBS_SAFE_MODE=false` to disable strict safe mode (not recommended for public launch)\n- `ENABLE_ARBEITNOW_SOURCE=true` and `NEXT_PUBLIC_ENABLE_ARBEITNOW_SOURCE=true` to allow Arbeitnow while safe mode is on\n- `ENABLE_4DAYWEEK_SOURCE=true` and `NEXT_PUBLIC_ENABLE_4DAYWEEK_SOURCE=true`\n- `ENABLE_THEMUSE_SOURCE=true` and `NEXT_PUBLIC_ENABLE_THEMUSE_SOURCE=true`\n\nBy default, safe mode is ON and uncertain sources stay disabled.\n\n---\n\n## Security\n\n- CV builder data is not sent to a server; optional `/post-job` submissions are sent to the backend and emailed via Resend\n- All CV data is stored in `localStorage` and/or encoded in the share URL (LZ-compressed)\n- **Privacy Mode** keeps everything in memory — nothing written to disk\n- Security headers enforced via `next.config.mjs`: `X-Frame-Options`, `X-Content-Type-Options`, `Strict-Transport-Security`, `Permissions-Policy`, and a Content Security Policy\n- See [SECURITY.md](SECURITY.md) for the full security policy and vulnerability reporting\n\n---\n\n## License\n\nMIT — free to use, modify, and distribute.\n\n---\n\n*Made with care by [Bagalinis Consulting](https://bagalinis.com)*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faugustosc-eu%2Fglobalcv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faugustosc-eu%2Fglobalcv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faugustosc-eu%2Fglobalcv/lists"}