Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: app router - all sub-pages in /apps #16976

Draft
wants to merge 57 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
ec41b0c
chore: apps/[slug] remove pages router
hbjORbj Oct 7, 2024
873088d
remove apps/[slug] pages from /future
hbjORbj Oct 7, 2024
89ecada
Merge remote-tracking branch 'origin/main' into chore/apps-remove-pag…
hbjORbj Dec 14, 2024
5587b8f
chore: apps/installed remove pages router
hbjORbj Dec 14, 2024
bcd6b9a
chore: apps/installation remove pages router
hbjORbj Oct 7, 2024
9dfa68c
remove Head element
hbjORbj Dec 6, 2024
d202648
fix metadata
hbjORbj Dec 6, 2024
ca569fe
fix test
hbjORbj Dec 6, 2024
d77b260
fix another test
hbjORbj Dec 6, 2024
45639f3
chore: apps/categories remove pages router
hbjORbj Oct 7, 2024
30e0f40
revert unneeded changes
hbjORbj Dec 14, 2024
e5902dd
update middleware
hbjORbj Dec 14, 2024
9d083e5
Remove <Head>
hbjORbj Dec 14, 2024
ed3d41d
Merge remote-tracking branch 'origin/main' into chore/apps-remove-pag…
hbjORbj Dec 20, 2024
7b3320e
remove unused import and code
hbjORbj Dec 20, 2024
2a32e66
remove unused import and code again
hbjORbj Dec 20, 2024
e4511ce
fix
hbjORbj Dec 21, 2024
d4f68c3
fix category page
hbjORbj Dec 21, 2024
ae30ea6
add split icon
hbjORbj Dec 21, 2024
fcc5c23
add /routing paths to middleware matcher
hbjORbj Dec 21, 2024
72d61a3
wip
hbjORbj Dec 21, 2024
4498bed
Merge remote-tracking branch 'origin/main' into chore/apps-remove-pag…
hbjORbj Dec 23, 2024
cff2a24
remove HeadSeo from App.tsx
hbjORbj Dec 23, 2024
eae1c4a
clean up head-seo test
hbjORbj Dec 23, 2024
2f622a4
add generateAppMetadata
hbjORbj Dec 23, 2024
5d94216
use generateAppMetadata in apps/[slug] page
hbjORbj Dec 23, 2024
8844697
delete file
hbjORbj Dec 23, 2024
f0dfc9d
Merge remote-tracking branch 'origin/main' into chore/apps-remove-pag…
hbjORbj Jan 2, 2025
91461a6
Merge origin/main
hbjORbj Jan 3, 2025
df28b6c
remove log
hbjORbj Jan 3, 2025
6c86eb4
fix
hbjORbj Jan 3, 2025
bff1e0f
fix
hbjORbj Jan 3, 2025
18e7419
fix apps/installed pages
hbjORbj Jan 3, 2025
d890d5a
fix cateogires pages
hbjORbj Jan 3, 2025
cf30c47
fix
hbjORbj Jan 4, 2025
beed796
fix imports
hbjORbj Jan 4, 2025
b4774b7
Merge branch 'main' into chore/apps-remove-pages-router-1
PeerRich Jan 4, 2025
4d761fa
wip
hbjORbj Jan 5, 2025
2011b9c
fix
hbjORbj Jan 5, 2025
84f58e4
fix
hbjORbj Jan 5, 2025
542405c
fix metadata
hbjORbj Jan 5, 2025
7b60a2a
fix
hbjORbj Jan 5, 2025
8990703
redirect /apps/routing-forms to /routing
hbjORbj Jan 5, 2025
6f54c96
replace all usages of /apps/routing-forms to /routing
hbjORbj Jan 5, 2025
dc9ec05
better naming
hbjORbj Jan 5, 2025
9f2fd6f
/routing -> /routing/forms
hbjORbj Jan 5, 2025
5bc5a6d
fix
hbjORbj Jan 5, 2025
5a6583b
fix
hbjORbj Jan 5, 2025
ae3ccc0
fix
hbjORbj Jan 5, 2025
aed704f
fix
hbjORbj Jan 6, 2025
90c2846
remove backPath as it is irrelevant when withoutMain is true
hbjORbj Jan 6, 2025
4a55a46
fix type checks
hbjORbj Jan 6, 2025
19753fa
fix type check in apps/[slug]
hbjORbj Jan 6, 2025
0812ff4
refactors
hbjORbj Jan 6, 2025
b41e10f
fix
hbjORbj Jan 6, 2025
6a9ab4a
fix test
hbjORbj Jan 6, 2025
3b8dad0
Merge branch 'main' into chore/apps-remove-pages-router-1
hbjORbj Jan 7, 2025
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
8 changes: 0 additions & 8 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -357,14 +357,6 @@ E2E_TEST_OIDC_USER_PASSWORD=
AB_TEST_BUCKET_PROBABILITY=50
# whether we redirect to the future/event-types from event-types or not
APP_ROUTER_EVENT_TYPES_ENABLED=0
APP_ROUTER_APPS_INSTALLED_CATEGORY_ENABLED=0
APP_ROUTER_APPS_SLUG_ENABLED=0
APP_ROUTER_APPS_SLUG_SETUP_ENABLED=0
# whether we redirect to the future/apps/categories from /apps/categories or not
APP_ROUTER_APPS_CATEGORIES_ENABLED=0
# whether we redirect to the future/apps/categories/[category] from /apps/categories/[category] or not
APP_ROUTER_APPS_CATEGORIES_CATEGORY_ENABLED=0
APP_ROUTER_APPS_ENABLED=0
APP_ROUTER_AUTH_FORGOT_PASSWORD_ENABLED=0
APP_ROUTER_AUTH_LOGIN_ENABLED=0
APP_ROUTER_AUTH_LOGOUT_ENABLED=0
Expand Down
5 changes: 0 additions & 5 deletions apps/web/abTest/middlewareFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@ import { FUTURE_ROUTES_ENABLED_COOKIE_NAME, FUTURE_ROUTES_OVERRIDE_COOKIE_NAME }

const ROUTES: [URLPattern, boolean][] = [
["/event-types", process.env.APP_ROUTER_EVENT_TYPES_ENABLED === "1"] as const,
["/apps/installed/:category", process.env.APP_ROUTER_APPS_INSTALLED_CATEGORY_ENABLED === "1"] as const,
["/apps/:slug", process.env.APP_ROUTER_APPS_SLUG_ENABLED === "1"] as const,
["/apps/:slug/setup", process.env.APP_ROUTER_APPS_SLUG_SETUP_ENABLED === "1"] as const,
["/apps/categories", process.env.APP_ROUTER_APPS_CATEGORIES_ENABLED === "1"] as const,
["/apps/categories/:category", process.env.APP_ROUTER_APPS_CATEGORIES_CATEGORY_ENABLED === "1"] as const,
["/auth/forgot-password/:path*", process.env.APP_ROUTER_AUTH_FORGOT_PASSWORD_ENABLED === "1"] as const,
["/auth/login", process.env.APP_ROUTER_AUTH_LOGIN_ENABLED === "1"] as const,
["/auth/logout", process.env.APP_ROUTER_AUTH_LOGOUT_ENABLED === "1"] as const,
Expand Down
32 changes: 27 additions & 5 deletions apps/web/app/_utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import i18next from "i18next";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import { headers } from "next/headers";

import type { MeetingImageProps } from "@calcom/lib/OgImages";
import { constructGenericImage, constructMeetingImage } from "@calcom/lib/OgImages";
import type { AppImageProps, MeetingImageProps } from "@calcom/lib/OgImages";
import { constructGenericImage, constructAppImage, constructMeetingImage } from "@calcom/lib/OgImages";
import { IS_CALCOM, WEBAPP_URL, APP_NAME, SEO_IMG_OGIMG, CAL_URL } from "@calcom/lib/constants";
import { buildCanonical } from "@calcom/lib/next-seo.config";
import { truncateOnWord } from "@calcom/lib/text";
Expand Down Expand Up @@ -62,17 +62,18 @@ const _generateMetadataWithoutImage = async (
const t = await getTranslationWithCache(locale);

const title = getTitle(t);
const description = getDescription(t);

const titleSuffix = `| ${APP_NAME}`;
const displayedTitle = title.includes(titleSuffix) || hideBranding ? title : `${title} ${titleSuffix}`;
const metadataBase = new URL(IS_CALCOM ? "https://cal.com" : WEBAPP_URL);
const truncatedDescription = truncateOnWord(getDescription(t), 158);

return {
title: title.length === 0 ? APP_NAME : displayedTitle,
description,
description: truncatedDescription,
alternates: { canonical },
openGraph: {
description: truncateOnWord(description, 158),
description: truncatedDescription,
url: canonical,
type: "website",
siteName: APP_NAME,
Expand Down Expand Up @@ -105,6 +106,26 @@ export const _generateMetadata = async (
};
};

export const generateAppMetadata = async (
app: AppImageProps,
getTitle: (t: TFunction<string, undefined>) => string,
getDescription: (t: TFunction<string, undefined>) => string,
hideBranding?: boolean,
origin?: string
) => {
const metadata = await _generateMetadataWithoutImage(getTitle, getDescription, hideBranding, origin);

const image = SEO_IMG_OGIMG + constructAppImage({ ...app, description: metadata.description });

return {
...metadata,
openGraph: {
...metadata.openGraph,
images: [image],
},
};
};

export const generateMeetingMetadata = async (
meeting: MeetingImageProps,
getTitle: (t: TFunction<string, undefined>) => string,
Expand All @@ -113,6 +134,7 @@ export const generateMeetingMetadata = async (
origin?: string
) => {
const metadata = await _generateMetadataWithoutImage(getTitle, getDescription, hideBranding, origin);

const image = SEO_IMG_OGIMG + constructMeetingImage(meeting);
return {
...metadata,
Expand Down
68 changes: 68 additions & 0 deletions apps/web/app/apps/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import type { PageProps as _PageProps } from "app/_types";
import { _generateMetadata, generateAppMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { notFound } from "next/navigation";
import { z } from "zod";

import { AppRepository } from "@calcom/lib/server/repository/app";
import { isPrismaAvailableCheck } from "@calcom/prisma/is-prisma-available-check";

import { getStaticProps } from "@lib/apps/[slug]/getStaticProps";

import AppView from "~/apps/[slug]/slug-view";

const paramsSchema = z.object({
slug: z.string(),
});

export const generateMetadata = async ({ params, searchParams }: _PageProps) => {
const p = paramsSchema.safeParse(params);

if (!p.success) {
return notFound();
}

const props = await getStaticProps(p.data.slug);

if (!props) {
notFound();
}
const { name, logo, description } = props.data;

return await generateAppMetadata(
{ slug: logo, name, description },
() => name,
() => description
);
};

export const generateStaticParams = async () => {
const isPrismaAvailable = await isPrismaAvailableCheck();

if (!isPrismaAvailable) {
// Database is not available at build time. Make sure we fall back to building these pages on demand
return [];
}
const appStore = await AppRepository.findAppStore();
return appStore.map(({ slug }) => ({ slug }));
};

async function Page({ params }: _PageProps) {
const p = paramsSchema.safeParse(params);

if (!p.success) {
return notFound();
}

const props = await getStaticProps(p.data.slug);

if (!props) {
notFound();
}

return <AppView {...props} />;
}

export default WithLayout({ getLayout: null, ServerPage: Page });

export const dynamic = "force-dynamic";
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,34 @@ import { withAppDirSsr } from "app/WithAppDirSsr";
import type { PageProps as _PageProps } from "app/_types";
import { _generateMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { notFound } from "next/navigation";
import { z } from "zod";

import { getServerSideProps } from "@calcom/app-store/_pages/setup/_getServerSideProps";

import Page, { type PageProps } from "~/apps/[slug]/setup/setup-view";

const paramsSchema = z.object({
slug: z.string(),
});

export const generateMetadata = async ({ params }: _PageProps) => {
return await _generateMetadata(
() => `${params.slug}`,
const p = paramsSchema.safeParse(params);

if (!p.success) {
return notFound();
}
const metadata = await _generateMetadata(
() => `${p.data.slug}`,
() => ""
);
return {
...metadata,
robots: {
follow: false,
index: false,
},
};
};

const getData = withAppDirSsr<PageProps>(getServerSideProps);
Expand Down
40 changes: 40 additions & 0 deletions apps/web/app/apps/categories/[category]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import type { PageProps } from "app/_types";
import { _generateMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { redirect } from "next/navigation";
import { z } from "zod";

import { AppCategories } from "@calcom/prisma/enums";

import { getStaticProps } from "@lib/apps/categories/[category]/getStaticProps";

import CategoryPage from "~/apps/categories/[category]/category-view";

const querySchema = z.object({
category: z.enum(Object.values(AppCategories) as [AppCategories, ...AppCategories[]]),
});

export const generateMetadata = async () => {
return await _generateMetadata(
(t) => t("app_store"),
(t) => t("app_store_description")
);
};

export const generateStaticParams = async () => {
const paths = Object.keys(AppCategories);
return paths.map((category) => ({ category }));
};

async function Page({ params, searchParams }: PageProps) {
const parsed = querySchema.safeParse({ ...params, ...searchParams });
if (!parsed.success) {
redirect("/apps/categories/calendar");
}

const props = await getStaticProps(parsed.data.category);

return <CategoryPage {...props} />;
}

export default WithLayout({ getLayout: null, ServerPage: Page });
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import Page from "~/apps/installation/[[...step]]/step-view";

export const generateMetadata = async ({ params, searchParams }: PageProps) => {
const legacyCtx = buildLegacyCtx(headers(), cookies(), params, searchParams);

const { appMetadata } = await getData(legacyCtx);
return await _generateMetadata(
(t) => `${t("install")} ${appMetadata?.name ?? ""}`,
Expand All @@ -23,3 +22,4 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => {
const getData = withAppDirSsr<OnboardingPageProps>(getServerSideProps);

export default WithLayout({ getLayout: null, getData, Page });

32 changes: 32 additions & 0 deletions apps/web/app/apps/installed/[category]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { PageProps } from "app/_types";
import { _generateMetadata } from "app/_utils";
import { WithLayout } from "app/layoutHOC";
import { redirect } from "next/navigation";
import { z } from "zod";

import { AppCategories } from "@calcom/prisma/enums";

import InstalledApps from "~/apps/installed/[category]/installed-category-view";

const querySchema = z.object({
category: z.nativeEnum(AppCategories),
});

export const generateMetadata = async () => {
return await _generateMetadata(
(t) => t("installed_apps"),
(t) => t("manage_your_connected_apps")
);
};

const InstalledAppsWrapper = async ({ params }: PageProps) => {
const parsedParams = querySchema.safeParse(params);

if (!parsedParams.success) {
redirect("/apps/installed/calendar");
}

return <InstalledApps category={parsedParams.data.category} />;
};

export default WithLayout({ getLayout: null, ServerPage: InstalledAppsWrapper });
45 changes: 0 additions & 45 deletions apps/web/app/future/apps/[slug]/page.tsx

This file was deleted.

34 changes: 0 additions & 34 deletions apps/web/app/future/apps/categories/[category]/page.tsx

This file was deleted.

18 changes: 0 additions & 18 deletions apps/web/app/future/apps/installed/[category]/page.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion apps/web/app/future/routing-forms/[...pages]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const paramsSchema = z
const Page = ({ params, searchParams }: PageProps) => {
const { pages } = paramsSchema.parse({ ...params, ...searchParams });

redirect(`/apps/routing-forms/${pages.length ? pages.join("/") : ""}`);
redirect(`/routing/${pages.length ? pages.join("/") : ""}`);
};

export default Page;
Loading
Loading