feat(phase-4): WS2 + WS3 — Developer Portal (Next.js 14) and CLI tool (sentryagent)
WS2: Developer Portal (portal/) - Standalone Next.js 14 + Tailwind CSS app — independent deployment - Home page: hero, feature grid, CTA to /get-started - /pricing: free tier limits table (10 agents, 1k calls/day) + paid tier CTA - /sdks: all 4 SDKs (Node.js, Python, Go, Java) with install + code examples - /api-explorer: Swagger UI from NEXT_PUBLIC_API_URL/openapi.json, persistAuthorization - /get-started: 4-step wizard (setup → register agent → credentials → SDK snippet) - Shared Nav component with active-link highlighting - Build: 8/8 static pages, zero TypeScript errors WS3: CLI Tool (cli/ — npm package: sentryagent) - configure, register-agent, list-agents, issue-token, rotate-credentials, tail-audit-log - Auto OAuth2 token fetch + 30s-buffer cache via client_credentials flow - chalk-formatted table output, confirmation prompts, bounded audit log dedup - bash + zsh shell completion scripts - README with installation, all commands, and completion setup - Build: tsc clean, node dist/index.js --help verified Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
66
portal/components/Nav.tsx
Normal file
66
portal/components/Nav.tsx
Normal file
@@ -0,0 +1,66 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
|
||||
interface NavLink {
|
||||
href: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
const links: NavLink[] = [
|
||||
{ href: '/', label: 'Home' },
|
||||
{ href: '/api-explorer', label: 'API Explorer' },
|
||||
{ href: '/get-started', label: 'Get Started' },
|
||||
{ href: '/sdks', label: 'SDKs' },
|
||||
{ href: '/pricing', label: 'Pricing' },
|
||||
];
|
||||
|
||||
export function Nav(): React.ReactElement {
|
||||
const pathname = usePathname();
|
||||
|
||||
return (
|
||||
<header className="sticky top-0 z-50 border-b border-slate-200 bg-white/90 backdrop-blur">
|
||||
<nav className="mx-auto flex max-w-7xl items-center justify-between px-6 py-4">
|
||||
<Link href="/" className="flex items-center gap-2">
|
||||
<span className="text-xl font-bold text-brand-600">
|
||||
SentryAgent
|
||||
</span>
|
||||
<span className="rounded bg-brand-100 px-1.5 py-0.5 text-xs font-semibold text-brand-700">
|
||||
AgentIdP
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
<ul className="flex items-center gap-1">
|
||||
{links.map(({ href, label }) => {
|
||||
const isActive =
|
||||
href === '/' ? pathname === '/' : pathname.startsWith(href);
|
||||
return (
|
||||
<li key={href}>
|
||||
<Link
|
||||
href={href}
|
||||
className={[
|
||||
'rounded-md px-3 py-2 text-sm font-medium transition-colors',
|
||||
isActive
|
||||
? 'bg-brand-100 text-brand-700'
|
||||
: 'text-slate-600 hover:bg-slate-100 hover:text-slate-900',
|
||||
].join(' ')}
|
||||
>
|
||||
{label}
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
|
||||
<Link
|
||||
href="/get-started"
|
||||
className="rounded-lg bg-brand-600 px-4 py-2 text-sm font-semibold text-white shadow-sm transition-colors hover:bg-brand-700"
|
||||
>
|
||||
Get Started Free
|
||||
</Link>
|
||||
</nav>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user