abhishek-portfolio-template 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/README.md +59 -0
  2. package/bin/cli.js +54 -0
  3. package/package.json +27 -0
  4. package/template/components.json +22 -0
  5. package/template/next.config.ts +79 -0
  6. package/template/package.json +43 -0
  7. package/template/postcss.config.js +6 -0
  8. package/template/public/BoliviaSignature-ZpWnz.ttf +0 -0
  9. package/template/public/Gemini_Generated_Image_xc97toxc97toxc97.png +0 -0
  10. package/template/public/Hendrigo.otf +0 -0
  11. package/template/public/audiomass-output.mp3 +0 -0
  12. package/template/public/file.svg +1 -0
  13. package/template/public/globe.svg +1 -0
  14. package/template/public/googlec77e59474f5a09cb.html +1 -0
  15. package/template/public/icon-192x192.png +0 -0
  16. package/template/public/icon-512x512.png +0 -0
  17. package/template/public/next.svg +1 -0
  18. package/template/public/paper sound .mpeg +0 -0
  19. package/template/public/removebg.png +0 -0
  20. package/template/public/resume.pdf +0 -0
  21. package/template/public/sw.js +1 -0
  22. package/template/public/swe-worker-5c72df51bb1f6ee0.js +1 -0
  23. package/template/public/vercel.svg +1 -0
  24. package/template/public/window.svg +1 -0
  25. package/template/public/workbox-f1770938.js +1 -0
  26. package/template/src/app/about/page.tsx +91 -0
  27. package/template/src/app/actions/optimize-text.ts +54 -0
  28. package/template/src/app/gaming/page.tsx +308 -0
  29. package/template/src/app/github/[username]/page.tsx +97 -0
  30. package/template/src/app/globals.css +321 -0
  31. package/template/src/app/layout.tsx +39 -0
  32. package/template/src/app/manifest.ts +25 -0
  33. package/template/src/app/not-found.tsx +16 -0
  34. package/template/src/app/page.tsx +28 -0
  35. package/template/src/app/robots.ts +12 -0
  36. package/template/src/app/sitemap.ts +38 -0
  37. package/template/src/app/template.tsx +5 -0
  38. package/template/src/app/works/[slug]/page.tsx +50 -0
  39. package/template/src/app/works/client.tsx +44 -0
  40. package/template/src/app/works/page.tsx +24 -0
  41. package/template/src/components/about/about-client.tsx +259 -0
  42. package/template/src/components/home/bento-gallery.tsx +52 -0
  43. package/template/src/components/home/contact-section.tsx +34 -0
  44. package/template/src/components/home/craft-card.tsx +18 -0
  45. package/template/src/components/home/featured-projects.tsx +186 -0
  46. package/template/src/components/home/focus-card.tsx +171 -0
  47. package/template/src/components/home/identity-card.tsx +45 -0
  48. package/template/src/components/home/philosophy-card.tsx +104 -0
  49. package/template/src/components/home/skills-in-motion.tsx +109 -0
  50. package/template/src/components/home/tech-stack-marquee.tsx +56 -0
  51. package/template/src/components/ui/3d-folder.tsx +569 -0
  52. package/template/src/components/ui/avatar.tsx +50 -0
  53. package/template/src/components/ui/badge.tsx +36 -0
  54. package/template/src/components/ui/basic-avatar.tsx +12 -0
  55. package/template/src/components/ui/button.tsx +117 -0
  56. package/template/src/components/ui/clipboard-secret.tsx +39 -0
  57. package/template/src/components/ui/command-menu.tsx +519 -0
  58. package/template/src/components/ui/command-palette.tsx +152 -0
  59. package/template/src/components/ui/consciousness-mode.tsx +200 -0
  60. package/template/src/components/ui/copy-code-button.tsx +135 -0
  61. package/template/src/components/ui/display-cards.tsx +70 -0
  62. package/template/src/components/ui/dotted-map.tsx +128 -0
  63. package/template/src/components/ui/dropdown-menu.tsx +200 -0
  64. package/template/src/components/ui/emoji-rating.tsx +123 -0
  65. package/template/src/components/ui/exit-message.tsx +50 -0
  66. package/template/src/components/ui/image-zoom-overlay.tsx +178 -0
  67. package/template/src/components/ui/input-otp.tsx +71 -0
  68. package/template/src/components/ui/kbd.tsx +87 -0
  69. package/template/src/components/ui/location-tag.tsx +232 -0
  70. package/template/src/components/ui/minimal-testimonial.tsx +97 -0
  71. package/template/src/components/ui/mobile-menu.tsx +191 -0
  72. package/template/src/components/ui/navbar.tsx +148 -0
  73. package/template/src/components/ui/page-transition.tsx +24 -0
  74. package/template/src/components/ui/pixeleted-404-not-found.tsx +110 -0
  75. package/template/src/components/ui/preloader-wrapper.tsx +102 -0
  76. package/template/src/components/ui/preloader.tsx +104 -0
  77. package/template/src/components/ui/project-contributors.tsx +57 -0
  78. package/template/src/components/ui/scroll-area.tsx +117 -0
  79. package/template/src/components/ui/signature.tsx +173 -0
  80. package/template/src/components/ui/smooth-scroll.tsx +31 -0
  81. package/template/src/components/ui/social-icons.tsx +103 -0
  82. package/template/src/components/ui/social-stories.tsx +394 -0
  83. package/template/src/components/ui/sound-constants.ts +1 -0
  84. package/template/src/components/ui/text-explode.tsx +188 -0
  85. package/template/src/components/ui/toast.tsx +80 -0
  86. package/template/src/components/ui/tooltip.tsx +30 -0
  87. package/template/src/components/ui/user-location.tsx +151 -0
  88. package/template/src/components/ui/vertical-image-stack.tsx +345 -0
  89. package/template/src/components/works/changelog-overlay.tsx +212 -0
  90. package/template/src/components/works/currently-working-card.tsx +130 -0
  91. package/template/src/components/works/project-details-view.tsx +464 -0
  92. package/template/src/components/works/project-grid.tsx +81 -0
  93. package/template/src/fonts/BoliviaSignature-ZpWnz.ttf +0 -0
  94. package/template/src/fonts/Hendrigo.otf +0 -0
  95. package/template/src/lib/data.ts +61 -0
  96. package/template/src/lib/fonts.ts +14 -0
  97. package/template/src/lib/github.ts +15 -0
  98. package/template/src/lib/supabase.ts +11 -0
  99. package/template/src/lib/utils.ts +6 -0
  100. package/template/tailwind.config.ts +31 -0
  101. package/template/tsconfig.json +34 -0
@@ -0,0 +1,321 @@
1
+ @import "tailwindcss";
2
+
3
+ @custom-variant dark (&:is(.dark *));
4
+ @plugin "tailwindcss-animate";
5
+
6
+ @theme {
7
+ --color-folder-back: var(--folder-back);
8
+ --color-folder-front: var(--folder-front);
9
+ --color-folder-tab: var(--folder-tab);
10
+
11
+ --color-background: var(--background);
12
+ --color-foreground: var(--foreground);
13
+ --color-card: var(--card);
14
+ --color-card-foreground: var(--card-foreground);
15
+ --color-popover: var(--popover);
16
+ --color-popover-foreground: var(--popover-foreground);
17
+ --color-primary: var(--primary);
18
+ --color-primary-foreground: var(--primary-foreground);
19
+ --color-secondary: var(--secondary);
20
+ --color-secondary-foreground: var(--secondary-foreground);
21
+ --color-muted: var(--muted);
22
+ --color-muted-foreground: var(--muted-foreground);
23
+ --color-accent: var(--accent);
24
+ --color-accent-foreground: var(--accent-foreground);
25
+ --color-destructive: var(--destructive);
26
+ --color-destructive-foreground: var(--destructive-foreground);
27
+ --color-border: var(--border);
28
+ --color-input: var(--input);
29
+ --color-ring: var(--ring);
30
+
31
+ @keyframes spin-slow {
32
+ from {
33
+ transform: rotate(0deg);
34
+ }
35
+
36
+ to {
37
+ transform: rotate(360deg);
38
+ }
39
+ }
40
+
41
+ --animate-spin-slow: spin-slow 20s linear infinite;
42
+ }
43
+
44
+ /* User Provided Variables for Command Menu */
45
+ :root {
46
+ --hu-font-geist: var(--font-geist);
47
+ --hu-font-jetbrains: var(--font-jetbrains-mono);
48
+ --hu-background: 0, 0%, 100%;
49
+ --hu-foreground: 0, 0%, 14%;
50
+ --hu-card: 0, 0%, 99%;
51
+ --hu-card-foreground: 0, 0%, 14%;
52
+ --hu-primary: 235, 100%, 60%;
53
+ --hu-primary-foreground: 0, 0%, 98%;
54
+ --hu-secondary: 0, 0%, 97%;
55
+ --hu-secondary-foreground: 0, 0%, 20%;
56
+ --hu-muted: 0, 0%, 97%;
57
+ --hu-muted-foreground: 0, 0%, 56%;
58
+ --hu-accent: 0, 0%, 96%;
59
+ --hu-accent-foreground: 0, 0%, 20%;
60
+ --hu-destructive: 9, 96%, 47%;
61
+ --hu-destructive-foreground: 0, 0%, 98%;
62
+ --hu-border: 0, 0%, 92%;
63
+ --hu-input: 0, 0%, 100%;
64
+ --hu-ring: 0, 0%, 71%;
65
+ --color-fd-background: hsl(var(--hu-background));
66
+ --color-fd-card: hsl(var(--hu-background));
67
+ }
68
+
69
+ .dark {
70
+ --hu-background: 0, 0%, 7%;
71
+ --hu-foreground: 0, 0%, 100%;
72
+ --hu-card: 0, 0%, 9%;
73
+ --hu-card-foreground: 0, 0%, 100%;
74
+ --hu-primary: 235, 100%, 60%;
75
+ --hu-primary-foreground: 0, 0%, 98%;
76
+ --hu-secondary: 0, 0%, 15%;
77
+ --hu-secondary-foreground: 0, 0%, 100%;
78
+ --hu-muted: 0, 0%, 15%;
79
+ --hu-muted-foreground: 0, 0%, 71%;
80
+ --hu-accent: 0, 0%, 15%;
81
+ --hu-accent-foreground: 0, 0%, 100%;
82
+ --hu-destructive: 0, 84%, 50%;
83
+ --hu-destructive-foreground: 0, 0%, 98%;
84
+ --hu-border: 0, 0%, 100%, 10%;
85
+ --hu-input: 0, 0%, 100%, 5%;
86
+ --hu-ring: 0, 0%, 56%;
87
+ --color-fd-background: hsl(var(--hu-background));
88
+ --color-fd-card: hsl(var(--hu-background));
89
+ }
90
+
91
+ :root {
92
+ /* Core Dark Theme */
93
+
94
+ --card: oklch(1 0 0);
95
+ --card-foreground: oklch(0.145 0 0);
96
+
97
+ --popover: oklch(1 0 0);
98
+ --popover-foreground: oklch(0.145 0 0);
99
+
100
+ --primary: oklch(0.205 0 0);
101
+ --primary-foreground: oklch(0.985 0 0);
102
+
103
+ --secondary: oklch(0.97 0 0);
104
+ --secondary-foreground: oklch(0.205 0 0);
105
+
106
+ --muted: oklch(0.97 0 0);
107
+ --muted-foreground: oklch(0.556 0 0);
108
+
109
+ --accent: oklch(0.97 0 0);
110
+ --accent-foreground: oklch(0.205 0 0);
111
+
112
+ --destructive: oklch(0.577 0.245 27.325);
113
+ --destructive-foreground: #ffffff;
114
+
115
+ --border: oklch(0.922 0 0);
116
+ --input: oklch(0.922 0 0);
117
+ --ring: oklch(0.708 0 0);
118
+
119
+ --radius: 0.625rem;
120
+
121
+ /* Animated Folder Colors - Using OKLCH values for the specific folder look */
122
+ /* These values roughly correspond to a warm orange/gold folder */
123
+ --folder-back: oklch(0.65 0.12 45);
124
+ --folder-front: oklch(0.7 0.14 50);
125
+ --folder-tab: oklch(0.6 0.1 40);
126
+ --background: oklch(1 0 0);
127
+ --foreground: oklch(0.145 0 0);
128
+ --chart-1: oklch(0.646 0.222 41.116);
129
+ --chart-2: oklch(0.6 0.118 184.704);
130
+ --chart-3: oklch(0.398 0.07 227.392);
131
+ --chart-4: oklch(0.828 0.189 84.429);
132
+ --chart-5: oklch(0.769 0.188 70.08);
133
+ --sidebar: oklch(0.985 0 0);
134
+ --sidebar-foreground: oklch(0.145 0 0);
135
+ --sidebar-primary: oklch(0.205 0 0);
136
+ --sidebar-primary-foreground: oklch(0.985 0 0);
137
+ --sidebar-accent: oklch(0.97 0 0);
138
+ --sidebar-accent-foreground: oklch(0.205 0 0);
139
+ --sidebar-border: oklch(0.922 0 0);
140
+ --sidebar-ring: oklch(0.708 0 0);
141
+ }
142
+
143
+ html,
144
+ body {
145
+ background-color: #0a0a0a;
146
+ /* Force dark background immediately */
147
+ color: #ededed;
148
+ overscroll-behavior: none;
149
+ touch-action: manipulation;
150
+ }
151
+
152
+ body {
153
+ @apply bg-background text-foreground;
154
+ }
155
+
156
+ @theme inline {
157
+ --radius-sm: calc(var(--radius) - 4px);
158
+ --radius-md: calc(var(--radius) - 2px);
159
+ --radius-lg: var(--radius);
160
+ --radius-xl: calc(var(--radius) + 4px);
161
+ --radius-2xl: calc(var(--radius) + 8px);
162
+ --radius-3xl: calc(var(--radius) + 12px);
163
+ --radius-4xl: calc(var(--radius) + 16px);
164
+ --color-background: var(--background);
165
+ --color-foreground: var(--foreground);
166
+ --color-card: var(--card);
167
+ --color-card-foreground: var(--card-foreground);
168
+ --color-popover: var(--popover);
169
+ --color-popover-foreground: var(--popover-foreground);
170
+ --color-primary: var(--primary);
171
+ --color-primary-foreground: var(--primary-foreground);
172
+ --color-secondary: var(--secondary);
173
+ --color-secondary-foreground: var(--secondary-foreground);
174
+ --color-muted: var(--muted);
175
+ --color-muted-foreground: var(--muted-foreground);
176
+ --color-accent: var(--accent);
177
+ --color-accent-foreground: var(--accent-foreground);
178
+ --color-destructive: var(--destructive);
179
+ --color-border: var(--border);
180
+ --color-input: var(--input);
181
+ --color-ring: var(--ring);
182
+ --color-chart-1: var(--chart-1);
183
+ --color-chart-2: var(--chart-2);
184
+ --color-chart-3: var(--chart-3);
185
+ --color-chart-4: var(--chart-4);
186
+ --color-chart-5: var(--chart-5);
187
+ --color-sidebar: var(--sidebar);
188
+ --color-sidebar-foreground: var(--sidebar-foreground);
189
+ --color-sidebar-primary: var(--sidebar-primary);
190
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
191
+ --color-sidebar-accent: var(--sidebar-accent);
192
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
193
+ --color-sidebar-border: var(--sidebar-border);
194
+ --color-sidebar-ring: var(--sidebar-ring);
195
+ }
196
+
197
+ .dark {
198
+ --background: oklch(0.145 0 0);
199
+ --foreground: oklch(0.985 0 0);
200
+ --card: oklch(0.205 0 0);
201
+ --card-foreground: oklch(0.985 0 0);
202
+ --popover: oklch(0.205 0 0);
203
+ --popover-foreground: oklch(0.985 0 0);
204
+ --primary: oklch(0.922 0 0);
205
+ --primary-foreground: oklch(0.205 0 0);
206
+ --secondary: oklch(0.269 0 0);
207
+ --secondary-foreground: oklch(0.985 0 0);
208
+ --muted: oklch(0.269 0 0);
209
+ --muted-foreground: oklch(0.708 0 0);
210
+ --accent: oklch(0.269 0 0);
211
+ --accent-foreground: oklch(0.985 0 0);
212
+ --destructive: oklch(0.704 0.191 22.216);
213
+ --border: oklch(1 0 0 / 10%);
214
+ --input: oklch(1 0 0 / 15%);
215
+ --ring: oklch(0.556 0 0);
216
+ --chart-1: oklch(0.488 0.243 264.376);
217
+ --chart-2: oklch(0.696 0.17 162.48);
218
+ --chart-3: oklch(0.769 0.188 70.08);
219
+ --chart-4: oklch(0.627 0.265 303.9);
220
+ --chart-5: oklch(0.645 0.246 16.439);
221
+ --sidebar: oklch(0.205 0 0);
222
+ --sidebar-foreground: oklch(0.985 0 0);
223
+ --sidebar-primary: oklch(0.488 0.243 264.376);
224
+ --sidebar-primary-foreground: oklch(0.985 0 0);
225
+ --sidebar-accent: oklch(0.269 0 0);
226
+ --sidebar-accent-foreground: oklch(0.985 0 0);
227
+ --sidebar-border: oklch(1 0 0 / 10%);
228
+ --sidebar-ring: oklch(0.556 0 0);
229
+ }
230
+
231
+ @layer base {
232
+ * {
233
+ @apply border-border outline-ring/50;
234
+ }
235
+
236
+ body {
237
+ @apply bg-background text-foreground;
238
+ }
239
+ }
240
+
241
+ /* --- TIME TRAVELER EASTER EGG (v2) --- */
242
+ .retro-mode {
243
+ --background: #050505;
244
+ --foreground: #33ff00;
245
+ /* Phosphor Green */
246
+ --muted: #1a2a1a;
247
+ --muted-foreground: #25b800;
248
+ --card: #000000;
249
+ --card-foreground: #33ff00;
250
+ --border: #33ff00;
251
+
252
+ font-family: 'Courier New', Courier, monospace !important;
253
+ text-shadow: 0 0 2px rgba(51, 255, 0, 0.4), 0 0 8px rgba(51, 255, 0, 0.2);
254
+ overflow-x: hidden;
255
+ }
256
+
257
+ .retro-mode body {
258
+ background-color: #050505 !important;
259
+ }
260
+
261
+ /* Force Green Wireframe Look */
262
+ .retro-mode * {
263
+ border-color: rgba(51, 255, 0, 0.3) !important;
264
+ scrollbar-color: #33ff00 #000;
265
+ }
266
+
267
+ .retro-mode img,
268
+ .retro-mode video {
269
+ filter: grayscale(100%) contrast(1.2) brightness(0.8) sepia(100%) hue-rotate(50deg) saturate(3);
270
+ mix-blend-mode: luminosity;
271
+ opacity: 0.8;
272
+ }
273
+
274
+ /* Override text colors globally */
275
+ .retro-mode h1,
276
+ .retro-mode h2,
277
+ .retro-mode h3,
278
+ .retro-mode h4,
279
+ .retro-mode p,
280
+ .retro-mode span,
281
+ .retro-mode div,
282
+ .retro-mode a,
283
+ .retro-mode button {
284
+ color: #33ff00 !important;
285
+ letter-spacing: -0.02em;
286
+ }
287
+
288
+ /* CRT Scanlines & Vignette Overlay */
289
+ .retro-mode::after {
290
+ content: "";
291
+ position: fixed;
292
+ inset: 0;
293
+ background:
294
+ linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%),
295
+ linear-gradient(90deg, rgba(255, 0, 0, 0.06), rgba(0, 255, 0, 0.02), rgba(0, 0, 255, 0.06));
296
+ background-size: 100% 2px, 3px 100%;
297
+ pointer-events: none;
298
+ z-index: 99999;
299
+ }
300
+
301
+ /* Screen Curve / Vignette */
302
+ .retro-mode::before {
303
+ content: "";
304
+ position: fixed;
305
+ inset: 0;
306
+ background: radial-gradient(circle at center, transparent 60%, rgba(0, 0, 0, 0.6) 100%);
307
+ pointer-events: none;
308
+ z-index: 99998;
309
+ }
310
+
311
+ /* Hide Navbar ONLY when Terminal is Active (Transition) */
312
+ html.terminal-active nav {
313
+ display: none !important;
314
+ }
315
+
316
+ html.terminal-active,
317
+ html.terminal-active body {
318
+ overflow: hidden !important;
319
+ height: 100vh !important;
320
+ touch-action: none !important;
321
+ }
@@ -0,0 +1,39 @@
1
+ import type { Metadata, Viewport } from "next";
2
+ import { Outfit } from "next/font/google";
3
+ import { bolivia } from "@/lib/fonts";
4
+ import { NavBar } from "@/components/ui/navbar";
5
+ import "./globals.css";
6
+
7
+ const outfit = Outfit({
8
+ subsets: ["latin"],
9
+ variable: "--font-sans",
10
+ display: "swap",
11
+ });
12
+
13
+ export const viewport: Viewport = {
14
+ themeColor: "#050805",
15
+ width: "device-width",
16
+ initialScale: 1,
17
+ maximumScale: 1,
18
+ userScalable: false,
19
+ };
20
+
21
+ export const metadata: Metadata = {
22
+ title: "Abhishek Singh | Portfolio",
23
+ description: "A premium portfolio template with Bento layout and smooth animations.",
24
+ };
25
+
26
+ export default function RootLayout({
27
+ children,
28
+ }: Readonly<{
29
+ children: React.ReactNode;
30
+ }>) {
31
+ return (
32
+ <html lang="en">
33
+ <body className={`${outfit.variable} ${bolivia.variable} bg-[#050805] text-[#ededed] antialiased`}>
34
+ <NavBar />
35
+ <main>{children}</main>
36
+ </body>
37
+ </html>
38
+ );
39
+ }
@@ -0,0 +1,25 @@
1
+ import { MetadataRoute } from 'next'
2
+
3
+ export default function manifest(): MetadataRoute.Manifest {
4
+ return {
5
+ name: 'Abhishek Singh | Portfolio',
6
+ short_name: 'Abhishek',
7
+ description: 'Product Engineer',
8
+ start_url: '/',
9
+ display: 'standalone',
10
+ background_color: '#050805',
11
+ theme_color: '#050805',
12
+ icons: [
13
+ {
14
+ src: '/icon-192x192.png',
15
+ sizes: '192x192',
16
+ type: 'image/png',
17
+ },
18
+ {
19
+ src: '/icon-512x512.png',
20
+ sizes: '512x512',
21
+ type: 'image/png',
22
+ },
23
+ ],
24
+ }
25
+ }
@@ -0,0 +1,16 @@
1
+ import { Error404 } from "@/components/ui/pixeleted-404-not-found";
2
+
3
+ export default function NotFound() {
4
+ return (
5
+ <Error404
6
+ postcardImage="https://res.cloudinary.com/dap0u41dz/image/upload/v1766866944/Batman_z0yo3k.jpg"
7
+ postcardAlt="New York City Postcard with Statue of Liberty"
8
+ curvedTextTop="The General Intelligence"
9
+ curvedTextBottom="of New York"
10
+ heading="(404) Looks like the page you're looking for got lost somewhere."
11
+ subtext="But hey — in New York, even the unexpected detours lead somewhere."
12
+ backButtonLabel="Back to Home"
13
+ backButtonHref="/"
14
+ />
15
+ );
16
+ }
@@ -0,0 +1,28 @@
1
+ "use client";
2
+
3
+ import { motion } from "framer-motion";
4
+ import { BentoGallery } from "@/components/home/bento-gallery";
5
+ import { FeaturedProjects } from "@/components/home/featured-projects";
6
+ import { TestimonialsMinimal } from "@/components/ui/minimal-testimonial";
7
+ import { ContactSection } from "@/components/home/contact-section";
8
+
9
+ export default function Home() {
10
+ return (
11
+ <main className="min-h-screen bg-[#0a0a0a] text-white selection:bg-white/20 relative overflow-x-hidden">
12
+ <div className="relative z-0">
13
+ <div className="lg:h-screen lg:overflow-hidden flex flex-col pt-24 md:pt-28 lg:pt-0 pb-6 px-4 md:px-8 max-w-[1600px] mx-auto min-h-[calc(100vh-80px)] lg:min-h-0">
14
+ <div className="hidden lg:block h-16 shrink-0" />
15
+ <div className="flex-1 flex flex-col justify-center">
16
+ <BentoGallery />
17
+ </div>
18
+ </div>
19
+
20
+ <div className="mt-32 px-4 md:px-8 max-w-[1600px] mx-auto space-y-32 pb-32">
21
+ <FeaturedProjects />
22
+ <TestimonialsMinimal />
23
+ <ContactSection />
24
+ </div>
25
+ </div>
26
+ </main>
27
+ );
28
+ }
@@ -0,0 +1,12 @@
1
+ import { MetadataRoute } from 'next'
2
+
3
+ export default function robots(): MetadataRoute.Robots {
4
+ return {
5
+ rules: {
6
+ userAgent: '*',
7
+ allow: '/',
8
+ disallow: '/admin/',
9
+ },
10
+ sitemap: 'https://abhishekkpf.vercel.app/sitemap.xml',
11
+ }
12
+ }
@@ -0,0 +1,38 @@
1
+ import { MetadataRoute } from 'next'
2
+
3
+ export default function sitemap(): MetadataRoute.Sitemap {
4
+ const baseUrl = 'https://abhishekkpf.vercel.app'
5
+
6
+ return [
7
+ {
8
+ url: baseUrl,
9
+ lastModified: new Date(),
10
+ changeFrequency: 'weekly',
11
+ priority: 1,
12
+ },
13
+ {
14
+ url: `${baseUrl}/works`,
15
+ lastModified: new Date(),
16
+ changeFrequency: 'monthly',
17
+ priority: 0.9,
18
+ },
19
+ {
20
+ url: `${baseUrl}/about`,
21
+ lastModified: new Date(),
22
+ changeFrequency: 'monthly',
23
+ priority: 0.8,
24
+ },
25
+ {
26
+ url: `${baseUrl}/github`,
27
+ lastModified: new Date(),
28
+ changeFrequency: 'daily',
29
+ priority: 0.8,
30
+ },
31
+ {
32
+ url: `${baseUrl}/contact`,
33
+ lastModified: new Date(),
34
+ changeFrequency: 'yearly',
35
+ priority: 0.7,
36
+ },
37
+ ]
38
+ }
@@ -0,0 +1,5 @@
1
+ import { PageTransition } from "@/components/ui/page-transition";
2
+
3
+ export default function Template({ children }: { children: React.ReactNode }) {
4
+ return <PageTransition>{children}</PageTransition>;
5
+ }
@@ -0,0 +1,50 @@
1
+ import { createClient } from "@/utils/supabase/server";
2
+ import { notFound } from "next/navigation";
3
+ import { ProjectDetailsView } from "@/components/works/project-details-view";
4
+ import { Metadata } from "next";
5
+
6
+ export const revalidate = 0; // Dynamic rendering
7
+
8
+ interface WorksDetailProps {
9
+ params: Promise<{
10
+ slug: string;
11
+ }>;
12
+ }
13
+
14
+ async function getProject(slug: string) {
15
+ const supabase = await createClient();
16
+ const { data } = await supabase
17
+ .from("projects")
18
+ .select("*")
19
+ .eq("slug", slug)
20
+ .single();
21
+
22
+ return data;
23
+ }
24
+
25
+ export async function generateMetadata({ params }: WorksDetailProps): Promise<Metadata> {
26
+ const { slug } = await params;
27
+ const project = await getProject(slug);
28
+ if (!project) return { title: "Project Not Found" };
29
+ return {
30
+ title: `${project.title} - Case Study`,
31
+ description: project.description,
32
+ };
33
+ }
34
+
35
+ export default async function ProjectDetailPage({ params }: WorksDetailProps) {
36
+ const { slug } = await params;
37
+ const project = await getProject(slug);
38
+
39
+ if (!project) {
40
+ notFound();
41
+ }
42
+
43
+ const { data: contributors } = await (await createClient())
44
+ .from("project_contributors")
45
+ .select("*")
46
+ .eq("project_id", project.id)
47
+ .order("created_at", { ascending: true });
48
+
49
+ return <ProjectDetailsView project={project} contributors={contributors || []} />;
50
+ }
@@ -0,0 +1,44 @@
1
+ "use client";
2
+
3
+ import { motion } from "framer-motion";
4
+ import { CurrentlyWorkingCard } from "@/components/works/currently-working-card";
5
+ import { ProjectGrid } from "@/components/works/project-grid";
6
+
7
+ import { Project } from "@/types/project";
8
+
9
+ export function WorksClient({ projects }: { projects: Project[] }) {
10
+ const currentlyWorking = projects.find(p => p.is_currently_working);
11
+ const otherProjects = projects.filter(p => !p.is_currently_working);
12
+
13
+ return (
14
+ <main className="min-h-screen bg-[#050505] pt-32 px-6 md:px-12 pb-20 selection:bg-emerald-500/30 selection:text-emerald-50">
15
+ <motion.div
16
+ initial={{ opacity: 0 }}
17
+ animate={{ opacity: 1 }}
18
+ transition={{ duration: 0.5 }}
19
+ className="w-full max-w-[1280px] mx-auto space-y-24"
20
+ >
21
+ {/* 1. Currently Working Section */}
22
+ {currentlyWorking && (
23
+ <section>
24
+ <CurrentlyWorkingCard project={currentlyWorking} />
25
+ </section>
26
+ )}
27
+
28
+ {/* 2. All Projects Section */}
29
+ {projects.length > 0 && (
30
+ <section>
31
+ <ProjectGrid projects={projects} />
32
+ </section>
33
+ )}
34
+
35
+ {/* Empty State */}
36
+ {!projects.length && (
37
+ <div className="text-center text-white/40 py-20">
38
+ <p>No projects found. Use the Admin panel to add your works.</p>
39
+ </div>
40
+ )}
41
+ </motion.div>
42
+ </main>
43
+ );
44
+ }
@@ -0,0 +1,24 @@
1
+ import { createClient } from "@/utils/supabase/server";
2
+ import { WorksClient } from "./client";
3
+ import { NavBar } from "@/components/ui/navbar";
4
+
5
+ export const metadata = {
6
+ title: "Works | Abhishek Singh",
7
+ description: "A curated list of my projects and current work in progress.",
8
+ };
9
+
10
+ export default async function WorksPage() {
11
+ const supabase = await createClient();
12
+
13
+ const { data: projects } = await supabase
14
+ .from("projects")
15
+ .select("*")
16
+ .order("display_order", { ascending: true });
17
+
18
+ return (
19
+ <>
20
+ <NavBar />
21
+ <WorksClient projects={projects || []} />
22
+ </>
23
+ );
24
+ }