← back to amit-biswas-1992__bentoskills

Function bodies 84 total

All specs Real LLM only Function bodies
POST function · typescript · L10-L31 (22 LOC)
app/api/cron/sync-registry/route.ts
export async function POST(req: Request) {
  const auth = req.headers.get("authorization");
  if (auth !== `Bearer ${process.env.CRON_SECRET}`) {
    return NextResponse.json({ error: "unauthorized" }, { status: 401 });
  }

  const repoName = process.env.GITHUB_REGISTRY_REPO;
  if (!repoName) {
    return NextResponse.json({ error: "GITHUB_REGISTRY_REPO not set" }, { status: 500 });
  }

  const github = createGithubClient(repoName, process.env.GITHUB_TOKEN);
  const repo = new SkillRepository();
  const result = await syncRegistry({
    github,
    repo,
    repoUrlFor: (slug) => `https://github.com/${repoName}/tree/main/skills/${slug}`,
    logger,
  });

  return NextResponse.json(result);
}
GET function · typescript · L33-L35 (3 LOC)
app/api/cron/sync-registry/route.ts
export async function GET(req: Request) {
  return POST(req);
}
AppLayout function · typescript · L4-L8 (5 LOC)
app/(app)/layout.tsx
export default async function AppLayout({ children }: { children: React.ReactNode }) {
  const session = await auth();
  if (!session?.user) redirect("/api/auth/signin?callbackUrl=/me");
  return <div className="mx-auto max-w-6xl px-6 py-8">{children}</div>;
}
MePage function · typescript · L6-L48 (43 LOC)
app/(app)/me/page.tsx
export default async function MePage() {
  const session = await auth();
  const userId = (session!.user as { id: string }).id;
  const [favs, installs] = await Promise.all([
    new FavoriteRepository().listForUser(userId),
    new InstallLogRepository().listForUser(userId, 20),
  ]);

  return (
    <div className="space-y-12">
      <section>
        <h2 className="mb-4 text-xl font-semibold">Favorites</h2>
        {favs.length === 0 ? (
          <p className="text-[--muted-foreground]">No favorites yet. Browse and heart a skill.</p>
        ) : (
          <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
            {favs.map((s) => (
              <SkillCard key={s.id} skill={s} />
            ))}
          </div>
        )}
      </section>

      <section>
        <h2 className="mb-4 text-xl font-semibold">Recent installs</h2>
        {installs.length === 0 ? (
          <p className="text-[--muted-foreground]">No installs yet.</p>
        ) : (
          
RootLayout function · typescript · L14-L23 (10 LOC)
app/layout.tsx
export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" className={`${inter.variable} ${mono.variable}`} suppressHydrationWarning>
      <body>
        <ThemeScript />
        {children}
      </body>
    </html>
  );
}
fetchContributors function · typescript · L38-L53 (16 LOC)
app/(marketing)/contributors/page.tsx
async function fetchContributors(repo: string): Promise<GhContributor[]> {
  const headers: Record<string, string> = {
    Accept: "application/vnd.github+json",
    "User-Agent": "bentoskills-app",
  };
  if (process.env.GITHUB_TOKEN) {
    headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`;
  }
  const res = await fetch(
    `https://api.github.com/repos/${repo}/contributors?per_page=100&anon=0`,
    { headers, next: { revalidate: 21600 } }
  );
  if (!res.ok) return [];
  const data = (await res.json()) as GhContributor[];
  return Array.isArray(data) ? data.filter((c) => c.type === "User") : [];
}
ContributorsPage function · typescript · L62-L164 (103 LOC)
app/(marketing)/contributors/page.tsx
export default async function ContributorsPage() {
  const results = await Promise.all(REPOS.map(fetchContributors));

  const byLogin = new Map<string, Merged>();
  for (const [i, list] of results.entries()) {
    // REPOS is a fixed-length const tuple, so i is always in range.
    const repo = REPOS[i] as string;
    for (const c of list) {
      const existing = byLogin.get(c.login);
      if (existing) {
        existing.total += c.contributions;
        existing.repos.push(repo);
      } else {
        byLogin.set(c.login, {
          login: c.login,
          avatarUrl: c.avatar_url,
          htmlUrl: c.html_url,
          total: c.contributions,
          repos: [repo],
        });
      }
    }
  }

  const ranked = [...byLogin.values()].sort((a, b) => b.total - a.total);

  return (
    <div className="space-y-10">
      <header className="space-y-3">
        <h1 className="text-3xl font-semibold tracking-tight">Contributors</h1>
        <p className="max-w-2xl text-[--muted-
Open data scored by Repobility · https://repobility.com
MarketingLayout function · typescript · L5-L44 (40 LOC)
app/(marketing)/layout.tsx
export default function MarketingLayout({ children }: { children: React.ReactNode }) {
  return (
    <div className="mx-auto max-w-6xl px-6 py-8">
      <header className="flex items-center justify-between pb-10">
        <Link href="/" className="text-lg font-semibold">
          bentoskills<span className="text-[--color-accent]">.sh</span>
        </Link>
        <nav className="flex items-center gap-4 text-sm">
          <Link href="/skills" className="hover:text-[--color-accent]">
            Browse
          </Link>
          <Link href="/contributors" className="hover:text-[--color-accent]">
            Contributors
          </Link>
          <Link href="/publish" className="hover:text-[--color-accent]">
            Publish
          </Link>
          <StarButton />
          <ThemeToggle />
          <Link
            href="/api/auth/signin"
            className="inline-flex h-8 items-center rounded-md border border-[--border] px-3 text-sm hover:bg-[--muted]"
          >
    
HomePage function · typescript · L9-L62 (54 LOC)
app/(marketing)/page.tsx
export default async function HomePage() {
  const repo = new SkillRepository();
  const [featured, trending, newest] = await Promise.all([
    repo.listFeatured(1),
    repo.listTrending(4),
    repo.listNewest(8),
  ]);

  return (
    <div className="space-y-12">
      <BentoGrid>
        <BentoTile size="xl">
          <h1 className="text-4xl font-semibold tracking-tight">
            UI/UX skills for Claude Code.
          </h1>
          <p className="mt-3 max-w-xl text-[--muted-foreground]">
            Agent skills that make your interfaces better — design critique, accessibility review,
            UX copy, handoff specs.
          </p>
          <div className="mt-6 max-w-md">
            <CommandBlock command="npx bentoskills install design-critique" />
          </div>
        </BentoTile>
        {featured[0] && (
          <BentoTile size="lg">
            <span className="text-xs uppercase tracking-wide text-[--muted-foreground]">Featured</span>
            <div classNam
PublishPage function · typescript · L1-L40 (40 LOC)
app/(marketing)/publish/page.tsx
export default function PublishPage() {
  return (
    <article className="prose prose-zinc max-w-none dark:prose-invert">
      <h1>Publish a skill</h1>
      <p>bentoskills.sh is backed by a public GitHub registry. To publish:</p>
      <ol>
        <li>
          Fork{" "}
          <a href="https://github.com/amit-biswas-1992/bentoskills-registry">
            <code>amit-biswas-1992/bentoskills-registry</code>
          </a>
          .
        </li>
        <li>
          Add a folder under <code>skills/&lt;slug&gt;/</code> containing <code>skill.yaml</code> and{" "}
          <code>README.md</code>.
        </li>
        <li>
          Add an entry to <code>registry.json</code>.
        </li>
        <li>Open a pull request.</li>
      </ol>
      <h2>
        <code>skill.yaml</code> schema
      </h2>
      <pre>
        <code>{`slug: design-critique           # required, [a-z0-9-]+
name: Design Critique           # required
tagline: Get structured ...     # required, ≤140 chars
BrowsePage function · typescript · L22-L113 (92 LOC)
app/(marketing)/skills/page.tsx
export default async function BrowsePage({
  searchParams,
}: {
  searchParams: Promise<SearchParams>;
}) {
  const sp = await searchParams;
  const page = Math.max(1, Number(sp.page ?? "1"));
  const pageSize = 24;
  const repo = new SkillRepository();
  const { items, total } = await repo.search({
    q: sp.q,
    category: sp.category,
    tag: sp.tag,
    sort: sp.sort,
    page,
    pageSize,
  });

  const totalPages = Math.max(1, Math.ceil(total / pageSize));

  return (
    <div className="grid grid-cols-1 gap-8 md:grid-cols-[220px_1fr]">
      <aside className="space-y-6">
        <div>
          <h3 className="mb-2 text-xs uppercase tracking-wide text-[--muted-foreground]">Category</h3>
          <ul className="space-y-1 text-sm">
            <li>
              <Link href="/skills" className={!sp.category ? "font-semibold" : ""}>
                All
              </Link>
            </li>
            {CATEGORIES.map((c) => (
              <li key={c}>
                <Link hr
SkillPage function · typescript · L13-L86 (74 LOC)
app/(marketing)/skills/[slug]/page.tsx
export default async function SkillPage({
  params,
}: {
  params: Promise<{ slug: string }>;
}) {
  const { slug } = await params;
  const skill = await new SkillRepository().findBySlug(slug);
  if (!skill) notFound();
  const session = await auth();
  let isFavorited = false;
  if (session?.user) {
    isFavorited = await new FavoriteRepository().isFavorited(
      (session.user as { id: string }).id,
      skill.id,
    );
  }
  const html = await renderMarkdown(skill.description);

  return (
    <div className="grid grid-cols-1 gap-12 lg:grid-cols-[1fr_320px]">
      <article>
        <h1 className="text-3xl font-semibold tracking-tight">{skill.name}</h1>
        <p className="mt-2 text-[--muted-foreground]">{skill.tagline}</p>
        <div className="mt-8">
          <MarkdownView html={html} />
        </div>
      </article>

      <aside className="sticky top-6 h-fit space-y-4 rounded-2xl border border-[--border] p-5">
        <div>
          <Badge>{skill.category}</Badge>
  
install function · typescript · L24-L92 (69 LOC)
cli/src/commands/install.ts
export async function install(slug: string | undefined, flags: Flags) {
  if (!slug) {
    log.error("Missing skill slug.");
    log.info(`Usage: ${c("bold", "bentoskills install <slug>")}`);
    process.exit(1);
  }

  const info = getRegistryInfo();
  log.step(`Resolving ${c("cyan", slug)} in ${c("gray", info.repo)}…`);
  const registry = await fetchRegistry();
  const entry = registry.find((e) => e.slug === slug);
  if (!entry) {
    log.error(`Skill "${slug}" not found in the registry.`);
    const suggestions = registry
      .map((e) => e.slug)
      .filter((s) => s.startsWith(slug.slice(0, 3)))
      .slice(0, 5);
    if (suggestions.length) {
      log.info(`  Did you mean: ${suggestions.map((s) => c("cyan", s)).join(", ")}?`);
    } else {
      log.info(`  Run ${c("bold", "bentoskills list")} to see all skills.`);
    }
    process.exit(1);
  }

  const targetRoot = flags.dir ?? getSkillsDir();
  const targetDir = path.join(targetRoot, slug);

  try {
    const stat = await 
list function · typescript · L8-L23 (16 LOC)
cli/src/commands/list.ts
export async function list() {
  const info = getRegistryInfo();
  const registry = await fetchRegistry();
  if (registry.length === 0) {
    log.warn("Registry is empty.");
    return;
  }
  log.info(
    `${c("bold", `${registry.length} skill${registry.length === 1 ? "" : "s"}`)} in ${c("gray", info.repo)}:\n`
  );
  for (const entry of registry) {
    console.log(`  ${c("cyan", entry.slug)}  ${c("gray", entry.path)}`);
  }
  console.log("");
  log.dim(`Install one with: bentoskills install <slug>`);
}
search function · typescript · L9-L28 (20 LOC)
cli/src/commands/search.ts
export async function search(query: string | undefined) {
  if (!query) {
    log.error("Missing search query.");
    log.info(`Usage: ${c("bold", "bentoskills search <query>")}`);
    process.exit(1);
  }
  const q = query.toLowerCase();
  const registry = await fetchRegistry();
  const matches = registry.filter(
    (e) => e.slug.toLowerCase().includes(q) || e.path.toLowerCase().includes(q)
  );
  if (matches.length === 0) {
    log.warn(`No skills matched "${query}".`);
    return;
  }
  log.info(`${c("bold", `${matches.length} match${matches.length === 1 ? "" : "es"}`)}:\n`);
  for (const entry of matches) {
    console.log(`  ${c("cyan", entry.slug)}  ${c("gray", entry.path)}`);
  }
}
Source: Repobility analyzer · https://repobility.com
main function · typescript · L51-L94 (44 LOC)
cli/src/index.ts
async function main() {
  const argv = process.argv.slice(2);

  // Fast paths for help / version regardless of position.
  if (argv.length === 0 || argv.includes("-h") || argv.includes("--help") || argv[0] === "help") {
    console.log(HELP);
    return;
  }
  if (argv.includes("-v") || argv.includes("--version") || argv[0] === "version") {
    console.log(VERSION);
    return;
  }

  const [command, ...rest] = argv;

  // Parse flags from the remaining args so commands see clean positionals.
  const { values, positionals } = parseArgs({
    args: rest,
    options: {
      force: { type: "boolean", default: false },
      dir: { type: "string" },
    },
    allowPositionals: true,
    strict: true,
  });

  switch (command) {
    case "install":
      await install(positionals[0], { force: values.force as boolean, dir: values.dir as string | undefined });
      break;
    case "list":
    case "ls":
      await list();
      break;
    case "search":
    case "find":
      await sear
buildHeaders function · typescript · L32-L41 (10 LOC)
cli/src/registry.ts
function buildHeaders(accept = "application/vnd.github+json"): Record<string, string> {
  const headers: Record<string, string> = {
    Accept: accept,
    "User-Agent": "bentoskills-cli",
  };
  if (process.env.GITHUB_TOKEN) {
    headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`;
  }
  return headers;
}
fetchRegistry function · typescript · L43-L57 (15 LOC)
cli/src/registry.ts
export async function fetchRegistry(): Promise<RegistryEntry[]> {
  const url = `${RAW_BASE}/registry.json`;
  const res = await fetch(url, { headers: buildHeaders("application/json") });
  if (!res.ok) {
    throw new Error(
      `Failed to fetch registry (${res.status} ${res.statusText}) from ${url}`
    );
  }
  const data = (await res.json()) as { skills?: RegistryEntry[] } | RegistryEntry[];
  const list = Array.isArray(data) ? data : (data.skills ?? []);
  if (!Array.isArray(list)) {
    throw new Error("registry.json is malformed: expected an array of skills");
  }
  return list;
}
listSkillFiles function · typescript · L59-L73 (15 LOC)
cli/src/registry.ts
export async function listSkillFiles(skillPath: string): Promise<RegistryFile[]> {
  const url = `${API_BASE}/contents/${encodeURIComponent(skillPath).replace(/%2F/g, "/")}?ref=${REGISTRY_BRANCH}`;
  const res = await fetch(url, { headers: buildHeaders() });
  if (!res.ok) {
    if (res.status === 404) throw new Error(`Skill path not found: ${skillPath}`);
    if (res.status === 403) {
      throw new Error(
        "GitHub API rate limit hit. Set GITHUB_TOKEN to raise the limit."
      );
    }
    throw new Error(`Failed to list skill files (${res.status} ${res.statusText})`);
  }
  const data = (await res.json()) as RegistryFile[];
  return data;
}
downloadFile function · typescript · L75-L82 (8 LOC)
cli/src/registry.ts
export async function downloadFile(downloadUrl: string): Promise<Buffer> {
  const res = await fetch(downloadUrl, { headers: buildHeaders("application/octet-stream") });
  if (!res.ok) {
    throw new Error(`Failed to download file (${res.status} ${res.statusText})`);
  }
  const buf = await res.arrayBuffer();
  return Buffer.from(buf);
}
getRegistryInfo function · typescript · L84-L86 (3 LOC)
cli/src/registry.ts
export function getRegistryInfo() {
  return { repo: REGISTRY_REPO, branch: REGISTRY_BRANCH };
}
c function · typescript · L17-L25 (9 LOC)
cli/src/utils.ts
export function c(color: Color | Color[], text: string): string {
  if (!supportsColor) return text;
  const colors = Array.isArray(color) ? color : [color];
  try {
    return styleText(colors, text);
  } catch {
    return text;
  }
}
getSkillsDir function · typescript · L37-L40 (4 LOC)
cli/src/utils.ts
export function getSkillsDir(): string {
  if (process.env.CLAUDE_SKILLS_DIR) return process.env.CLAUDE_SKILLS_DIR;
  return path.join(os.homedir(), ".claude", "skills");
}
Repobility (the analyzer behind this table) · https://repobility.com
BentoGrid function · typescript · L4-L21 (18 LOC)
components/bento-grid.tsx
export function BentoGrid({
  children,
  className,
}: {
  children: ReactNode;
  className?: string;
}) {
  return (
    <div
      className={cn(
        "grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-4 md:grid-rows-[repeat(3,12rem)]",
        className,
      )}
    >
      {children}
    </div>
  );
}
BentoTile function · typescript · L23-L49 (27 LOC)
components/bento-grid.tsx
export function BentoTile({
  children,
  size = "sm",
  className,
}: {
  children: ReactNode;
  size?: "sm" | "md" | "lg" | "xl";
  className?: string;
}) {
  const spans = {
    sm: "md:col-span-1 md:row-span-1",
    md: "md:col-span-2 md:row-span-1",
    lg: "md:col-span-2 md:row-span-2",
    xl: "md:col-span-3 md:row-span-2",
  }[size];
  return (
    <div
      className={cn(
        "overflow-hidden rounded-2xl border border-[--border] bg-[--background] p-6",
        spans,
        className,
      )}
    >
      {children}
    </div>
  );
}
CommandBlock function · typescript · L5-L29 (25 LOC)
components/command-block.tsx
export function CommandBlock({ command, slug }: { command: string; slug?: string }) {
  const [copied, setCopied] = useState(false);

  async function copy() {
    await navigator.clipboard.writeText(command);
    setCopied(true);
    setTimeout(() => setCopied(false), 1500);
    if (slug) {
      fetch("/api/installs", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({ slug }),
      }).catch(() => {});
    }
  }

  return (
    <div className="flex items-center justify-between gap-2 rounded-lg border border-[--border] bg-[--muted] px-3 py-2 font-mono text-sm">
      <code className="truncate">{command}</code>
      <Button variant="ghost" size="sm" onClick={copy}>
        {copied ? "copied" : "copy"}
      </Button>
    </div>
  );
}
copy function · typescript · L8-L19 (12 LOC)
components/command-block.tsx
  async function copy() {
    await navigator.clipboard.writeText(command);
    setCopied(true);
    setTimeout(() => setCopied(false), 1500);
    if (slug) {
      fetch("/api/installs", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({ slug }),
      }).catch(() => {});
    }
  }
FavoriteButton function · typescript · L5-L51 (47 LOC)
components/favorite-button.tsx
export function FavoriteButton({
  slug,
  initialFavorited,
  initialCount,
}: {
  slug: string;
  initialFavorited: boolean;
  initialCount: number;
}) {
  const [favorited, setFavorited] = useState(initialFavorited);
  const [count, setCount] = useState(initialCount);
  const [pending, startTransition] = useTransition();

  function toggle() {
    const nextFavorited = !favorited;
    setFavorited(nextFavorited);
    setCount((c) => c + (nextFavorited ? 1 : -1));
    startTransition(async () => {
      try {
        const res = await fetch(
          `/api/favorites${nextFavorited ? "" : "/" + slug}`,
          {
            method: nextFavorited ? "POST" : "DELETE",
            headers: { "content-type": "application/json" },
            body: nextFavorited ? JSON.stringify({ slug }) : undefined,
          },
        );
        if (!res.ok) throw new Error();
        const data = await res.json();
        setCount(data.count);
      } catch {
        setFavorited(!nextFavorited);
 
toggle function · typescript · L18-L40 (23 LOC)
components/favorite-button.tsx
  function toggle() {
    const nextFavorited = !favorited;
    setFavorited(nextFavorited);
    setCount((c) => c + (nextFavorited ? 1 : -1));
    startTransition(async () => {
      try {
        const res = await fetch(
          `/api/favorites${nextFavorited ? "" : "/" + slug}`,
          {
            method: nextFavorited ? "POST" : "DELETE",
            headers: { "content-type": "application/json" },
            body: nextFavorited ? JSON.stringify({ slug }) : undefined,
          },
        );
        if (!res.ok) throw new Error();
        const data = await res.json();
        setCount(data.count);
      } catch {
        setFavorited(!nextFavorited);
        setCount((c) => c + (nextFavorited ? -1 : 1));
      }
    });
  }
MarkdownView function · typescript · L1-L8 (8 LOC)
components/markdown-view.tsx
export function MarkdownView({ html }: { html: string }) {
  return (
    <div
      className="prose prose-zinc max-w-none dark:prose-invert"
      dangerouslySetInnerHTML={{ __html: html }}
    />
  );
}
SkillCard function · typescript · L21-L53 (33 LOC)
components/skill-card.tsx
export function SkillCard({
  skill,
  variant = "compact",
}: {
  skill: Skill;
  variant?: "compact" | "feature";
}) {
  return (
    <article className="group relative rounded-2xl border border-[--border] p-5 transition hover:border-[--color-accent] focus-within:border-[--color-accent]">
      <div className="flex items-start justify-between gap-3">
        <h3 className={variant === "feature" ? "text-2xl font-semibold" : "text-base font-semibold"}>
          <Link
            href={`/skills/${skill.slug}`}
            className="after:absolute after:inset-0 after:rounded-2xl focus:outline-none"
          >
            {skill.name}
          </Link>
        </h3>
        <Badge>{skill.category}</Badge>
      </div>
      <p className="mt-2 line-clamp-2 text-sm text-[--muted-foreground]">{skill.tagline}</p>
      <div className="relative mt-4 flex flex-wrap gap-1.5">
        {skill.tags.slice(0, 4).map((t) => (
          <TagPill key={t} tag={t} />
        ))}
      </div>
      <div
Repobility's GitHub App fixes findings like these · https://github.com/apps/repobility-bot
getStarCount function · typescript · L12-L33 (22 LOC)
components/star-button.tsx
async function getStarCount(): Promise<number | null> {
  try {
    const headers: Record<string, string> = {
      Accept: "application/vnd.github+json",
      "User-Agent": "bentoskills-app",
    };
    // Use token if available to lift rate limits. No secrets reach the client;
    // this is a server component.
    if (process.env.GITHUB_TOKEN) {
      headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`;
    }
    const res = await fetch(API, {
      headers,
      next: { revalidate: 1800 },
    });
    if (!res.ok) return null;
    const data = (await res.json()) as { stargazers_count?: number };
    return typeof data.stargazers_count === "number" ? data.stargazers_count : null;
  } catch {
    return null;
  }
}
formatCount function · typescript · L35-L38 (4 LOC)
components/star-button.tsx
function formatCount(n: number): string {
  if (n >= 1000) return `${(n / 1000).toFixed(1).replace(/\.0$/, "")}k`;
  return String(n);
}
StarButton function · typescript · L40-L59 (20 LOC)
components/star-button.tsx
export async function StarButton() {
  const count = await getStarCount();
  return (
    <a
      href={`https://github.com/${REPO}`}
      target="_blank"
      rel="noopener noreferrer"
      className="inline-flex h-8 items-center gap-1.5 rounded-md border border-[--border] px-2.5 text-sm text-[--foreground] transition-colors hover:border-[--color-accent] hover:bg-[--muted] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[--color-accent]"
      aria-label={`Star bentoskills on GitHub${count !== null ? ` (${count} stars)` : ""}`}
    >
      <StarIcon />
      <span className="font-medium">Star</span>
      {count !== null && (
        <span className="text-[--muted-foreground] tabular-nums">
          {formatCount(count)}
        </span>
      )}
    </a>
  );
}
StarIcon function · typescript · L61-L73 (13 LOC)
components/star-button.tsx
function StarIcon() {
  return (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 24 24"
      fill="currentColor"
      className="h-4 w-4 text-[--color-accent]"
      aria-hidden="true"
    >
      <path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" />
    </svg>
  );
}
TagPill function · typescript · L3-L12 (10 LOC)
components/tag-pill.tsx
export function TagPill({ tag }: { tag: string }) {
  return (
    <Link
      href={`/skills?tag=${encodeURIComponent(tag)}`}
      className="relative inline-flex h-6 items-center rounded-full border border-[--border] px-2 text-xs text-[--muted-foreground] hover:bg-[--muted]"
    >
      #{tag}
    </Link>
  );
}
ThemeScript function · typescript · L22-L28 (7 LOC)
components/theme-script.tsx
export function ThemeScript() {
  return (
    <Script id="bentoskills-theme" strategy="beforeInteractive">
      {script}
    </Script>
  );
}
getInitialTheme function · typescript · L7-L10 (4 LOC)
components/theme-toggle.tsx
function getInitialTheme(): Theme {
  if (typeof window === "undefined") return "light";
  return document.documentElement.classList.contains("dark") ? "dark" : "light";
}
ThemeToggle function · typescript · L12-L50 (39 LOC)
components/theme-toggle.tsx
export function ThemeToggle() {
  const [theme, setTheme] = useState<Theme>("light");
  const [mounted, setMounted] = useState(false);

  useEffect(() => {
    setTheme(getInitialTheme());
    setMounted(true);
  }, []);

  function toggle() {
    const next: Theme = theme === "dark" ? "light" : "dark";
    setTheme(next);
    document.documentElement.classList.toggle("dark", next === "dark");
    try {
      localStorage.setItem("theme", next);
    } catch {}
  }

  const label = theme === "dark" ? "Switch to light mode" : "Switch to dark mode";

  return (
    <button
      type="button"
      onClick={toggle}
      aria-label={label}
      title={label}
      className="inline-flex h-8 w-8 items-center justify-center rounded-md border border-[--border] text-[--foreground] hover:bg-[--muted] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[--color-accent]"
    >
      {/* Render neutral placeholder pre-mount to match SSR */}
      {!mounted ? (
        <span aria-h
Open data scored by Repobility · https://repobility.com
toggle function · typescript · L21-L28 (8 LOC)
components/theme-toggle.tsx
  function toggle() {
    const next: Theme = theme === "dark" ? "light" : "dark";
    setTheme(next);
    document.documentElement.classList.toggle("dark", next === "dark");
    try {
      localStorage.setItem("theme", next);
    } catch {}
  }
SunIcon function · typescript · L52-L69 (18 LOC)
components/theme-toggle.tsx
function SunIcon() {
  return (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      strokeWidth={2}
      strokeLinecap="round"
      strokeLinejoin="round"
      className="h-4 w-4"
      aria-hidden="true"
    >
      <circle cx="12" cy="12" r="4" />
      <path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41" />
    </svg>
  );
}
MoonIcon function · typescript · L71-L87 (17 LOC)
components/theme-toggle.tsx
function MoonIcon() {
  return (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      strokeWidth={2}
      strokeLinecap="round"
      strokeLinejoin="round"
      className="h-4 w-4"
      aria-hidden="true"
    >
      <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />
    </svg>
  );
}
Badge function · typescript · L4-L14 (11 LOC)
components/ui/badge.tsx
export function Badge({ className, ...p }: React.HTMLAttributes<HTMLSpanElement>) {
  return (
    <span
      className={cn(
        "inline-flex items-center rounded-full border border-[--border] px-2.5 py-0.5 text-xs",
        className,
      )}
      {...p}
    />
  );
}
Skeleton function · typescript · L4-L6 (3 LOC)
components/ui/skeleton.tsx
export function Skeleton({ className, ...p }: React.HTMLAttributes<HTMLDivElement>) {
  return <div className={cn("animate-pulse rounded-md bg-[--muted]", className)} {...p} />;
}
HttpError class · typescript · L1-L10 (10 LOC)
lib/api/errors.ts
export class HttpError extends Error {
  constructor(
    public status: number,
    public code: string,
    message: string,
    public fields?: Record<string, string[]>,
  ) {
    super(message);
  }
}
constructor method · typescript · L2-L9 (8 LOC)
lib/api/errors.ts
  constructor(
    public status: number,
    public code: string,
    message: string,
    public fields?: Record<string, string[]>,
  ) {
    super(message);
  }
withErrorHandler function · typescript · L8-L37 (30 LOC)
lib/api/handler.ts
export function withErrorHandler<Ctx>(fn: Handler<Ctx>): Handler<Ctx> {
  return async (req, ctx) => {
    try {
      return await fn(req, ctx);
    } catch (e) {
      if (e instanceof HttpError) {
        return NextResponse.json(
          { error: { code: e.code, message: e.message, fields: e.fields } },
          { status: e.status },
        );
      }
      if (e instanceof ZodError) {
        const fields: Record<string, string[]> = {};
        for (const iss of e.issues) {
          const key = iss.path.join(".") || "_";
          (fields[key] ||= []).push(iss.message);
        }
        return NextResponse.json(
          { error: { code: "validation_error", message: "invalid input", fields } },
          { status: 400 },
        );
      }
      logger.error({ error: (e as Error).message }, "unhandled api error");
      return NextResponse.json(
        { error: { code: "internal_error", message: "something went wrong" } },
        { status: 500 },
      );
    }
  };
}
Source: Repobility analyzer · https://repobility.com
main function · typescript · L6-L29 (24 LOC)
lib/db/cli.ts
async function main() {
  const cmd = process.argv[2];
  await ds.initialize();

  switch (cmd) {
    case "migrate":
      await ds.runMigrations();
      console.log("migrations applied");
      break;
    case "revert":
      await ds.undoLastMigration();
      console.log("last migration reverted");
      break;
    case "generate": {
      const name = process.argv[3];
      if (!name) throw new Error("usage: pnpm db:generate <Name>");
      console.log(`run: pnpm typeorm migration:generate lib/db/migrations/${name} -d lib/db/data-source.ts`);
      break;
    }
    default:
      throw new Error(`unknown command: ${cmd}`);
  }
  await ds.destroy();
}
buildDataSource function · typescript · L40-L54 (15 LOC)
lib/db/data-source.ts
function buildDataSource(): DataSource {
  const url = process.env.DATABASE_URL;
  if (!url) throw new Error("DATABASE_URL is not set");

  return new DataSource({
    type: "postgres",
    url,
    ssl: process.env.DATABASE_SSL === "true" ? { rejectUnauthorized: false } : false,
    entities: [User, Account, Session, Skill, Favorite, InstallLog],
    synchronize: false,
    logging: process.env.NODE_ENV === "development" ? ["error", "warn"] : ["error"],
    // Cap per-DataSource connections so a single bundle can't starve the pooler.
    poolSize: 5,
  });
}
destroyQuietly function · typescript · L57-L63 (7 LOC)
lib/db/data-source.ts
function destroyQuietly(ds: DataSource): void {
  if (!ds.isInitialized) return;
  ds.destroy().catch(() => {
    // TypeORM/pg can throw "Called end on pool more than once" if cleanup
    // raced with another path. That's fine during teardown.
  });
}
page 1 / 2next ›