Skip to content

Commit 182d16b

Browse files
committed
implement notFound handling for missing APIs in ProviderPage and ApiPage; update next.config for redirects based on legacy slugs
1 parent b48ce2f commit 182d16b

File tree

3 files changed

+66
-43
lines changed

3 files changed

+66
-43
lines changed

app/apis/[providerSlug]/[serviceSlug]/page.tsx

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import Link from "next/link";
33
import Image from "next/image";
44
import { marked } from "marked";
55
import { Metadata, ResolvingMetadata } from "next";
6+
import { notFound } from "next/navigation";
67
import DescriptionSection from "../../../../components/DescriptionSection";
78
import list from "../../../../list.json";
8-
import { Badge } from "@/components/ui/badge";
9+
910
import JsonTreeContainer, { JsonTree } from "@/components/JsonTree";
1011
import ApiButtons from "@/components/ApiButtons";
1112
import VisitCounter from "@/components/VisitCounter";
@@ -154,13 +155,7 @@ export async function generateMetadata(
154155
const isProduction = process.env.NEXT_PUBLIC_SITE_ENV === "production";
155156

156157
if (!api) {
157-
return {
158-
title: "API Not Found",
159-
description: "The requested API was not found in the directory.",
160-
alternates: {
161-
canonical: `${siteUrl}/apis/${providerSlug}/${serviceSlug}`,
162-
},
163-
};
158+
notFound();
164159
}
165160

166161
const title = `${api.info.title} API`;
@@ -213,17 +208,7 @@ export default async function ApiPage({
213208
const api = getData(providerSlug, serviceSlug);
214209

215210
if (!api) {
216-
return (
217-
<div className="container mx-auto p-6 max-w-4xl">
218-
<Link
219-
href="/"
220-
className="text-[#388c9a] hover:underline mb-4 inline-block"
221-
>
222-
← Back to APIs
223-
</Link>
224-
<div>API not found</div>
225-
</div>
226-
);
211+
notFound();
227212
}
228213

229214
return (

app/apis/[providerSlug]/page.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from "react";
22
import Link from "next/link";
3+
import { notFound } from "next/navigation";
34
import list from "../../../list.json";
45
import { generateSimpleMetadata } from "@/sanity/lib/metadata";
56

@@ -108,6 +109,10 @@ export default async function ProviderPage({
108109
const { providerSlug } = await params;
109110
const apis = getProviderApis(providerSlug);
110111

112+
if (apis.length === 0) {
113+
notFound();
114+
}
115+
111116
const services = apis.filter((api) => api.serviceName);
112117
if (services.length > 0) {
113118
const providerName = apis[0]?.providerName || providerSlug;

next.config.ts

Lines changed: 57 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { withSentryConfig } from "@sentry/nextjs";
22
import type { NextConfig } from "next";
3-
3+
import list from "./list.json";
44
const nextConfig: NextConfig = {
55
output: "standalone",
66
basePath: "",
@@ -31,36 +31,69 @@ const nextConfig: NextConfig = {
3131

3232
return config;
3333
},
34-
};
34+
async redirects() {
35+
const redirectList = [];
3536

36-
export default withSentryConfig(nextConfig, {
37-
// For all available options, see:
38-
// https://www.npmjs.com/package/@sentry/webpack-plugin#options
37+
const normalizeSlug = (text: string, preserveDots = false) => {
38+
return text
39+
.toLowerCase()
40+
.replace(preserveDots ? /[^a-z0-9.]+/g : /[^a-z0-9]+/g, "-")
41+
.replace(/-+/g, "-")
42+
.replace(/^-+|-+$/g, "");
43+
};
3944

40-
org: "apisguru",
41-
project: "apis-guru",
45+
const normalizeServiceSlug = (service: string) => {
46+
return service
47+
.toLowerCase()
48+
.replace(/[\(\)]/g, "")
49+
.replace(/[^a-z0-9]+/g, "-")
50+
.replace(/-+/g, "-")
51+
.replace(/^-+|-+$/g, "");
52+
};
4253

43-
// Only print logs for uploading source maps in CI
44-
silent: !process.env.CI,
54+
for (const key in list) {
55+
if (!Object.prototype.hasOwnProperty.call(list, key)) continue;
4556

46-
// For all available options, see:
47-
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
57+
const [provider, service] = key.split(":");
58+
if (!provider) {
59+
console.warn(`Invalid key format: ${key}`);
60+
continue;
61+
}
4862

49-
// Upload a larger set of source maps for prettier stack traces (increases build time)
50-
widenClientFileUpload: true,
63+
const legacyFullSlug = normalizeSlug(key);
64+
const currentProviderSlug = normalizeSlug(provider, true);
65+
const legacyProviderSlug = normalizeSlug(provider.replace(/\./g, "-"));
5166

52-
// Uncomment to route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.
53-
// This can increase your server load as well as your hosting bill.
54-
// Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client-
55-
// side errors will fail.
56-
// tunnelRoute: "/monitoring",
67+
const destination = service
68+
? `/apis/${encodeURIComponent(currentProviderSlug)}/${encodeURIComponent(normalizeServiceSlug(service))}`
69+
: `/apis/${encodeURIComponent(currentProviderSlug)}`;
5770

58-
// Automatically tree-shake Sentry logger statements to reduce bundle size
59-
disableLogger: true,
71+
if (legacyFullSlug !== currentProviderSlug) {
72+
redirectList.push({
73+
source: `/apis/${encodeURIComponent(legacyFullSlug)}`,
74+
destination,
75+
permanent: true,
76+
});
77+
}
78+
79+
if (legacyProviderSlug !== currentProviderSlug) {
80+
redirectList.push({
81+
source: `/apis/${encodeURIComponent(legacyProviderSlug)}`,
82+
destination: `/apis/${encodeURIComponent(currentProviderSlug)}`,
83+
permanent: true,
84+
});
85+
}
86+
}
6087

61-
// Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.)
62-
// See the following for more information:
63-
// https://docs.sentry.io/product/crons/
64-
// https://vercel.com/docs/cron-jobs
88+
return redirectList;
89+
},
90+
};
91+
92+
export default withSentryConfig(nextConfig, {
93+
org: "apisguru",
94+
project: "apis-guru",
95+
silent: !process.env.CI,
96+
widenClientFileUpload: true,
97+
disableLogger: true,
6598
automaticVercelMonitors: true,
6699
});

0 commit comments

Comments
 (0)