mirror of
https://github.com/better-auth/better-hub
synced 2026-08-09 12:26:04 +00:00
feat: page metadata (#24)
page metadata <img width="590" height="110" alt="CleanShot 2026-02-22 at 14 40 28@2x" src="https://github.com/user-attachments/assets/f311ac3c-3a79-4e96-980d-5b71289d17c7" />
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import type { Metadata } from "next";
|
||||
import { notFound } from "next/navigation";
|
||||
import {
|
||||
getOrg,
|
||||
@@ -10,6 +11,27 @@ import {
|
||||
import { OrgDetailContent } from "@/components/orgs/org-detail-content";
|
||||
import { UserProfileContent } from "@/components/users/user-profile-content";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ owner: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { owner } = await params;
|
||||
const orgData = await getOrg(owner).catch(() => null);
|
||||
if (orgData) {
|
||||
return { title: orgData.name || orgData.login };
|
||||
}
|
||||
const userData = await getUser(owner).catch(() => null);
|
||||
if (userData) {
|
||||
return {
|
||||
title: userData.name
|
||||
? `${userData.name} (${userData.login})`
|
||||
: userData.login,
|
||||
};
|
||||
}
|
||||
return { title: owner };
|
||||
}
|
||||
|
||||
export default async function OwnerPage({ params }: { params: Promise<{ owner: string }> }) {
|
||||
const { owner } = await params;
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { Metadata } from "next";
|
||||
import { getServerSession } from "@/lib/auth";
|
||||
import { redirect } from "next/navigation";
|
||||
import {
|
||||
@@ -10,6 +11,10 @@ import {
|
||||
import { DashboardContent } from "@/components/dashboard/dashboard-content";
|
||||
import { all } from "better-all";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Dashboard",
|
||||
};
|
||||
|
||||
export default async function DashboardPage() {
|
||||
const session = await getServerSession();
|
||||
if (!session) return redirect("/");
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import type { Metadata } from "next";
|
||||
import { ExtensionPageContent } from "@/components/extension/extension-page-content";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Browser Extension",
|
||||
};
|
||||
|
||||
export default function ExtensionPage() {
|
||||
return <ExtensionPageContent />;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import type { Metadata } from "next";
|
||||
import { getAuthenticatedUser, searchIssues } from "@/lib/github";
|
||||
import { IssuesContent } from "@/components/issues/issues-content";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Issues",
|
||||
};
|
||||
|
||||
export default async function IssuesPage() {
|
||||
const user = await getAuthenticatedUser();
|
||||
if (!user) return null;
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import type { Metadata } from "next";
|
||||
import { getNotifications } from "@/lib/github";
|
||||
import { NotificationsContent } from "@/components/notifications/notifications-content";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Notifications",
|
||||
};
|
||||
|
||||
export default async function NotificationsPage() {
|
||||
const notifications = await getNotifications(50);
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import type { Metadata } from "next";
|
||||
import { getUserOrgs } from "@/lib/github";
|
||||
import { OrgsContent, type OrgListItem } from "@/components/orgs/orgs-content";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Organizations",
|
||||
};
|
||||
|
||||
export default async function OrgsPage() {
|
||||
const orgsResponse = await getUserOrgs(50);
|
||||
|
||||
|
||||
@@ -1,7 +1,25 @@
|
||||
import type { Metadata } from "next";
|
||||
import { notFound } from "next/navigation";
|
||||
import { getWorkflowRun, getWorkflowRunJobs } from "@/lib/github";
|
||||
import { RunDetail } from "@/components/actions/run-detail";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ owner: string; repo: string; runId: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { owner, repo, runId } = await params;
|
||||
const runIdNum = parseInt(runId, 10);
|
||||
if (isNaN(runIdNum)) {
|
||||
return { title: `Run · ${owner}/${repo}` };
|
||||
}
|
||||
const run = await getWorkflowRun(owner, repo, runIdNum);
|
||||
if (!run) {
|
||||
return { title: `Run #${runId} · ${owner}/${repo}` };
|
||||
}
|
||||
return { title: `${run.name || run.display_title} #${run.run_number} · ${owner}/${repo}` };
|
||||
}
|
||||
|
||||
export default async function WorkflowRunPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
import type { Metadata } from "next";
|
||||
import { getRepo } from "@/lib/github";
|
||||
import { RunComparisonPage } from "@/components/actions/run-comparison-page";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ owner: string; repo: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { owner, repo } = await params;
|
||||
return { title: `Compare Runs · ${owner}/${repo}` };
|
||||
}
|
||||
|
||||
export default async function CompareRunsPage({
|
||||
params,
|
||||
searchParams,
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
import type { Metadata } from "next";
|
||||
import { getRepoWorkflows, getRepoWorkflowRuns } from "@/lib/github";
|
||||
import { ActionsList } from "@/components/actions/actions-list";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ owner: string; repo: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { owner, repo } = await params;
|
||||
return { title: `Actions · ${owner}/${repo}` };
|
||||
}
|
||||
|
||||
export default async function ActionsPage({
|
||||
params,
|
||||
searchParams,
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
import type { Metadata } from "next";
|
||||
import { getRepo, getRepoEvents, getCommitActivity } from "@/lib/github";
|
||||
import { RepoActivityView } from "@/components/repo/repo-activity-view";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ owner: string; repo: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { owner, repo } = await params;
|
||||
return { title: `Activity · ${owner}/${repo}` };
|
||||
}
|
||||
|
||||
export default async function ActivityPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { Metadata } from "next";
|
||||
import {
|
||||
getFileContent,
|
||||
getRepoBranches,
|
||||
@@ -15,6 +16,22 @@ const MARKDOWN_EXTENSIONS = new Set(["md", "mdx", "markdown", "mdown", "mkd"]);
|
||||
|
||||
const IMAGE_EXTENSIONS = new Set(["png", "jpg", "jpeg", "gif", "svg", "webp", "ico", "bmp"]);
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ owner: string; repo: string; path: string[] }>;
|
||||
}): Promise<Metadata> {
|
||||
const { owner, repo, path: pathSegments } = await params;
|
||||
const [branches, tags] = await Promise.all([
|
||||
getRepoBranches(owner, repo),
|
||||
getRepoTags(owner, repo),
|
||||
]);
|
||||
const branchNames = [...branches.map((b) => b.name), ...tags.map((t) => t.name)];
|
||||
const { path } = parseRefAndPath(pathSegments, branchNames);
|
||||
const filename = path.split("/").pop() || path;
|
||||
return { title: `${filename} · ${owner}/${repo}` };
|
||||
}
|
||||
|
||||
function isBinary(content: string): boolean {
|
||||
// eslint-disable-next-line no-control-regex
|
||||
return /[\x00-\x08\x0E-\x1F]/.test(content.slice(0, 1000));
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { Metadata } from "next";
|
||||
import {
|
||||
getRepo,
|
||||
getRepoContents,
|
||||
@@ -13,6 +14,15 @@ import { MarkdownRenderer } from "@/components/shared/markdown-renderer";
|
||||
import { TrackView } from "@/components/shared/track-view";
|
||||
import { deleteBranch } from "../actions";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ owner: string; repo: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { owner, repo } = await params;
|
||||
return { title: `Code · ${owner}/${repo}` };
|
||||
}
|
||||
|
||||
export default async function CodePage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -1,7 +1,23 @@
|
||||
import type { Metadata } from "next";
|
||||
import { getCommit } from "@/lib/github";
|
||||
import { highlightDiffLines, type SyntaxToken } from "@/lib/shiki";
|
||||
import { CommitDetail } from "@/components/repo/commit-detail";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ owner: string; repo: string; sha: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { owner, repo, sha } = await params;
|
||||
const commit = await getCommit(owner, repo, sha);
|
||||
if (!commit) {
|
||||
return { title: `Commit ${sha.slice(0, 7)} · ${owner}/${repo}` };
|
||||
}
|
||||
const message = commit.commit?.message?.split("\n")[0] || "";
|
||||
const shortSha = sha.slice(0, 7);
|
||||
return { title: `${message || shortSha} · ${owner}/${repo}` };
|
||||
}
|
||||
|
||||
export default async function CommitDetailPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
import type { Metadata } from "next";
|
||||
import { getRepoCommits, getRepo, getRepoBranches } from "@/lib/github";
|
||||
import { CommitsList } from "@/components/repo/commits-list";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ owner: string; repo: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { owner, repo } = await params;
|
||||
return { title: `Commits · ${owner}/${repo}` };
|
||||
}
|
||||
|
||||
export default async function CommitsPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { Metadata } from "next";
|
||||
import {
|
||||
getRepo,
|
||||
getCommitActivity,
|
||||
@@ -8,6 +9,15 @@ import {
|
||||
} from "@/lib/github";
|
||||
import { InsightsView } from "@/components/repo/insights-view";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ owner: string; repo: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { owner, repo } = await params;
|
||||
return { title: `Insights · ${owner}/${repo}` };
|
||||
}
|
||||
|
||||
export default async function InsightsPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { Metadata } from "next";
|
||||
import {
|
||||
getIssue,
|
||||
getIssueComments,
|
||||
@@ -21,6 +22,24 @@ import { headers } from "next/headers";
|
||||
import { inngest } from "@/lib/inngest";
|
||||
import { isItemPinned } from "@/lib/pinned-items-store";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ owner: string; repo: string; number: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { owner, repo, number: numStr } = await params;
|
||||
const issueNumber = parseInt(numStr, 10);
|
||||
const issue = await getIssue(owner, repo, issueNumber);
|
||||
|
||||
if (!issue) {
|
||||
return { title: `Issue #${issueNumber} · ${owner}/${repo}` };
|
||||
}
|
||||
|
||||
return {
|
||||
title: `${issue.title} · Issue #${issueNumber} · ${owner}/${repo}`,
|
||||
};
|
||||
}
|
||||
|
||||
export default async function IssueDetailPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
import type { Metadata } from "next";
|
||||
import { getRepoIssuesPage } from "@/lib/github";
|
||||
import { IssuesList } from "@/components/issue/issues-list";
|
||||
import { fetchIssuesByAuthor } from "./actions";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ owner: string; repo: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { owner, repo } = await params;
|
||||
return { title: `Issues · ${owner}/${repo}` };
|
||||
}
|
||||
|
||||
export default async function IssuesListPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { Metadata } from "next";
|
||||
import { getRepoPageData } from "@/lib/github";
|
||||
import { TrackView } from "@/components/shared/track-view";
|
||||
import { RepoOverview, type RepoOverviewProps } from "@/components/repo/repo-overview";
|
||||
@@ -12,6 +13,15 @@ import {
|
||||
import { fetchPinnedItemsForRepo } from "./pin-actions";
|
||||
import { revalidateReadme } from "./readme-actions";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ owner: string; repo: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { owner, repo } = await params;
|
||||
return { title: `${owner}/${repo}` };
|
||||
}
|
||||
|
||||
export default async function RepoPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
import type { Metadata } from "next";
|
||||
import { getUser, getPersonRepoActivity, getRepoContributorStats } from "@/lib/github";
|
||||
import { PersonDetail } from "@/components/people/person-detail";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ owner: string; repo: string; username: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { owner, repo, username } = await params;
|
||||
return { title: `${username} · ${owner}/${repo}` };
|
||||
}
|
||||
|
||||
export default async function PersonPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
import type { Metadata } from "next";
|
||||
import { getOrgMembers, getUser, getOctokit } from "@/lib/github";
|
||||
import { PeopleList } from "@/components/people/people-list";
|
||||
import { inviteOrgMember } from "./actions";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ owner: string; repo: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { owner, repo } = await params;
|
||||
return { title: `People · ${owner}/${repo}` };
|
||||
}
|
||||
|
||||
export default async function PeoplePage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -1,9 +1,23 @@
|
||||
import type { Metadata } from "next";
|
||||
import { getPromptRequest, listPromptRequestComments } from "@/lib/prompt-request-store";
|
||||
import { PromptDetail } from "@/components/prompt-request/prompt-detail";
|
||||
import { notFound } from "next/navigation";
|
||||
import { auth } from "@/lib/auth";
|
||||
import { headers } from "next/headers";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ owner: string; repo: string; id: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { owner, repo, id } = await params;
|
||||
const promptRequest = await getPromptRequest(id);
|
||||
if (!promptRequest) {
|
||||
return { title: `Prompt · ${owner}/${repo}` };
|
||||
}
|
||||
return { title: `${promptRequest.title} · ${owner}/${repo}` };
|
||||
}
|
||||
|
||||
export default async function PromptDetailPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
import type { Metadata } from "next";
|
||||
import { listPromptRequests } from "@/lib/prompt-request-store";
|
||||
import { PromptList } from "@/components/prompt-request/prompt-list";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ owner: string; repo: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { owner, repo } = await params;
|
||||
return { title: `Prompts · ${owner}/${repo}` };
|
||||
}
|
||||
|
||||
export default async function PromptsPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { Metadata } from "next";
|
||||
import {
|
||||
getPullRequestBundle,
|
||||
getPullRequestFiles,
|
||||
@@ -35,6 +36,24 @@ import { inngest } from "@/lib/inngest";
|
||||
import { isItemPinned } from "@/lib/pinned-items-store";
|
||||
import { all } from "better-all";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ owner: string; repo: string; number: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { owner, repo, number: numStr } = await params;
|
||||
const pullNumber = parseInt(numStr, 10);
|
||||
const bundle = await getPullRequestBundle(owner, repo, pullNumber);
|
||||
|
||||
if (!bundle) {
|
||||
return { title: `PR #${pullNumber} · ${owner}/${repo}` };
|
||||
}
|
||||
|
||||
return {
|
||||
title: `${bundle.pr.title} · PR #${pullNumber} · ${owner}/${repo}`,
|
||||
};
|
||||
}
|
||||
|
||||
type GitHubPRFile = {
|
||||
filename: string;
|
||||
status: string;
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
import type { Metadata } from "next";
|
||||
import { getRepoPullRequestsWithStats } from "@/lib/github";
|
||||
import { PRsList } from "@/components/pr/prs-list";
|
||||
import { fetchPRsByAuthor, fetchAllCheckStatuses, prefetchPRDetail, fetchPRPage } from "./actions";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ owner: string; repo: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { owner, repo } = await params;
|
||||
return { title: `Pull Requests · ${owner}/${repo}` };
|
||||
}
|
||||
|
||||
export default async function PullsListPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -1,8 +1,22 @@
|
||||
import type { Metadata } from "next";
|
||||
import { ShieldAlert } from "lucide-react";
|
||||
import { getRepositoryAdvisory } from "@/lib/github";
|
||||
import { renderMarkdownToHtml } from "@/components/shared/markdown-renderer";
|
||||
import { AdvisoryDetail } from "@/components/security/advisory-detail";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ owner: string; repo: string; ghsaId: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { owner, repo, ghsaId } = await params;
|
||||
const advisory = await getRepositoryAdvisory(owner, repo, ghsaId);
|
||||
if (!advisory) {
|
||||
return { title: `Advisory · ${owner}/${repo}` };
|
||||
}
|
||||
return { title: `${advisory.summary || ghsaId} · ${owner}/${repo}` };
|
||||
}
|
||||
|
||||
export default async function AdvisoryDetailPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { Metadata } from "next";
|
||||
import { ShieldAlert } from "lucide-react";
|
||||
import { getRepoSecurityTabData, getFileContent } from "@/lib/github";
|
||||
import { renderMarkdownToHtml } from "@/components/shared/markdown-renderer";
|
||||
@@ -17,6 +18,15 @@ async function fetchSecurityPolicy(owner: string, repo: string): Promise<string
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ owner: string; repo: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { owner, repo } = await params;
|
||||
return { title: `Security · ${owner}/${repo}` };
|
||||
}
|
||||
|
||||
export default async function SecurityPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Settings } from "lucide-react";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Settings",
|
||||
};
|
||||
|
||||
export default function SettingsPage() {
|
||||
return (
|
||||
<div className="py-16 text-center">
|
||||
|
||||
@@ -1,7 +1,23 @@
|
||||
import type { Metadata } from "next";
|
||||
import { getRepoContents, getRepoBranches, getRepoTags } from "@/lib/github";
|
||||
import { parseRefAndPath } from "@/lib/github-utils";
|
||||
import { FileList } from "@/components/repo/file-list";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ owner: string; repo: string; path: string[] }>;
|
||||
}): Promise<Metadata> {
|
||||
const { owner, repo, path: pathSegments } = await params;
|
||||
const [branches, tags] = await Promise.all([
|
||||
getRepoBranches(owner, repo),
|
||||
getRepoTags(owner, repo),
|
||||
]);
|
||||
const branchNames = [...branches.map((b) => b.name), ...tags.map((t) => t.name)];
|
||||
const { path } = parseRefAndPath(pathSegments, branchNames);
|
||||
return { title: `${path || "/"} · ${owner}/${repo}` };
|
||||
}
|
||||
|
||||
export default async function TreePage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import type { Metadata } from "next";
|
||||
import { getUserRepos } from "@/lib/github";
|
||||
import { ReposContent } from "@/components/repos/repos-content";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Repositories",
|
||||
};
|
||||
|
||||
export default async function ReposPage() {
|
||||
const repos = await getUserRepos("updated", 50);
|
||||
return <ReposContent repos={repos} />;
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import type { Metadata } from "next";
|
||||
import { SearchContent } from "@/components/search/search-content";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Search",
|
||||
};
|
||||
|
||||
export default async function SearchPage({
|
||||
searchParams,
|
||||
}: {
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import type { Metadata } from "next";
|
||||
import { getTrendingRepos } from "@/lib/github";
|
||||
import { TrendingContent } from "@/components/trending/trending-content";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Trending",
|
||||
};
|
||||
|
||||
export default async function TrendingPage() {
|
||||
const [weekly, daily, monthly] = await Promise.all([
|
||||
getTrendingRepos(undefined, "weekly", 25),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { Metadata } from "next";
|
||||
import { getUser, getUserPublicRepos, getUserPublicOrgs, getContributionData } from "@/lib/github";
|
||||
import { UserProfileContent } from "@/components/users/user-profile-content";
|
||||
import { ExternalLink, User } from "lucide-react";
|
||||
@@ -30,6 +31,19 @@ function UnknownUserPage({ username }: { username: string }) {
|
||||
);
|
||||
}
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ username: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { username } = await params;
|
||||
const userData = await getUser(username).catch(() => null);
|
||||
if (!userData) {
|
||||
return { title: username };
|
||||
}
|
||||
return { title: userData.name ? `${userData.name} (${userData.login})` : userData.login };
|
||||
}
|
||||
|
||||
export default async function UserProfilePage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
Reference in New Issue
Block a user