Skip to content

Commit d97b0c7

Browse files
committed
Fix CI backend tests and ship frontend UI overhaul
Replace the brittle test/**/*.test.js glob (fails on Linux Node 20 CI) with a cross-platform test runner script. Includes dashboard layout, portfolio template redesign, unified theming, and navbar polish.
1 parent 48d99ac commit d97b0c7

46 files changed

Lines changed: 3336 additions & 3420 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"scripts": {
88
"dev": "node --watch src/index.js",
99
"start": "node src/index.js",
10-
"test": "node --test test/**/*.test.js"
10+
"test": "node scripts/run-tests.mjs"
1111
},
1212
"dependencies": {
1313
"@clerk/express": "^1.0.0",

backend/scripts/run-tests.mjs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { readdirSync } from 'node:fs'
2+
import { spawnSync } from 'node:child_process'
3+
import { join, dirname } from 'node:path'
4+
import { fileURLToPath } from 'node:url'
5+
6+
const root = join(dirname(fileURLToPath(import.meta.url)), '..')
7+
const testDir = join(root, 'test')
8+
const files = readdirSync(testDir)
9+
.filter((name) => name.endsWith('.test.js'))
10+
.map((name) => join(testDir, name))
11+
.sort()
12+
13+
if (files.length === 0) {
14+
console.error('No test files found in backend/test/')
15+
process.exit(1)
16+
}
17+
18+
const result = spawnSync(process.execPath, ['--test', ...files], { stdio: 'inherit' })
19+
process.exit(result.status ?? 1)

frontend/index.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
2525
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
2626
<link rel="manifest" href="/manifest.json" />
27-
<meta name="theme-color" content="#6366f1" />
28-
<meta name="msapplication-TileColor" content="#6366f1" />
27+
<meta name="theme-color" content="#5a7a9e" />
28+
<meta name="msapplication-TileColor" content="#5a7a9e" />
2929

3030
<!-- Open Graph / Facebook -->
3131
<meta property="og:type" content="website" />
@@ -137,7 +137,7 @@
137137
<link rel="preconnect" href="https://fonts.googleapis.com">
138138
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
139139
<link
140-
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Outfit:wght@400;500;600;700;800&display=swap"
140+
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap"
141141
rel="stylesheet">
142142
<!-- Author / Creator Link -->
143143
<link rel="author" href="https://techycsr.dev" />

frontend/public/favicon.svg

Lines changed: 2 additions & 2 deletions
Loading

frontend/public/manifest.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
"description": "Transform your resume into a stunning, professional portfolio in seconds with AI.",
55
"start_url": "/",
66
"display": "standalone",
7-
"background_color": "#0f0f23",
8-
"theme_color": "#6366f1",
7+
"background_color": "#09090b",
8+
"theme_color": "#5a7a9e",
99
"orientation": "portrait-primary",
1010
"scope": "/",
1111
"lang": "en",

frontend/public/og-image.svg

Lines changed: 18 additions & 28 deletions
Loading

frontend/src/App.jsx

Lines changed: 23 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { SignIn, SignUp } from '@clerk/clerk-react'
33
import { ThemeProvider, useTheme } from './context/ThemeContext'
44
import { ToastProvider } from './context/ToastContext'
55
import Navbar from './components/Navbar'
6+
import ScrollToTop from './components/ScrollToTop'
67
import Landing from './pages/Landing'
78
import UsernameSelection from './pages/UsernameSelection'
89
import Onboarding from './pages/Onboarding'
@@ -14,106 +15,8 @@ import Analytics from './pages/Analytics'
1415
import Premium from './pages/Premium'
1516
import Portfolio from './pages/Portfolio'
1617
import ProtectedRoute from './components/ProtectedRoute'
17-
18-
// Clerk appearance config based on theme
19-
const getClerkAppearance = (theme) => ({
20-
baseTheme: theme === 'dark' ? undefined : undefined,
21-
variables: {
22-
colorPrimary: '#6366f1',
23-
colorBackground: theme === 'dark' ? '#1e1e2a' : '#ffffff',
24-
colorText: theme === 'dark' ? '#ffffff' : '#0f172a',
25-
colorTextSecondary: theme === 'dark' ? '#a0a0b0' : '#475569',
26-
colorInputBackground: theme === 'dark' ? '#1a1a25' : '#f1f5f9',
27-
colorInputText: theme === 'dark' ? '#ffffff' : '#0f172a',
28-
colorNeutral: theme === 'dark' ? '#a0a0b0' : '#475569',
29-
borderRadius: '12px',
30-
fontFamily: 'Inter, system-ui, sans-serif'
31-
},
32-
elements: {
33-
rootBox: {
34-
boxShadow: theme === 'dark'
35-
? '0 25px 50px -12px rgba(0, 0, 0, 0.5)'
36-
: '0 25px 50px -12px rgba(0, 0, 0, 0.15)'
37-
},
38-
card: {
39-
backgroundColor: theme === 'dark' ? '#1e1e2a' : '#ffffff',
40-
border: theme === 'dark' ? '1px solid rgba(255,255,255,0.08)' : '1px solid rgba(0,0,0,0.08)',
41-
boxShadow: 'none'
42-
},
43-
headerTitle: {
44-
color: theme === 'dark' ? '#ffffff' : '#0f172a'
45-
},
46-
headerSubtitle: {
47-
color: theme === 'dark' ? '#a0a0b0' : '#475569'
48-
},
49-
socialButtonsBlockButton: {
50-
backgroundColor: theme === 'dark' ? '#12121a' : '#f8fafc',
51-
border: theme === 'dark' ? '1px solid rgba(255,255,255,0.1)' : '1px solid rgba(0,0,0,0.1)',
52-
color: theme === 'dark' ? '#ffffff' : '#0f172a',
53-
'&:hover': {
54-
backgroundColor: theme === 'dark' ? '#1a1a25' : '#f1f5f9'
55-
}
56-
},
57-
formFieldLabel: {
58-
color: theme === 'dark' ? '#a0a0b0' : '#475569'
59-
},
60-
formFieldInput: {
61-
backgroundColor: theme === 'dark' ? '#12121a' : '#f8fafc',
62-
borderColor: theme === 'dark' ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.1)',
63-
color: theme === 'dark' ? '#ffffff' : '#0f172a',
64-
'&:focus': {
65-
borderColor: '#6366f1',
66-
boxShadow: '0 0 0 3px rgba(99, 102, 241, 0.2)'
67-
}
68-
},
69-
formButtonPrimary: {
70-
background: 'linear-gradient(135deg, #6366f1, #a855f7)',
71-
'&:hover': {
72-
background: 'linear-gradient(135deg, #4f46e5, #9333ea)'
73-
}
74-
},
75-
footerActionLink: {
76-
color: '#6366f1'
77-
},
78-
identityPreviewText: {
79-
color: theme === 'dark' ? '#ffffff' : '#0f172a'
80-
},
81-
identityPreviewEditButton: {
82-
color: '#6366f1'
83-
},
84-
formFieldHintText: {
85-
color: theme === 'dark' ? '#6b6b7b' : '#94a3b8'
86-
},
87-
dividerLine: {
88-
backgroundColor: theme === 'dark' ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.1)'
89-
},
90-
dividerText: {
91-
color: theme === 'dark' ? '#6b6b7b' : '#94a3b8'
92-
},
93-
userButtonPopoverCard: {
94-
backgroundColor: theme === 'dark' ? '#1e1e2a' : '#ffffff',
95-
border: theme === 'dark' ? '1px solid rgba(255,255,255,0.08)' : '1px solid rgba(0,0,0,0.08)'
96-
},
97-
userButtonPopoverActionButton: {
98-
color: theme === 'dark' ? '#ffffff' : '#0f172a',
99-
'&:hover': {
100-
backgroundColor: theme === 'dark' ? '#12121a' : '#f1f5f9'
101-
}
102-
},
103-
userButtonPopoverActionButtonText: {
104-
color: theme === 'dark' ? '#ffffff' : '#0f172a'
105-
},
106-
userButtonPopoverActionButtonIcon: {
107-
color: theme === 'dark' ? '#a0a0b0' : '#475569'
108-
},
109-
userPreviewMainIdentifier: {
110-
color: theme === 'dark' ? '#ffffff' : '#0f172a'
111-
},
112-
userPreviewSecondaryIdentifier: {
113-
color: theme === 'dark' ? '#a0a0b0' : '#475569'
114-
}
115-
}
116-
})
18+
import DashboardLayout from './components/DashboardLayout'
19+
import { getClerkAppearance } from './utils/clerkAppearance'
11720

11821
// Layout wrapper that conditionally shows navbar
11922
function AppLayout({ children }) {
@@ -133,12 +36,14 @@ function AppLayout({ children }) {
13336

13437
return (
13538
<>
136-
{/* Background orbs */}
137-
<div className="bg-orb orb-1" />
138-
<div className="bg-orb orb-2" />
139-
<div className="bg-orb orb-3" />
39+
{/* Background orbs — clipped so they never cause horizontal scroll */}
40+
<div className="orb-container" aria-hidden="true">
41+
<div className="bg-orb orb-1" />
42+
<div className="bg-orb orb-2" />
43+
<div className="bg-orb orb-3" />
44+
</div>
14045

141-
<div className="min-h-screen relative">
46+
<div className="min-h-screen relative overflow-x-clip">
14247
{!isPortfolioPage && <Navbar />}
14348
{children}
14449
</div>
@@ -152,7 +57,7 @@ function SignInPage() {
15257
const redirectUrl = location.state?.from?.pathname || '/dashboard'
15358

15459
return (
155-
<div className="min-h-screen flex items-center justify-center pt-20">
60+
<div className="min-h-screen flex items-center justify-center pt-navbar">
15661
<SignIn
15762
routing="path"
15863
path="/sign-in"
@@ -168,7 +73,7 @@ function SignInPage() {
16873
function SignUpPage() {
16974
const { theme } = useTheme()
17075
return (
171-
<div className="min-h-screen flex items-center justify-center pt-20">
76+
<div className="min-h-screen flex items-center justify-center pt-navbar">
17277
<SignUp
17378
routing="path"
17479
path="/sign-up"
@@ -199,36 +104,18 @@ function AppRoutes() {
199104
<Onboarding />
200105
</ProtectedRoute>
201106
} />
202-
<Route path="/upload" element={
203-
<ProtectedRoute>
204-
<ResumeUpload />
205-
</ProtectedRoute>
206-
} />
207-
<Route path="/editor" element={
208-
<ProtectedRoute>
209-
<ProfileEditor />
210-
</ProtectedRoute>
211-
} />
212-
<Route path="/dashboard" element={
213-
<ProtectedRoute>
214-
<Dashboard />
215-
</ProtectedRoute>
216-
} />
217-
<Route path="/settings" element={
218-
<ProtectedRoute>
219-
<Settings />
220-
</ProtectedRoute>
221-
} />
222-
<Route path="/analytics" element={
107+
<Route element={
223108
<ProtectedRoute>
224-
<Analytics />
109+
<DashboardLayout />
225110
</ProtectedRoute>
226-
} />
227-
<Route path="/premium" element={
228-
<ProtectedRoute>
229-
<Premium />
230-
</ProtectedRoute>
231-
} />
111+
}>
112+
<Route path="/upload" element={<ResumeUpload />} />
113+
<Route path="/editor" element={<ProfileEditor />} />
114+
<Route path="/dashboard" element={<Dashboard />} />
115+
<Route path="/settings" element={<Settings />} />
116+
<Route path="/analytics" element={<Analytics />} />
117+
<Route path="/premium" element={<Premium />} />
118+
</Route>
232119

233120
{/* Public portfolio route - must be last */}
234121
<Route path="/:username" element={<Portfolio />} />
@@ -242,6 +129,7 @@ function App() {
242129
<ThemeProvider>
243130
<ToastProvider>
244131
<Router>
132+
<ScrollToTop />
245133
<AppRoutes />
246134
</Router>
247135
</ToastProvider>

0 commit comments

Comments
 (0)