Skip to content

Commit ae53aaa

Browse files
refactor: simplify navbar layout and fix dev caching
- Swap Header for SiteNavbar in root layout - Center social icons in navbar with rounded states and CTA on the right - Support icon/external link items in NavbarWithMenu - Drop redundant hero heading and tidy ask-ai button sizing - Skip immutable cache headers in development to keep HMR working Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent d7350a5 commit ae53aaa

7 files changed

Lines changed: 47 additions & 86 deletions

File tree

app/blog/[slug]/page.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ export default async function BlogPost({
122122
<PostBanner slug={slug} topic={post.frontmatter.topic} />
123123

124124
{/* Meta info - subtle and refined */}
125-
<div className="flex items-center gap-3 mt-10 mb-6 text-xs text-muted-foreground/60 uppercase tracking-[0.15em]">
125+
<div className="flex items-center justify-center gap-3 mt-10 mb-6 text-xs text-muted-foreground/60 uppercase tracking-[0.15em]">
126126
<span>{post.frontmatter.topic}</span>
127127
<span className="text-muted-foreground/30">·</span>
128128
<span>
@@ -135,20 +135,20 @@ export default async function BlogPost({
135135
</div>
136136

137137
{/* Title - clean, readable */}
138-
<h1 className="text-3xl md:text-4xl font-semibold tracking-tight text-foreground mb-6 leading-[1.3] italic">
138+
<h1 className="text-3xl md:text-4xl font-semibold tracking-tight text-foreground mb-6 leading-[1.3] italic text-center">
139139
{post.frontmatter.title}
140140
</h1>
141141

142142
{/* Description - subtle, refined */}
143-
<p className="text-base text-foreground/60 leading-relaxed max-w-xl">
143+
<p className="text-base text-foreground/60 leading-relaxed max-w-xl mx-auto text-center">
144144
{post.frontmatter.description}
145145
</p>
146146

147147
{/* Ask AI Buttons */}
148148
<AskAIButtons slug={slug} title={post.frontmatter.title} />
149149

150150
{/* Elegant separator */}
151-
<div className="mt-12 w-16 h-px bg-muted-foreground/20" />
151+
<div className="mt-12 w-16 h-px bg-muted-foreground/20 mx-auto" />
152152
</header>
153153
</div>
154154
)}

app/layout.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type React from "react";
22
import type { Metadata } from "next";
33
import { Geist, Geist_Mono, Poppins } from "next/font/google";
44
import { Analytics } from "@vercel/analytics/next";
5-
import { Header } from "@/components/header";
5+
import { SiteNavbar } from "@/components/site-navbar";
66
import "./globals.css";
77

88
const _geist = Geist({ subsets: ["latin"] });
@@ -59,7 +59,7 @@ export default function RootLayout({
5959
return (
6060
<html lang="en" className={`dark ${poppins.variable}`}>
6161
<body className="font-sans antialiased min-h-screen">
62-
<Header />
62+
<SiteNavbar />
6363
{children}
6464
<Analytics />
6565
</body>

app/page.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,7 @@ export default function Home() {
2121
<main className="max-w-4xl mx-auto px-6 py-16">
2222
{/* Hero */}
2323
<section className="pt-6 pb-24 md:pt-12 md:pb-36">
24-
<h1 className="text-4xl md:text-6xl font-bold tracking-tight leading-[1.05] text-foreground text-balance">
25-
Reactjs maxxing
26-
</h1>
27-
28-
<p className="mt-7 max-w-2xl text-base md:text-xl text-muted-foreground leading-relaxed md:leading-relaxed">
24+
<p className="max-w-2xl text-base md:text-xl text-muted-foreground leading-relaxed md:leading-relaxed">
2925
Where I dig into how React actually works under the hood: Fiber,
3026
reconciliation, and server components. Find me on <HeroSocials />{" "}
3127
where I share deep dives every week.

components/blog/ask-ai-buttons.tsx

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
"use client";
22

3-
import { HugeiconsIcon } from "@hugeicons/react";
4-
import { AiChat02Icon } from "@hugeicons/core-free-icons";
5-
63
interface AskAIButtonsProps {
74
slug: string;
85
title: string;
@@ -20,12 +17,12 @@ Help me understand the concepts explained in this article. Be ready to explain c
2017
const claudeUrl = `https://claude.ai/new?q=${encodedPrompt}`;
2118

2219
return (
23-
<div className="flex items-center gap-3 mt-8 pt-6 border-t border-muted-foreground/15">
20+
<div className="flex items-center justify-center gap-3 mt-8 pt-6 border-t border-muted-foreground/15">
2421
<a
2522
href={chatGPTUrl}
2623
target="_blank"
2724
rel="noopener noreferrer"
28-
className="inline-flex items-center gap-2 px-3 py-1.5 text-sm bg-muted/50 hover:bg-muted text-muted-foreground hover:text-foreground rounded-md transition-colors"
25+
className="inline-flex min-w-28 items-center justify-center gap-2 px-3 py-1.5 text-sm bg-muted/50 hover:bg-muted text-muted-foreground hover:text-foreground rounded-md transition-colors"
2926
>
3027
<svg
3128
width="16"
@@ -42,29 +39,29 @@ Help me understand the concepts explained in this article. Be ready to explain c
4239
href={claudeUrl}
4340
target="_blank"
4441
rel="noopener noreferrer"
45-
className="inline-flex items-center gap-2 px-3 py-1.5 text-sm bg-muted/50 hover:bg-muted text-muted-foreground hover:text-foreground rounded-md transition-colors"
42+
className="inline-flex min-w-28 items-center justify-center gap-2 px-3 py-1.5 text-sm bg-muted/50 hover:bg-muted text-muted-foreground hover:text-foreground rounded-md transition-colors"
4643
>
4744
<img
4845
src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/b0/Claude_AI_symbol.svg/960px-Claude_AI_symbol.svg.png"
4946
alt="Claude"
5047
width={16}
5148
height={16}
52-
className="opacity-70"
49+
className="h-4 w-4 shrink-0 object-contain opacity-70"
5350
/>
5451
Claude
5552
</a>
5653
<a
5754
href="https://heygaia.io/c"
5855
target="_blank"
5956
rel="noopener noreferrer"
60-
className="inline-flex items-center gap-2 px-3 py-1.5 text-sm bg-muted/50 hover:bg-muted text-muted-foreground hover:text-foreground rounded-md transition-colors"
57+
className="inline-flex min-w-28 items-center justify-center gap-2 px-3 py-1.5 text-sm bg-muted/50 hover:bg-muted text-muted-foreground hover:text-foreground rounded-md transition-colors"
6158
>
6259
<img
6360
src="https://raw.githubusercontent.com/theexperiencecompany/gaia/10ddc7be52907bb2810114234418787aad257bd8/apps/web/public/brand/gaia_logo.svg"
6461
alt="Gaia"
6562
width={16}
6663
height={16}
67-
className="opacity-70"
64+
className="h-4 w-4 shrink-0 object-contain opacity-70"
6865
/>
6966
Gaia
7067
</a>

components/navbar-withmenu.tsx

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,13 @@ export interface NavbarMenuProps {
4242
export interface NavbarWithMenuProps {
4343
sections: NavbarMenuSection[];
4444
navItems?: Array<
45-
| { type: "link"; label: string; href: string }
45+
| {
46+
type: "link";
47+
label: string;
48+
href: string;
49+
icon?: React.ReactNode;
50+
external?: boolean;
51+
}
4652
| { type: "dropdown"; label: string; menu: string }
4753
>;
4854
logo?: React.ReactNode;
@@ -151,7 +157,7 @@ export function NavbarMenu({ activeMenu, sections }: NavbarMenuProps) {
151157
return (
152158
<div
153159
className={cn(
154-
"absolute top-full left-0 z-40 w-full origin-top overflow-hidden border border-y-0 border-border bg-background/95 backdrop-blur-2xl outline-none",
160+
"absolute top-full left-0 z-40 w-full origin-top overflow-hidden rounded-b-2xl border border-t-0 border-border bg-background/95 backdrop-blur-2xl outline-none",
155161
)}
156162
>
157163
<div className="p-6">
@@ -223,7 +229,7 @@ export function NavbarWithMenu({
223229
duration: shouldReduceMotion ? 0.35 : 0.8,
224230
ease: [0.2, 0.9, 0.24, 1],
225231
}}
226-
className="sticky top-0 z-50 w-full"
232+
className="sticky top-3 z-50 w-full"
227233
>
228234
{/* biome-ignore lint/a11y/noStaticElementInteractions: Hover container for menu, not interactive content */}
229235
<motion.div
@@ -232,7 +238,7 @@ export function NavbarWithMenu({
232238
onMouseLeave={handleNavbarMouseLeave}
233239
animate={{
234240
maxWidth: scrolled ? "56rem" : "100vw",
235-
marginTop: scrolled ? 12 : 0,
241+
marginTop: scrolled ? 12 : 8,
236242
paddingLeft: scrolled ? 16 : 0,
237243
paddingRight: scrolled ? 16 : 0,
238244
}}
@@ -246,12 +252,12 @@ export function NavbarWithMenu({
246252
<motion.div
247253
initial={false}
248254
className={cn(
249-
"navbar_content flex h-14 w-full items-center justify-between border transition-colors duration-300",
255+
"navbar_content relative flex h-14 w-full items-center justify-between border transition-[border-radius,background-color,border-color] duration-300",
250256
activeDropdown
251-
? "border-border border-b-transparent bg-background backdrop-blur-md"
257+
? "rounded-t-lg border-border border-b-transparent bg-background backdrop-blur-md"
252258
: scrolled
253-
? "border-border bg-card/40 backdrop-blur-md"
254-
: "border-transparent bg-transparent",
259+
? "rounded-lg border-border bg-card/40 backdrop-blur-md"
260+
: "rounded-none border-transparent bg-transparent",
255261
)}
256262
animate={{
257263
paddingLeft: scrolled ? 12 : 32,
@@ -276,20 +282,23 @@ export function NavbarWithMenu({
276282
)}
277283
</div>
278284

279-
<div className="hidden items-center gap-2 px-1 py-1 md:flex">
280-
<div className="flex items-center gap-1">
285+
{/* Center nav — social icons */}
286+
<div className="absolute left-1/2 hidden -translate-x-1/2 items-center gap-1 md:flex">
281287
{items.map((item) =>
282288
item.type === "link" ? (
283289
<Link
284290
key={item.href}
285291
href={item.href}
286-
className="relative flex h-9 cursor-pointer items-center px-4 py-2 text-sm text-foreground transition-colors hover:bg-foreground/5"
292+
target={item.external ? "_blank" : undefined}
293+
rel={item.external ? "noopener noreferrer" : undefined}
294+
aria-label={item.label}
295+
className="relative flex h-9 cursor-pointer items-center gap-2 rounded-lg px-3 py-2 text-sm text-foreground transition-colors hover:bg-foreground/5"
287296
onMouseEnter={() => {
288297
setHoveredItem(item.label.toLowerCase());
289298
setActiveDropdown(null);
290299
}}
291300
>
292-
<span className="relative z-10">{item.label}</span>
301+
{item.icon ?? <span className="relative z-10">{item.label}</span>}
293302
</Link>
294303
) : (
295304
<button
@@ -303,7 +312,8 @@ export function NavbarWithMenu({
303312
)}
304313
<div className="relative z-10 flex items-center gap-2">
305314
<span>
306-
{item.label.charAt(0).toUpperCase() + item.label.slice(1)}
315+
{item.label.charAt(0).toUpperCase() +
316+
item.label.slice(1)}
307317
</span>
308318
<HugeiconsIcon
309319
icon={ArrowDown01Icon}
@@ -317,10 +327,11 @@ export function NavbarWithMenu({
317327
</button>
318328
),
319329
)}
320-
</div>
321-
{cta}
322330
</div>
323331

332+
{/* Right — CTA (desktop) */}
333+
<div className="hidden md:block">{cta}</div>
334+
324335
<Sheet>
325336
<SheetTrigger asChild className="md:hidden">
326337
<Button variant="ghost" size="icon" aria-label="Open menu">

components/site-navbar.tsx

Lines changed: 2 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2,51 +2,7 @@
22

33
import Image from "next/image";
44
import Link from "next/link";
5-
import { HugeiconsIcon } from "@hugeicons/react";
6-
import {
7-
NewTwitterIcon,
8-
LinkedinIcon,
9-
GithubIcon,
10-
} from "@hugeicons/core-free-icons";
11-
import {
12-
NavbarWithMenu,
13-
type NavbarMenuSection,
14-
} from "@/components/navbar-withmenu";
15-
16-
const sections: NavbarMenuSection[] = [
17-
{
18-
id: "socials",
19-
gridLayout: "grid w-full grid-cols-1 gap-2",
20-
links: [
21-
{
22-
label: "X (Twitter)",
23-
href: "https://x.com/sankalpa_02",
24-
external: true,
25-
description: "Thoughts, threads & updates",
26-
icon: <HugeiconsIcon icon={NewTwitterIcon} size={18} />,
27-
},
28-
{
29-
label: "LinkedIn",
30-
href: "https://linkedin.com/in/sankalpa02",
31-
external: true,
32-
description: "Professional profile",
33-
icon: <HugeiconsIcon icon={LinkedinIcon} size={18} />,
34-
},
35-
{
36-
label: "GitHub",
37-
href: "https://github.com/sankalpaacharya",
38-
external: true,
39-
description: "Open source & projects",
40-
icon: <HugeiconsIcon icon={GithubIcon} size={18} />,
41-
},
42-
],
43-
},
44-
];
45-
46-
const navItems = [
47-
{ type: "link" as const, label: "Home", href: "/" },
48-
{ type: "dropdown" as const, label: "Socials", menu: "socials" },
49-
];
5+
import { NavbarWithMenu } from "@/components/navbar-withmenu";
506

517
const logo = (
528
<Link href="/" className="flex items-center gap-2.5">
@@ -72,11 +28,6 @@ const cta = (
7228

7329
export function SiteNavbar() {
7430
return (
75-
<NavbarWithMenu
76-
sections={sections}
77-
navItems={navItems}
78-
logo={logo}
79-
cta={cta}
80-
/>
31+
<NavbarWithMenu sections={[]} navItems={[]} logo={logo} cta={cta} />
8132
);
8233
}

next.config.mjs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ const nextConfig = {
2828
],
2929
},
3030
async headers() {
31+
// Never send long-lived/immutable cache headers in development —
32+
// the browser would hold onto stale dev chunks across HMR rebuilds,
33+
// which breaks hot reload and forces manual cache clears.
34+
if (process.env.NODE_ENV !== "production") {
35+
return [];
36+
}
3137
return [
3238
{
3339
// Cache all static assets in public folder for 1 year

0 commit comments

Comments
 (0)