Skip to content

feat(frontend): landing page redesign, public pages, resume picker, Adzuna pagination - #105

Merged
harmandeep2993 merged 18 commits into
mainfrom
feat/improvements
Jul 1, 2026
Merged

harmandeep2993 merged 18 commits into
mainfrom
feat/improvements

Conversation

@harmandeep2993

Copy link
Copy Markdown
Owner

Summary

  • Landing page rebuilt with Germany-specific copy: animated indigo app mockup, job
    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.
  • ResumePicker redesigned: flat scrollable list with all saved resumes + upload row
    visible simultaneously, no tab toggle.
  • New public pages wired into React Router:
    • /about - mission, Germany rationale, tech stack grid
    • /pricing - plan cards, full feature matrix table, pricing FAQ
    • /privacy - GDPR-aligned policy covering data storage, AI providers, user rights
  • Adzuna fetcher now paginates through 50-result pages up to 200 per title.
    SEARCH_PER_TITLE default raised from 5 to 200.
  • README rewritten to reflect the current React + FastAPI stack and Germany focus.

…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
…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.
Copilot AI review requested due to automatic review settings July 1, 2026 06:52
@harmandeep2993
harmandeep2993 merged commit a5fb82a into main Jul 1, 2026
1 check passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_TITLE to 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants