Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions apps/web/app/[username]/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { Loader2 } from "lucide-react";

const PRESET_WIDTHS = ["w-16", "w-10", "w-10", "w-10"];
const LIST_ROW_WIDTHS = ["w-24", "w-20", "w-28", "w-16", "w-24"];
const GRID_COLUMNS = Array.from({ length: 26 });
const GRID_ROWS = Array.from({ length: 7 });

function ShimmerBlock({ className }: { className: string }) {
return (
<div
className={`animate-pulse rounded-md bg-muted/70 ${className}`}
aria-hidden="true"
/>
);
}

export default function PublicUsageLoading() {
return (
<main className="min-h-screen bg-background text-foreground">
<div className="mx-auto max-w-5xl px-6 py-8 sm:py-12">
<div className="flex items-center justify-between gap-4">
<ShimmerBlock className="h-8 w-24" />
<div className="flex gap-1">
{PRESET_WIDTHS.map((width, index) => (
<ShimmerBlock
key={`${width}-${index}`}
className={`h-8 rounded-md ${width}`}
/>
))}
</div>
</div>

<div className="mt-8 flex flex-col gap-8 lg:flex-row lg:gap-10">
<div className="w-full shrink-0 lg:w-56">
<div className="space-y-5">
<div className="flex items-center gap-3">
<div className="flex h-14 w-14 items-center justify-center rounded-full bg-muted/60 text-muted-foreground">
<Loader2 className="h-5 w-5 animate-spin" />
</div>
<div className="min-w-0 flex-1 space-y-2">
<ShimmerBlock className="h-4 w-28" />
<ShimmerBlock className="h-4 w-20" />
</div>
</div>

<div className="space-y-3">
<ShimmerBlock className="h-3 w-32" />
<div className="rounded-lg border border-border/50 bg-muted/10 px-4 py-1">
{Array.from({ length: 3 }).map((_, index) => (
<div
key={index}
className={`flex items-center justify-between gap-4 py-3 ${
index < 2 ? "border-b border-border/50" : ""
}`}
>
<ShimmerBlock className="h-4 w-20" />
<ShimmerBlock className="h-4 w-16" />
</div>
))}
</div>
</div>
</div>
</div>

<div className="min-w-0 flex-1 space-y-8">
<div>
<ShimmerBlock className="mb-3 h-4 w-16" />
<div className="overflow-hidden rounded-xl border border-border/50 bg-muted/10 p-4">
<div
className="grid gap-1.5"
style={{ gridTemplateColumns: "repeat(26, minmax(0, 1fr))" }}
>
{GRID_COLUMNS.flatMap((_, columnIndex) =>
GRID_ROWS.map((_, rowIndex) => (
<div
key={`${columnIndex}-${rowIndex}`}
className="aspect-square animate-pulse rounded-[3px] bg-muted/70"
/>
)),
)}
</div>
</div>
</div>

<div className="grid gap-8 sm:grid-cols-3">
{Array.from({ length: 3 }).map((_, index) => (
<div key={index} className="space-y-2.5">
<ShimmerBlock className="h-4 w-20" />
<div className="space-y-1.5">
{LIST_ROW_WIDTHS.map((width, rowIndex) => (
<div
key={`${index}-${rowIndex}`}
className="flex items-center gap-2.5"
>
<div className="h-2 w-2 rounded-full bg-muted/70" />
<ShimmerBlock className={`h-4 ${width}`} />
<ShimmerBlock className="ml-auto h-3 w-10" />
</div>
))}
</div>
</div>
))}
</div>

<div className="space-y-6">
<ShimmerBlock className="h-4 w-36" />
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
{Array.from({ length: 6 }).map((_, index) => (
<div
key={index}
className="space-y-2 rounded-lg border border-border/50 bg-muted/10 px-4 py-3"
>
<ShimmerBlock className="h-3 w-20" />
<ShimmerBlock className="h-7 w-24" />
<ShimmerBlock className="h-3 w-28" />
</div>
))}
</div>
</div>
</div>
</div>
</div>
</main>
);
}
17 changes: 3 additions & 14 deletions apps/web/app/[username]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { Metadata } from "next";
import Link from "next/link";
import Image from "next/image";
import { headers } from "next/headers";
import { notFound } from "next/navigation";
import { formatTokens } from "@open-harness/shared/lib/tool-state";
import { ContributionChart } from "@/components/contribution-chart";
Expand Down Expand Up @@ -41,16 +40,6 @@ function formatCompactNumber(value: number): string {
return value.toLocaleString();
}

async function getBaseUrl(): Promise<string> {
const headerStore = await headers();
const host =
headerStore.get("x-forwarded-host") ??
headerStore.get("host") ??
"open-agents.dev";
const protocol = headerStore.get("x-forwarded-proto") ?? "https";
return `${protocol}://${host}`;
}

export async function generateMetadata({
params,
searchParams,
Expand All @@ -74,7 +63,6 @@ export async function generateMetadata({
? `?date=${encodeURIComponent(profile.dateSelection.value)}`
: "";
const publicProfilePath = `/u/${profile.user.username}`;
const baseUrl = await getBaseUrl();

return {
title: `${displayName} · Open Agents Wrapped`,
Expand All @@ -83,13 +71,13 @@ export async function generateMetadata({
openGraph: {
title: `${displayName} · Open Agents Wrapped`,
description: `${formatCompactNumber(profile.totals.totalTokens)} tokens · ${profile.dateSelection.label}`,
images: [`${baseUrl}${publicProfilePath}/og${dateQuery}`],
images: [`${publicProfilePath}/og${dateQuery}`],
},
twitter: {
card: "summary_large_image",
title: `${displayName} · Open Agents Wrapped`,
description: `${formatCompactNumber(profile.totals.totalTokens)} tokens · ${profile.dateSelection.label}`,
images: [`${baseUrl}${publicProfilePath}/og${dateQuery}`],
images: [`${publicProfilePath}/og${dateQuery}`],
},
};
}
Expand Down Expand Up @@ -230,6 +218,7 @@ export default async function PublicUsagePage({
<Link
key={preset.label}
href={href}
prefetch={false}
className={`rounded-md px-3 py-1.5 text-xs font-medium transition-colors ${
isActive
? "bg-accent text-accent-foreground"
Expand Down
6 changes: 6 additions & 0 deletions apps/web/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,14 @@ const isPreviewDeployment = process.env.VERCEL_ENV === "preview";
const faviconPath = isPreviewDeployment
? "/favicon-preview.svg"
: "/favicon.ico";
const metadataBase = process.env.VERCEL_PROJECT_PRODUCTION_URL
? new URL(`https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`)
: process.env.VERCEL_URL
? new URL(`https://${process.env.VERCEL_URL}`)
: new URL("https://open-agents.dev");

export const metadata: Metadata = {
metadataBase,
title: {
default: "Open Agents",
template: "%s | Open Agents",
Expand Down
1 change: 1 addition & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading