Repository navigation
feat(frontend): landing page redesign, public pages, resume picker, Adzuna pagination - #105
Merged
Merged
Conversation
…ts, fixed spacing
…o-column analyzer - Indigo accent (99 102 241) with RGB channel CSS variables for Tailwind opacity modifiers - Plus Jakarta Sans headings + Inter body font pairing via Google Fonts - AppShell: AnimatePresence + motion.div tab transitions (fade+slide) - Sidebar: layoutId spring animation for active indicator dot - TopBar: glassmorphism blur, brand logotype, sign-out only (dark mode removed) - Analyzer: two-column split layout - inputs left, results slide in on right; drag-and-drop upload zone; animated score bars - Toast: framer-motion slide-in + scale from bottom-right with AnimatePresence exit - JobMatches: staggerChildren animation on job card list - All colors via CSS custom properties - no hardcoded values in components
…nd action button bottom-right
…ton, change file link
…th, poll extraction status
…cate name display
…na pagination Landing page rebuilt with Germany-specific copy throughout - hero with animated indigo mockup, job ticker, stats bar, how-it-works, comparison table, pricing section (Free/Pro), FAQ accordion, and CTA banner. All mockup colors aligned to the indigo accent palette. ResumePicker replaced tab toggle with a flat scrollable list - saved resumes and upload row visible simultaneously, no switching required. New public pages added: /about (mission, tech stack, Germany rationale), /pricing (plan cards + full feature matrix + FAQ), /privacy (GDPR-aligned policy). All wired into React Router in App.jsx. Adzuna fetcher now paginates automatically - loops 50-result pages up to MAX_RESULTS_PER_QUERY (200) per title instead of stopping at the first page. SEARCH_PER_TITLE default raised from 5 to 200 in config and config.example.yaml. README rewritten to reflect the current React + FastAPI stack, updated project structure, and Germany job board focus.
There was a problem hiding this comment.
Pull request overview
This PR modernizes the JobsFitAI user-facing experience (public marketing pages + in-app UI) around an indigo design system, adds new public routes (About/Pricing/Privacy), and expands the Adzuna fetcher to paginate up to a higher per-title cap to support deeper job matching in Germany.
Changes:
- Rebuilt the landing page and introduced new public pages (/about, /pricing, /privacy) with Framer Motion animations and updated typography.
- Refactored in-app UI to use shared UI primitives, redesigned ResumePicker/Resumes tab, and refreshed multiple tabs (Analyzer/ATS/History/JobMatches/Settings).
- Updated Adzuna fetcher to paginate 50-result pages up to 200 results per query and raised default
SEARCH_PER_TITLEto 200; updated docs/config examples accordingly.
Reviewed changes
Copilot reviewed 29 out of 30 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Updates project description, stack, and Germany focus; documents local run steps and API summary. |
| frontend/tailwind.config.js | Switches to RGB-channel CSS variables for opacity modifiers; updates radii/shadows/typography tokens. |
| frontend/src/pages/Privacy.jsx | Adds GDPR-oriented privacy policy page and public navigation/footer. |
| frontend/src/pages/Pricing.jsx | Adds pricing page with plan cards, feature matrix, and FAQ (uses Framer Motion). |
| frontend/src/pages/Login.jsx | Redesigns login/register UI and copy; adds “back to home” link. |
| frontend/src/pages/Landing.jsx | Major landing page redesign with mockups, animations, comparison, pricing, FAQ, CTA. |
| frontend/src/pages/About.jsx | Adds about page describing mission, Germany rationale, and tech stack grid. |
| frontend/src/lib/auth.js | Changes logout redirect destination to /. |
| frontend/src/layouts/AppShell.jsx | Adds animated tab transitions; removes dark-mode props. |
| frontend/src/index.css | Replaces token system with RGB CSS variables; adds reusable component classes (card/buttons/inputs) and focus ring. |
| frontend/src/components/ui.jsx | Introduces shared UI primitives (PageHeader, Card, EmptyState, score widgets, etc.). |
| frontend/src/components/TopBar.jsx | Redesigns top bar styling; removes theme toggle UI. |
| frontend/src/components/Toast.jsx | Adds Framer Motion-based toast animations and type styling. |
| frontend/src/components/tabs/Settings.jsx | Refactors settings UI to shared primitives; improves save states and copy. |
| frontend/src/components/tabs/Resumes.jsx | Redesigns resume management with preview modal, inline rename, and card grid. |
| frontend/src/components/tabs/JobMatches.jsx | Redesigns job matches list with animations, stats, better empty states, and actions. |
| frontend/src/components/tabs/History.jsx | Refactors history tab to shared primitives; improves empty states and formatting. |
| frontend/src/components/tabs/ATS.jsx | Integrates ResumePicker and redesigned ATS check/optimise flows with new layout. |
| frontend/src/components/tabs/Analyzer.jsx | Integrates ResumePicker and redesigned analyzer UX + richer results panel. |
| frontend/src/components/Sidebar.jsx | Redesigns sidebar nav, ordering, and active-state indicator (Framer Motion). |
| frontend/src/components/ResumePicker.jsx | Adds shared ResumePicker component for stored resumes + upload row (no tab toggle). |
| frontend/src/App.jsx | Wires new public routes and removes dark-mode state/props from routing. |
| frontend/package.json | Adds Framer Motion dependency. |
| frontend/package-lock.json | Locks Framer Motion (and motion-* deps + tslib). |
| frontend/index.html | Adds Plus Jakarta Sans font and updates font loading. |
| backend/services/fetchers/job_fetcher.py | Adds Adzuna pagination (50/page) with caps and throttling; raises per-title default to 200. |
| backend/repositories/resume_repo.py | Adds extracted_json presence flag to resume list query output. |
| backend/main.py | Avoids crash by only reading app-password login HTML when auth is enabled and file exists. |
| backend/core/config.py | Raises default SEARCH_PER_TITLE to 200. |
| backend/config.example.yaml | Updates job_search per_title_results documentation to reflect pagination and cap. |
Files not reviewed (1)
- frontend/package-lock.json: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+190
to
+206
| {MATRIX.map(group => ( | ||
| <> | ||
| <tr key={group.section + '_header'} | ||
| style={{ background: 'rgba(99,102,241,0.04)', borderTop: '1px solid rgba(0,0,0,0.06)', borderBottom: '1px solid rgba(0,0,0,0.06)' }}> | ||
| <td colSpan={3} className="px-5 py-2 text-[11px] font-bold uppercase tracking-widest" | ||
| style={{ color: 'rgb(99,102,241)' }}>{group.section}</td> | ||
| </tr> | ||
| {group.rows.map((row, ri) => ( | ||
| <tr key={row.label} | ||
| style={{ borderBottom: '1px solid rgba(0,0,0,0.05)', background: ri % 2 === 0 ? 'white' : 'rgb(250,250,252)' }}> | ||
| <td className="px-5 py-3" style={{ color: 'rgb(55,65,81)' }}>{row.label}</td> | ||
| <td className="px-5 py-3 text-center">{row.free ? CHECK : CROSS}</td> | ||
| <td className="px-5 py-3 text-center">{row.pro ? CHECK : CROSS}</td> | ||
| </tr> | ||
| ))} | ||
| </> | ||
| ))} |
Comment on lines
126
to
133
| async function exportCsv() { | ||
| const res = await apiFetch('/api/match/export') | ||
| if (!res?.ok) { toast('Export failed', 'error'); return } | ||
| const blob = await res.blob() | ||
| const url = URL.createObjectURL(blob) | ||
| const a = document.createElement('a') | ||
| a.href = url; a.download = 'job_matches.csv'; a.click() | ||
| URL.revokeObjectURL(url) | ||
| a.href = URL.createObjectURL(blob); a.download = 'job_matches.csv'; a.click() | ||
| toast('Exported', 'success') | ||
| } |
Comment on lines
116
to
119
| async function toggleApplied(id) { | ||
| await apiFetch('/api/match/applied', { method: 'POST', body: JSON.stringify({ id }) }) | ||
| load() | ||
| setState(s => s ? { ...s, results: s.results.map(r => r.id === id ? { ...r, applied: !r.applied } : r) } : s) | ||
| } |
Comment on lines
+207
to
+211
| const res = await apiFetch('/api/analyze', { method: 'POST', body: JSON.stringify(body) }) | ||
| if (!res?.ok) { | ||
| const errData = await res.json().catch(() => ({})) | ||
| toast(errData.error || errData.detail || 'Analysis failed', 'error'); return | ||
| } |
Comment on lines
+316
to
331
| <div className="grid grid-cols-1 md:grid-cols-3 gap-4 items-start"> | ||
| {resumes.map((r, i) => ( | ||
| <ResumeCard | ||
| key={r.id} | ||
| resume={r} | ||
| index={i} | ||
| onDelete={del} | ||
| onLabel={saveLabel} | ||
| onUseForMatching={useForMatching} | ||
| onPreview={setPreviewing} | ||
| /> | ||
| ))} | ||
| {canAddMore && ( | ||
| <AddResumeCard nextSlot={nextSlot} onUpload={upload} /> | ||
| )} | ||
| </div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ticker, stats bar, how-it-works, comparison table (vs Jobscan vs manual), pricing
section (Free/Pro), FAQ accordion, CTA banner. All mockup colors aligned to the indigo
accent palette.
visible simultaneously, no tab toggle.
SEARCH_PER_TITLE default raised from 5 to 200.