diff --git a/.claude/settings.json b/.claude/settings.json
index 4e595ab..79f72e0 100644
--- a/.claude/settings.json
+++ b/.claude/settings.json
@@ -8,14 +8,18 @@
"mcp__playwright__browser_close",
"mcp__playwright__browser_console_messages",
"mcp__playwright__browser_evaluate",
+ "mcp__playwright__browser_fill_form",
+ "mcp__playwright__browser_hover",
"mcp__playwright__browser_navigate",
"mcp__playwright__browser_navigate_back",
"mcp__playwright__browser_network_requests",
+ "mcp__playwright__browser_press_key",
"mcp__playwright__browser_resize",
"mcp__playwright__browser_run_code",
"mcp__playwright__browser_snapshot",
"mcp__playwright__browser_tabs",
"mcp__playwright__browser_take_screenshot",
+ "mcp__playwright__browser_type",
"mcp__playwright__browser_wait_for",
"Bash(cat:*)",
"Bash(echo:*)",
@@ -26,9 +30,11 @@
"Bash(tree:*)",
"Bash(wc:*)",
"Bash(xargs:*)",
+ "Bash(git diff:*)",
"Bash(git log:*)",
"Bash(gh pr checks:*)",
"Bash(gh pr list:*)",
+ "Bash(gh pr view:*)",
"Bash(gh run list:*)",
"Bash(gh run view:*)",
"Bash(npm run build)",
@@ -44,6 +50,7 @@
"Bash(npx @biomejs/biome:*)",
"Bash(npx lefthook:*)",
"Bash(npx playwright:*)",
+ "Bash(npx vercel:*)",
"Bash(vercel --help)",
"Bash(vercel env --help)",
"Bash(vercel env ls:*)",
diff --git a/app/(root)/layout.tsx b/app/(root)/layout.tsx
index f8d842c..aefd44e 100644
--- a/app/(root)/layout.tsx
+++ b/app/(root)/layout.tsx
@@ -1,8 +1,8 @@
import { cookies } from "next/headers";
-import { DesktopTopBar } from "@/components/navigation/desktop-top-bar";
+import { DesktopTopBar } from "@/components/navigation/desktop-topbar";
import { LeftSidebar } from "@/components/navigation/left-sidebar";
-import { MobileTopBar } from "@/components/navigation/mobile-top-bar";
-import { RightSidebar } from "@/components/navigation/right-sidebar";
+import { MobileTopBar } from "@/components/navigation/mobile-topbar";
+import { RightSidebar } from "@/components/right-sidebar/right-sidebar";
import { SidebarProvider } from "@/components/ui/sidebar";
const RootLayout = async ({ children }: { children: React.ReactNode }) => {
diff --git a/app/(root)/question/[id]/page.tsx b/app/(root)/question/[id]/page.tsx
new file mode 100644
index 0000000..dd2111e
--- /dev/null
+++ b/app/(root)/question/[id]/page.tsx
@@ -0,0 +1,8 @@
+type QuestionPageProps = {
+ params: Promise<{ id: string }>;
+};
+
+export default async function QuestionPage({ params }: QuestionPageProps) {
+ const { id } = await params;
+ return
Question {id}
;
+}
diff --git a/app/(root)/tags/[slug]/page.tsx b/app/(root)/tags/[slug]/page.tsx
new file mode 100644
index 0000000..9c41f51
--- /dev/null
+++ b/app/(root)/tags/[slug]/page.tsx
@@ -0,0 +1,8 @@
+type TagPageProps = {
+ params: Promise<{ slug: string }>;
+};
+
+export default async function TagPage({ params }: TagPageProps) {
+ const { slug } = await params;
+ return Tag: {slug}
;
+}
diff --git a/app/globals.css b/app/globals.css
index 6180cf6..e7ffeff 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -62,7 +62,6 @@
--color-sidebar-ring: var(--sidebar-ring);
/* Custom */
- --color-mobile-nav: var(--mobile-nav);
--color-overlay: var(--overlay);
}
@@ -119,13 +118,16 @@
var(--primary-gradient-to) 99.54%
);
- /* Custom: Navigation */
- --mobile-nav: oklch(1 0 0); /* #FFFFFF */
+ /* Custom: Overlay */
--overlay: oklch(0 0 0); /* black, both modes */
/* Custom: Assets (theme-aware URLs) */
--logo-full-themed: url("/images/logo-light.svg");
--auth-bg: url("/images/auth-bg-light.webp");
+
+ /* Custom: Tag badges */
+ --tag-bg: oklch(0.9722 0.0034 247.86); /* #F4F6F8 */
+ --tag-text: oklch(0.6504 0.0475 272.34); /* #858EAD */
}
/* Dark mode overrides — these values take precedence over :root when .dark is active */
@@ -178,13 +180,16 @@
var(--primary-gradient-to) 99.54%
); /* same as root */
- /* Custom: Navigation */
- --mobile-nav: oklch(0.1288 0.0406 264.7); /* #07080b */
+ /* Custom: Overlay */
--overlay: oklch(0 0 0); /* same as root */
/* Custom: Assets (theme-aware URLs) */
--logo-full-themed: url("/images/logo-dark.svg");
--auth-bg: url("/images/auth-bg-dark.webp");
+
+ /* Custom: Tag badges */
+ --tag-bg: oklch(0.2102 0.0185 270.39); /* #151821 */
+ --tag-text: oklch(0.6547 0.0897 269.9); /* #7B8EC8 */
}
@layer base {
diff --git a/components/navigation/desktop-top-bar.tsx b/components/navigation/desktop-topbar.tsx
similarity index 100%
rename from components/navigation/desktop-top-bar.tsx
rename to components/navigation/desktop-topbar.tsx
diff --git a/components/navigation/mobile-nav.tsx b/components/navigation/mobile-nav.tsx
index a527616..5a075b0 100644
--- a/components/navigation/mobile-nav.tsx
+++ b/components/navigation/mobile-nav.tsx
@@ -10,7 +10,7 @@ import {
import { Menu, X } from "lucide-react";
import Link from "next/link";
import { useState } from "react";
-import { MobileNavLink } from "@/components/navigation/mobile-nav-link";
+import { MobileNavLink } from "@/components/navigation/mobile-navlink";
import { NAV_LINKS } from "@/components/navigation/nav-links.constants";
import { ThemedFullLogo } from "@/components/navigation/themed-full-logo";
import { Button } from "@/components/ui/button";
@@ -58,7 +58,7 @@ export function MobileNav() {
diff --git a/components/navigation/mobile-nav-link.tsx b/components/navigation/mobile-navlink.tsx
similarity index 100%
rename from components/navigation/mobile-nav-link.tsx
rename to components/navigation/mobile-navlink.tsx
diff --git a/components/navigation/mobile-top-bar.tsx b/components/navigation/mobile-topbar.tsx
similarity index 100%
rename from components/navigation/mobile-top-bar.tsx
rename to components/navigation/mobile-topbar.tsx
diff --git a/components/right-sidebar/question-link.tsx b/components/right-sidebar/question-link.tsx
new file mode 100644
index 0000000..36d4490
--- /dev/null
+++ b/components/right-sidebar/question-link.tsx
@@ -0,0 +1,21 @@
+import { ChevronRight } from "lucide-react";
+import Link from "next/link";
+
+type QuestionLinkProps = {
+ id: string;
+ title: string;
+};
+
+export function QuestionLink({ id, title }: QuestionLinkProps) {
+ return (
+
+
+ {title}
+
+
+
+ );
+}
diff --git a/components/navigation/right-sidebar.tsx b/components/right-sidebar/right-sidebar.tsx
similarity index 57%
rename from components/navigation/right-sidebar.tsx
rename to components/right-sidebar/right-sidebar.tsx
index 50f8aed..3acd881 100644
--- a/components/navigation/right-sidebar.tsx
+++ b/components/right-sidebar/right-sidebar.tsx
@@ -1,15 +1,23 @@
+import { QuestionLink } from "@/components/right-sidebar/question-link";
+import { TagLink } from "@/components/right-sidebar/tag-link";
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
} from "@/components/ui/sidebar";
-import { Skeleton } from "@/components/ui/skeleton";
+import { getTopQuestions } from "@/lib/data/questions";
+import { getPopularTags } from "@/lib/data/tags";
/** Asymmetric padding: more on left, less on right (scrollbar side), reduced bottom */
const GROUP_PADDING = "pt-6 pb-2 pl-6 pr-3";
-export function RightSidebar() {
+export async function RightSidebar() {
+ const [topQuestions, popularTags] = await Promise.all([
+ getTopQuestions(5),
+ getPopularTags(5),
+ ]);
+
return (