Skip to content

Commit 967c5b6

Browse files
authored
Merge pull request #27 from devakone/develop
Release: develop → main
2 parents 77d6a5b + 033bd1e commit 967c5b6

26 files changed

Lines changed: 601 additions & 213 deletions
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
".": "0.1.0-alpha.9",
3-
"apps/web": "0.1.0-alpha.9",
2+
".": "0.1.0-alpha.10",
3+
"apps/web": "0.1.0-alpha.10",
44
"apps/worker": "0.1.0-alpha.3"
55
}

CHANGELOG-DEVELOP.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# Changelog
22

3+
## [0.1.0-alpha.10](https://github.com/devakone/vibe-coding-profiler/compare/vibe-coding-profiler-v0.1.0-alpha.9...vibe-coding-profiler-v0.1.0-alpha.10) (2026-01-31)
4+
5+
6+
### Features
7+
8+
* rewrite vibe coding language to be AI-native ([e45e55e](https://github.com/devakone/vibe-coding-profiler/commit/e45e55e4473869c3df80482245c836d19fa21a46))
9+
* simplify top nav with user menu dropdown and app footer ([029ad3a](https://github.com/devakone/vibe-coding-profiler/commit/029ad3af8b0d164d4f906c3eec3447691ba10e0b))
10+
11+
12+
### Bug Fixes
13+
14+
* filter out already-connected repos from Add a Repo picker ([8d08166](https://github.com/devakone/vibe-coding-profiler/commit/8d0816695033c5919ad16b734777d125a6abe718))
15+
* resolve story export crash and B&W PNG output in share routes ([7193754](https://github.com/devakone/vibe-coding-profiler/commit/71937546a9ee003ba1973ea3e315b0d855583a93))
16+
317
## [0.1.0-alpha.9](https://github.com/devakone/vibe-coding-profiler/compare/vibe-coding-profiler-v0.1.0-alpha.8...vibe-coding-profiler-v0.1.0-alpha.9) (2026-01-30)
418

519

apps/web/CHANGELOG-DEVELOP.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# Changelog
22

3+
## [0.1.0-alpha.10](https://github.com/devakone/vibe-coding-profiler/compare/web-v0.1.0-alpha.9...web-v0.1.0-alpha.10) (2026-01-31)
4+
5+
6+
### Features
7+
8+
* rewrite vibe coding language to be AI-native ([e45e55e](https://github.com/devakone/vibe-coding-profiler/commit/e45e55e4473869c3df80482245c836d19fa21a46))
9+
* simplify top nav with user menu dropdown and app footer ([029ad3a](https://github.com/devakone/vibe-coding-profiler/commit/029ad3af8b0d164d4f906c3eec3447691ba10e0b))
10+
11+
12+
### Bug Fixes
13+
14+
* filter out already-connected repos from Add a Repo picker ([8d08166](https://github.com/devakone/vibe-coding-profiler/commit/8d0816695033c5919ad16b734777d125a6abe718))
15+
* resolve story export crash and B&W PNG output in share routes ([7193754](https://github.com/devakone/vibe-coding-profiler/commit/71937546a9ee003ba1973ea3e315b0d855583a93))
16+
317
## [0.1.0-alpha.9](https://github.com/devakone/vibe-coding-profiler/compare/web-v0.1.0-alpha.8...web-v0.1.0-alpha.9) (2026-01-30)
418

519

apps/web/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"test:watch": "vitest"
1313
},
1414
"dependencies": {
15+
"@radix-ui/react-dropdown-menu": "^2.1.16",
1516
"@radix-ui/react-popover": "^1.1.15",
1617
"@radix-ui/react-toast": "^1.2.15",
1718
"@radix-ui/react-tooltip": "^1.2.8",

apps/web/src/app/AppFooter.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import Link from "next/link";
2+
3+
export default function AppFooter() {
4+
return (
5+
<footer className="mt-auto border-t border-black/5">
6+
<div className="mx-auto flex max-w-6xl flex-col gap-3 px-6 py-6 text-sm text-zinc-500 sm:flex-row sm:items-center sm:justify-between sm:px-10 lg:px-20">
7+
<p className="text-zinc-700">Vibe Coding Profiler</p>
8+
<nav className="flex flex-wrap items-center gap-4">
9+
<Link
10+
href="/methodology"
11+
className="transition hover:text-zinc-900"
12+
>
13+
Methodology
14+
</Link>
15+
<Link href="/security" className="transition hover:text-zinc-900">
16+
Security
17+
</Link>
18+
</nav>
19+
</div>
20+
</footer>
21+
);
22+
}

apps/web/src/app/AppHeader.tsx

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,17 @@
22

33
import Link from "next/link";
44
import { usePathname } from "next/navigation";
5+
import { Settings, LogOut, User } from "lucide-react";
56
import { wrappedTheme } from "@/lib/theme";
67
import { NotificationDropdown } from "@/components/notifications";
8+
import {
9+
DropdownMenu,
10+
DropdownMenuContent,
11+
DropdownMenuItem,
12+
DropdownMenuLabel,
13+
DropdownMenuSeparator,
14+
DropdownMenuTrigger,
15+
} from "@/components/ui/dropdown-menu";
716

817
function isActiveLink(pathname: string, href: string): boolean {
918
if (href === "/") return pathname === "/";
@@ -15,6 +24,7 @@ function isActiveLink(pathname: string, href: string): boolean {
1524
export default function AppHeader(props: {
1625
isAuthed: boolean;
1726
isAdmin?: boolean;
27+
userEmail?: string;
1828
signOut: () => Promise<void>;
1929
}) {
2030
const pathname = usePathname();
@@ -25,9 +35,6 @@ export default function AppHeader(props: {
2535
? [
2636
{ href: "/", label: "My VCP" },
2737
{ href: "/vibes", label: "Repo VCPs" },
28-
{ href: "/settings/repos", label: "Settings" },
29-
{ href: "/methodology", label: "Methodology" },
30-
{ href: "/security", label: "Security" },
3138
]
3239
: [
3340
{ href: "/", label: "Home" },
@@ -80,13 +87,54 @@ export default function AppHeader(props: {
8087
{props.isAuthed ? (
8188
<>
8289
<NotificationDropdown />
83-
<form action={props.signOut}>
84-
<button
85-
type="submit"
86-
className="rounded-full border border-zinc-300/80 bg-white/70 px-4 py-1.5 text-sm font-semibold text-zinc-950 shadow-sm backdrop-blur transition hover:border-zinc-400 hover:bg-white"
87-
>
88-
Sign out
89-
</button>
90+
<DropdownMenu>
91+
<DropdownMenuTrigger asChild>
92+
<button
93+
type="button"
94+
className="flex items-center gap-2 rounded-full border border-zinc-300/80 bg-white/70 px-3 py-1.5 text-sm font-semibold text-zinc-950 shadow-sm backdrop-blur transition hover:border-zinc-400 hover:bg-white"
95+
>
96+
<User className="h-4 w-4 text-zinc-600" />
97+
<span className="hidden max-w-[150px] truncate sm:inline">
98+
{props.userEmail ?? "Account"}
99+
</span>
100+
</button>
101+
</DropdownMenuTrigger>
102+
<DropdownMenuContent align="end" sideOffset={8}>
103+
<DropdownMenuLabel>
104+
{props.userEmail ?? "Signed in"}
105+
</DropdownMenuLabel>
106+
<DropdownMenuSeparator />
107+
<DropdownMenuItem asChild>
108+
<Link
109+
href="/settings/repos"
110+
className="flex items-center gap-2"
111+
>
112+
<Settings className="h-4 w-4" />
113+
Settings
114+
</Link>
115+
</DropdownMenuItem>
116+
<DropdownMenuSeparator />
117+
<DropdownMenuItem
118+
onSelect={(e) => {
119+
e.preventDefault();
120+
const form = document.getElementById(
121+
"sign-out-form"
122+
) as HTMLFormElement | null;
123+
form?.requestSubmit();
124+
}}
125+
className="flex items-center gap-2 text-red-600 hover:bg-red-50 focus:bg-red-50"
126+
>
127+
<LogOut className="h-4 w-4" />
128+
Sign out
129+
</DropdownMenuItem>
130+
</DropdownMenuContent>
131+
</DropdownMenu>
132+
<form
133+
id="sign-out-form"
134+
action={props.signOut}
135+
className="hidden"
136+
>
137+
<button type="submit" />
90138
</form>
91139
</>
92140
) : (

apps/web/src/app/api/share/[format]/[userId]/route.tsx

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import { ImageResponse } from "@vercel/og";
22
import { createClient } from "@supabase/supabase-js";
33
import { getPersonaAura } from "@/lib/persona-auras";
44

5-
export const runtime = 'edge';
5+
// Node.js runtime: edge can't reliably fetch self-origin images for aura backgrounds
6+
export const runtime = "nodejs";
67

78
export async function GET(
89
request: Request,
@@ -84,6 +85,23 @@ export async function GET(
8485
const personaConfidence = profile.persona_confidence || "High";
8586
const aura = getPersonaAura(profile.persona_id);
8687

88+
// Persona-based gradient colors (matches STORY_THEMES in story route)
89+
const PERSONA_COLORS: Record<string, { primary: string; accent: string }> = {
90+
prompt_sprinter: { primary: "#7c3aed", accent: "#6366f1" },
91+
rapid_risk_taker: { primary: "#8b5cf6", accent: "#6366f1" },
92+
fix_loop_hacker: { primary: "#7c3aed", accent: "#818cf8" },
93+
guardrailed_viber: { primary: "#6366f1", accent: "#7c3aed" },
94+
spec_first_director: { primary: "#4f46e5", accent: "#7c3aed" },
95+
balanced_builder: { primary: "#6366f1", accent: "#8b5cf6" },
96+
reflective_balancer: { primary: "#6366f1", accent: "#8b5cf6" },
97+
methodical_architect: { primary: "#4f46e5", accent: "#7c3aed" },
98+
vertical_slice_shipper: { primary: "#6366f1", accent: "#818cf8" },
99+
toolsmith_viber: { primary: "#4f46e5", accent: "#6366f1" },
100+
infra_weaver: { primary: "#4338ca", accent: "#6366f1" },
101+
};
102+
const DEFAULT_COLORS = { primary: "#7c3aed", accent: "#6366f1" };
103+
const colors = PERSONA_COLORS[profile.persona_id] ?? DEFAULT_COLORS;
104+
87105
const baseUrl = process.env.NEXT_PUBLIC_APP_URL || "http://localhost:8108";
88106
const displayUrl = new URL(baseUrl).host;
89107

@@ -105,29 +123,37 @@ export async function GET(
105123
strongest: "N/A",
106124
style: "Balanced",
107125
rhythm: "Mixed",
108-
peak: "Varied"
126+
peak: "All Hours"
109127
};
110128

111129
if (axes) {
112130
// 1. Strongest
113131
let maxScore = -1;
114-
let maxName = "";
132+
let maxKey = "";
115133
const AXIS_NAMES: Record<string, string> = {
116134
automation_heaviness: "Automation",
117135
guardrail_strength: "Guardrails",
118-
iteration_loop_intensity: "Loops",
136+
iteration_loop_intensity: "Iteration",
119137
planning_signal: "Planning",
120-
surface_area_per_change: "Scope",
138+
surface_area_per_change: "Surface Area",
121139
shipping_rhythm: "Rhythm",
122140
};
141+
const AXIS_HIGH_LABELS: Record<string, string> = {
142+
automation_heaviness: "AI-Heavy",
143+
guardrail_strength: "Rigorous",
144+
iteration_loop_intensity: "Rapid",
145+
planning_signal: "Structured",
146+
surface_area_per_change: "Wide",
147+
shipping_rhythm: "Bursty",
148+
};
123149
for (const [key, val] of Object.entries(axes)) {
124150
const axis = val as { score: number };
125151
if (axis.score > maxScore && AXIS_NAMES[key]) {
126152
maxScore = axis.score;
127-
maxName = AXIS_NAMES[key];
153+
maxKey = key;
128154
}
129155
}
130-
const strongest = maxName ? `${maxName} ${maxScore}` : "N/A";
156+
const strongest = maxKey ? `${AXIS_HIGH_LABELS[maxKey]} ${AXIS_NAMES[maxKey]}` : "N/A";
131157

132158
// 2. Style
133159
let style = "Mixed"; // Default
@@ -182,20 +208,32 @@ export async function GET(
182208
display: "flex",
183209
flexDirection: "column",
184210
position: "relative",
185-
backgroundColor: "#111",
186-
backgroundImage: `url(${bgUrl})`,
187-
backgroundSize: "cover",
188-
backgroundPosition: "center",
211+
background: `linear-gradient(180deg, ${colors.primary}, ${colors.accent})`,
189212
fontFamily: '"Space Grotesk", sans-serif',
190213
fontSize: 24 * scale,
214+
overflow: "hidden",
191215
}}
192216
>
193-
{/* Overlay */}
217+
{/* Aura background overlay */}
218+
{/* eslint-disable-next-line @next/next/no-img-element, jsx-a11y/alt-text */}
219+
<img
220+
src={bgUrl}
221+
style={{
222+
position: "absolute",
223+
top: 0,
224+
left: 0,
225+
width: "100%",
226+
height: "100%",
227+
objectFit: "cover",
228+
opacity: 0.25,
229+
}}
230+
/>
231+
{/* Readability overlay */}
194232
<div
195233
style={{
196234
position: "absolute",
197235
inset: 0,
198-
backgroundColor: "rgba(0,0,0,0.4)",
236+
backgroundColor: "rgba(0,0,0,0.15)",
199237
}}
200238
/>
201239

apps/web/src/app/api/share/story/[userId]/route.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import type { ShareCardColors, ShareCardMetric } from "@/components/share/types"
99
import type { InsightCard, VibeAxes } from "@vibe-coding-profiler/core";
1010
import { NextRequest, NextResponse } from "next/server";
1111

12-
export const runtime = "edge";
12+
// Node.js runtime required: qrcode package uses Node APIs incompatible with edge
13+
export const runtime = "nodejs";
1314

1415
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1516
type SupabaseClientInstance = any;

apps/web/src/app/favicon.ico

-20 KB
Binary file not shown.

apps/web/src/app/icon.svg

Lines changed: 10 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)