From 216badf57837577d078d0e7c51ea2345bde527af Mon Sep 17 00:00:00 2001 From: Izaak Lauer <8404559+izaaklauer@users.noreply.github.com> Date: Thu, 31 Oct 2024 15:04:48 -0400 Subject: [PATCH] Izaak/orgs 17 setactive by url (#14) * Using middleware to control the active org via the url * Renaming and reorganizing * Minor polish * Fixing personal workspace navigation highlights And cleaning up unused code. * Removing unused sign-in page * Cleaning up yalc dependencies * Minor cleanups * Adding loading state to client-side components. --- examples/sync-org-with-url/.gitignore | 2 + examples/sync-org-with-url/package-lock.json | 79 +++++------ examples/sync-org-with-url/package.json | 5 +- examples/sync-org-with-url/src/app/layout.tsx | 120 ++++++++++++++-- .../sync-org-with-url/src/app/me/page.tsx | 21 +++ .../src/app/me/settings/page.tsx | 17 +++ .../sync-org-with-url/src/app/not-found.tsx | 11 ++ .../src/app/orgs/[orgSlug]/layout.tsx | 131 ------------------ .../src/app/orgs/[orgSlug]/page.tsx | 33 ----- .../[orgSlug]/settings/[[...rest]]/page.tsx | 10 -- .../src/app/orgs/[slug]/page.tsx | 47 +++++++ .../orgs/[slug]/settings/[[...rest]]/page.tsx | 36 +++++ examples/sync-org-with-url/src/app/page.tsx | 54 ++------ .../src/app/utils/organization-sync.tsx | 61 -------- examples/sync-org-with-url/src/middleware.ts | 20 ++- 15 files changed, 309 insertions(+), 338 deletions(-) create mode 100644 examples/sync-org-with-url/src/app/me/page.tsx create mode 100644 examples/sync-org-with-url/src/app/me/settings/page.tsx create mode 100644 examples/sync-org-with-url/src/app/not-found.tsx delete mode 100644 examples/sync-org-with-url/src/app/orgs/[orgSlug]/layout.tsx delete mode 100644 examples/sync-org-with-url/src/app/orgs/[orgSlug]/page.tsx delete mode 100644 examples/sync-org-with-url/src/app/orgs/[orgSlug]/settings/[[...rest]]/page.tsx create mode 100644 examples/sync-org-with-url/src/app/orgs/[slug]/page.tsx create mode 100644 examples/sync-org-with-url/src/app/orgs/[slug]/settings/[[...rest]]/page.tsx delete mode 100644 examples/sync-org-with-url/src/app/utils/organization-sync.tsx diff --git a/examples/sync-org-with-url/.gitignore b/examples/sync-org-with-url/.gitignore index fd3dbb5..47a1759 100644 --- a/examples/sync-org-with-url/.gitignore +++ b/examples/sync-org-with-url/.gitignore @@ -34,3 +34,5 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +.env.* diff --git a/examples/sync-org-with-url/package-lock.json b/examples/sync-org-with-url/package-lock.json index c10a156..b3dd0cd 100644 --- a/examples/sync-org-with-url/package-lock.json +++ b/examples/sync-org-with-url/package-lock.json @@ -8,7 +8,10 @@ "name": "my-app", "version": "0.1.0", "dependencies": { - "@clerk/nextjs": "5.2.9", + "@clerk/backend": "^1.13.9", + "@clerk/clerk-react": "^5.11.0", + "@clerk/nextjs": "^5.7.2", + "@clerk/types": "^4.25.0", "@radix-ui/react-slot": "^1.1.0", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", @@ -42,13 +45,13 @@ } }, "node_modules/@clerk/backend": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@clerk/backend/-/backend-1.5.0.tgz", - "integrity": "sha512-uJUcA4oIDfTkjhjcjnlnarjuLXp5rVvtXB1/HtFKLXfvm8SveH5D3w97IeiUDNMvggxBo1Q/faBDBjEJxTV9Cw==", + "version": "1.13.9", + "resolved": "https://registry.npmjs.org/@clerk/backend/-/backend-1.13.9.tgz", + "integrity": "sha512-WW5IyCsaKHld1lNKQ+XSifUJ75CJ2EFJMPcx+R04icexE90EQzktwT5jeHr3brN7YVR9+PJREzlePrt7eIF/uw==", "dependencies": { - "@clerk/shared": "2.4.2", - "@clerk/types": "4.10.0", - "cookie": "0.5.0", + "@clerk/shared": "2.9.0", + "@clerk/types": "4.25.0", + "cookie": "0.7.0", "snakecase-keys": "5.4.4", "tslib": "2.4.1" }, @@ -56,18 +59,26 @@ "node": ">=18.17.0" } }, + "node_modules/@clerk/backend/node_modules/cookie": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.0.tgz", + "integrity": "sha512-qCf+V4dtlNhSRXGAZatc1TasyFO6GjohcOul807YOb5ik3+kQSnb4d7iajeCL8QHaJ4uZEjCgiCJerKXwdRVlQ==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/@clerk/backend/node_modules/tslib": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "node_modules/@clerk/clerk-react": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@clerk/clerk-react/-/clerk-react-5.3.0.tgz", - "integrity": "sha512-sKJrIHwkfeemSolI4pU+jwNFYFG+HfwZ+Anx1JvnvlLDELUrsQMFCVOKCE7TOEs+Y/9loEK7xFdanzvxL+uasA==", + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/@clerk/clerk-react/-/clerk-react-5.11.0.tgz", + "integrity": "sha512-JPvDxSPMV1Rrnh5k1ULxeemvUW+F5YdVUQAUhPPl/iZ6MHO6vXr5jn66xe0hM+wrw/snGlsrD9ePyy6tK8EDKw==", "dependencies": { - "@clerk/shared": "2.4.2", - "@clerk/types": "4.10.0", + "@clerk/shared": "2.9.0", + "@clerk/types": "4.25.0", "tslib": "2.4.1" }, "engines": { @@ -84,16 +95,15 @@ "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "node_modules/@clerk/nextjs": { - "version": "5.2.9", - "resolved": "https://registry.npmjs.org/@clerk/nextjs/-/nextjs-5.2.9.tgz", - "integrity": "sha512-7RKF5Pnv80n58niDS+8Fkn03HTm4/zkceplQh2fN0bjH8WDwRXxB/YWtgC1IFLbZ0PeiHzo1nVRguTSuUqo1+Q==", - "dependencies": { - "@clerk/backend": "1.5.0", - "@clerk/clerk-react": "5.3.0", - "@clerk/shared": "2.4.2", - "@clerk/types": "4.10.0", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/@clerk/nextjs/-/nextjs-5.7.2.tgz", + "integrity": "sha512-G2ilYV0RyOrwc6gI6qmKAsML+7YLiVX/VFlkuvh3vk+qJ6ka8RDaoaILcmREEs4AOaQXBHYQCfiCrYMUeEUJFg==", + "dependencies": { + "@clerk/backend": "1.13.9", + "@clerk/clerk-react": "5.11.0", + "@clerk/shared": "2.9.0", + "@clerk/types": "4.25.0", "crypto-js": "4.2.0", - "path-to-regexp": "6.2.2", "server-only": "0.0.1", "tslib": "2.4.1" }, @@ -112,12 +122,12 @@ "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "node_modules/@clerk/shared": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@clerk/shared/-/shared-2.4.2.tgz", - "integrity": "sha512-8AZg7Qus7nGBwhbdJINV1NR0vAbOYtv/m8C9VdASHW/DzamNJvyf9d61E1DLZGTTjQw/Fja9zolq9CcWT5d6NA==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/@clerk/shared/-/shared-2.9.0.tgz", + "integrity": "sha512-DAqxJbmQ3QnQXZepG2InLC7Hdq+4T9/+A/kwtMQtAyQcsZoDwZ1TqVJkrqZ55lJIAkR97HEn3/g+g1ySspdEfA==", "hasInstallScript": true, "dependencies": { - "@clerk/types": "4.10.0", + "@clerk/types": "4.25.0", "glob-to-regexp": "0.4.1", "js-cookie": "3.0.5", "std-env": "^3.7.0", @@ -140,9 +150,9 @@ } }, "node_modules/@clerk/types": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@clerk/types/-/types-4.10.0.tgz", - "integrity": "sha512-Yy4m+aCrvVHT8BVNGDi40hcSUTwMf5o+cBHhAQQTofzCikc+DRI6yL7aYT6nf2YJ5gfm7WdeUwPM8Zz08TDzNA==", + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/@clerk/types/-/types-4.25.0.tgz", + "integrity": "sha512-p2IyJ0q5WF1e976L1pS1J6Mb5ducfkUC31DR1EvMjPwJkrlWJdAMCPc+zqRRAePVy/JBVK2gEKbUVtJ6/jrpag==", "dependencies": { "csstype": "3.1.1" }, @@ -1253,14 +1263,6 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, - "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -3670,11 +3672,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/path-to-regexp": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", - "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==" - }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", diff --git a/examples/sync-org-with-url/package.json b/examples/sync-org-with-url/package.json index 192042c..d6aff4b 100644 --- a/examples/sync-org-with-url/package.json +++ b/examples/sync-org-with-url/package.json @@ -9,7 +9,10 @@ "lint": "next lint" }, "dependencies": { - "@clerk/nextjs": "5.2.9", + "@clerk/backend": "^1.13.9", + "@clerk/clerk-react": "^5.11.0", + "@clerk/nextjs": "^5.7.2", + "@clerk/types": "^4.25.0", "@radix-ui/react-slot": "^1.1.0", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", diff --git a/examples/sync-org-with-url/src/app/layout.tsx b/examples/sync-org-with-url/src/app/layout.tsx index 45f7f58..1dddb4a 100644 --- a/examples/sync-org-with-url/src/app/layout.tsx +++ b/examples/sync-org-with-url/src/app/layout.tsx @@ -1,24 +1,18 @@ -import type { Metadata } from "next"; -import { Button } from "@/components/ui/button"; +'use client' + import { Inter } from "next/font/google"; import "./globals.css"; import Link from "next/link"; import { ClerkProvider, OrganizationSwitcher, - SignInButton, - SignedIn, - SignedOut, UserButton, } from "@clerk/nextjs"; -import {OrganizationSync} from "@/app/utils/organization-sync"; +import { useAuth } from "@clerk/nextjs"; +import { usePathname } from 'next/navigation' -const inter = Inter({ subsets: ["latin"] }); -export const metadata: Metadata = { - title: "Clerk Orgs: Set Active via URL", - description: "", -}; +const inter = Inter({ subsets: ["latin"] }); export default function RootLayout({ children, @@ -26,15 +20,115 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - //
- {children} + + {children} +
); } + +function LayoutContent({ children }: Readonly<{ + children: React.ReactNode; +}>) { + const { orgSlug } = useAuth(); + const pathname = usePathname() + + let prefix = "/me" + if (orgSlug) { + prefix = `/orgs/${orgSlug}` + } + + return ( +
+
+
+
+
+ +
+
+ +
+
+
+
+
+ + Home + +
+

Dashboard

+
+
+ +
+
+
+ {children} +
+
+
+
+ ) +} + +/** + * Gets the application-global URL prefix for the given organization slug. + * If the organization slug is null or undefined, returns the URL prefix for the personal account, '/me/' + * If the organization slug is defined, returns the URL prefix for the organization, '/orgs/:slug' + */ +function urlPrefix(orgSlug: string | null | undefined): string { + if (orgSlug) { + return `/orgs/${orgSlug}` + } + return "/me" +} diff --git a/examples/sync-org-with-url/src/app/me/page.tsx b/examples/sync-org-with-url/src/app/me/page.tsx new file mode 100644 index 0000000..e0aac2a --- /dev/null +++ b/examples/sync-org-with-url/src/app/me/page.tsx @@ -0,0 +1,21 @@ +import { auth } from '@clerk/nextjs/server'; +import {notFound} from "next/navigation"; +import {OrganizationProfile} from "@clerk/nextjs"; + +export default function Home():{} { + const authObject = auth(); + const orgId = authObject.orgId + + if (orgId != null ) { + console.log("Some org other than the personal account is active!") + notFound() + } + + return ( +
+

+ Welcome to your personal account! +

+
+ ) +} \ No newline at end of file diff --git a/examples/sync-org-with-url/src/app/me/settings/page.tsx b/examples/sync-org-with-url/src/app/me/settings/page.tsx new file mode 100644 index 0000000..4a7416a --- /dev/null +++ b/examples/sync-org-with-url/src/app/me/settings/page.tsx @@ -0,0 +1,17 @@ +import { auth } from '@clerk/nextjs/server'; +import {notFound} from "next/navigation"; + +export default function Home():{} { + const authObject = auth(); + + if (authObject.orgId != null ) { + console.log("Some org other than the personal account is active!") + notFound(); + } + + return ( + <> +

Welcome, user {authObject.userId} to your own personal account settings!

+ + ) +} \ No newline at end of file diff --git a/examples/sync-org-with-url/src/app/not-found.tsx b/examples/sync-org-with-url/src/app/not-found.tsx new file mode 100644 index 0000000..a2d8b4d --- /dev/null +++ b/examples/sync-org-with-url/src/app/not-found.tsx @@ -0,0 +1,11 @@ +import Link from 'next/link' + +export default function NotFound() { + return ( +
+

Not Found

+

Could not find requested resource

+ Return Home +
+ ) +} \ No newline at end of file diff --git a/examples/sync-org-with-url/src/app/orgs/[orgSlug]/layout.tsx b/examples/sync-org-with-url/src/app/orgs/[orgSlug]/layout.tsx deleted file mode 100644 index 385aed0..0000000 --- a/examples/sync-org-with-url/src/app/orgs/[orgSlug]/layout.tsx +++ /dev/null @@ -1,131 +0,0 @@ -'use client'; - -import { Button } from "@/components/ui/button"; -import { Inter } from "next/font/google"; -import "../../globals.css"; -import Link from "next/link"; -import { - OrganizationSwitcher, - SignInButton, - SignedIn, - SignedOut, - UserButton, useAuth, -} from "@clerk/nextjs"; -import {OrganizationSync} from "@/app/utils/organization-sync"; -import {useParams, usePathname} from "next/navigation"; - -const inter = Inter({ subsets: ["latin"] }); - -export default function Layout({ - children, - params, -}: Readonly<{ - children: React.ReactNode; - params: { orgSlug: string }; -}>) { - - const pathname = usePathname(); - const { orgSlug } = useAuth(); - return ( -
- -
-
-
-
- -
-
- -
-
-
-
-
- - Home - -
-

Dashboard

-
-
- -
-
-
- {children} -
-
-
-
-
-
- Orgs: {""} -
- - - - - - - - - -
-
-
-
- {children} -
-
-
- -
- ); -} diff --git a/examples/sync-org-with-url/src/app/orgs/[orgSlug]/page.tsx b/examples/sync-org-with-url/src/app/orgs/[orgSlug]/page.tsx deleted file mode 100644 index 556aabc..0000000 --- a/examples/sync-org-with-url/src/app/orgs/[orgSlug]/page.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { auth } from '@clerk/nextjs/server'; - -export default function Home({params}):{ - params: { slug: string } -} { - const {orgSlug} = auth(); - - // console.log("I'm the server and I got this slug: ", orgSlug); - - return ( - <> - -

From auth(), I know your org slug is: {orgSlug}

-
- - ) -} - -export function SSRSyncActiveOrganizationFromUrlToSession( - { children, orgSlug }: { children: React.ReactNode, orgSlug: string } -): React.ReactElement | null { - const sessionAuth = auth(); - if (sessionAuth.orgSlug != orgSlug) { - console.log("Mismatch - returning nothing for now...", sessionAuth.orgSlug, orgSlug) - return null - } - - return( - <> - {children} - - ) -} \ No newline at end of file diff --git a/examples/sync-org-with-url/src/app/orgs/[orgSlug]/settings/[[...rest]]/page.tsx b/examples/sync-org-with-url/src/app/orgs/[orgSlug]/settings/[[...rest]]/page.tsx deleted file mode 100644 index 4cd9f0c..0000000 --- a/examples/sync-org-with-url/src/app/orgs/[orgSlug]/settings/[[...rest]]/page.tsx +++ /dev/null @@ -1,10 +0,0 @@ -"use client"; - -import {OrganizationProfile, useAuth} from "@clerk/nextjs"; - -export default function Home() { - const {orgSlug} = useAuth() - return <> - - -} \ No newline at end of file diff --git a/examples/sync-org-with-url/src/app/orgs/[slug]/page.tsx b/examples/sync-org-with-url/src/app/orgs/[slug]/page.tsx new file mode 100644 index 0000000..ae7968a --- /dev/null +++ b/examples/sync-org-with-url/src/app/orgs/[slug]/page.tsx @@ -0,0 +1,47 @@ +import { auth } from '@clerk/nextjs/server'; +import {OrganizationList} from "@clerk/nextjs"; + +export default function Home({params}:{ + params: { slug: string } +}) { + const authObject = auth(); + const orgSlug = authObject.orgSlug + + if (params.slug != orgSlug ) { + return ( + <> +

Sorry, organization {params.slug} is not valid.

+ + + ) + } + + // The organization name was added to session claims for this application by + // [customizing the session token](https://clerk.com/docs/backend-requests/making/custom-session-token), + // using the following template: + // ```json + // { + // "org_name": "{{org.name}}" + // } + // ``` + let orgName = authObject.sessionClaims['org_name'] as string + + return ( +
+ {orgName && ( +

+ Welcome to organization {orgName} +

+ )} +

+ Your role in this organization: {authObject.orgRole} +

+
+ ) +} \ No newline at end of file diff --git a/examples/sync-org-with-url/src/app/orgs/[slug]/settings/[[...rest]]/page.tsx b/examples/sync-org-with-url/src/app/orgs/[slug]/settings/[[...rest]]/page.tsx new file mode 100644 index 0000000..8373078 --- /dev/null +++ b/examples/sync-org-with-url/src/app/orgs/[slug]/settings/[[...rest]]/page.tsx @@ -0,0 +1,36 @@ +"use client"; + +import {OrganizationList, OrganizationProfile, useOrganization} from "@clerk/nextjs"; + +export default function Home({params}:{ + params: { slug: string } +}) { + const {organization, isLoaded} = useOrganization() + + if (!isLoaded) { + return <>Loading... + } + + if (!organization || organization.slug != params.slug) { + console.log("Organization:", organization) + console.log("Organization Slug:", organization?.slug) + console.log("Params slug:", params.slug) + + return ( + <> +

Sorry, organization {params.slug} is not valid.

+ + + ) + } + + return <> + + +} \ No newline at end of file diff --git a/examples/sync-org-with-url/src/app/page.tsx b/examples/sync-org-with-url/src/app/page.tsx index 7fc088e..783ccd2 100644 --- a/examples/sync-org-with-url/src/app/page.tsx +++ b/examples/sync-org-with-url/src/app/page.tsx @@ -1,46 +1,14 @@ -"use client"; - -import {OrganizationList, useOrganizationList} from "@clerk/nextjs"; -import Link from "next/link"; +import {auth} from "@clerk/nextjs/server"; +import {redirect} from "next/navigation"; export default function Home() { - return ( -
-

There's not much you can do in this app outside of an organization.

-

Select an organization to continue:

- -
- ) -} - -function OrgPicker() { - const {isLoaded, userMemberships} = useOrganizationList( - { - userMemberships: { - memberships: { - pageSize: 100, // TODO(izaak): Brittle - figure out pagination - keepPreviousData: true, - }, - } - } - ); - - if (!isLoaded) { - return <>Loading...; + // Nothing to display at the root. If the personal account is active, + // redirect to /me, otherwise redirect to the org home. + let {orgSlug} = auth(); + if (orgSlug) { + // An organization is active - redirect to the org home. + redirect(`/orgs/${orgSlug}`) } - - return ( -
- {userMemberships?.data?.map((mem) => ( - - {mem.organization.name} - - ))} -
- ) -} + // THe personal account is active - redirect to personal account home. + redirect ("/me") +} \ No newline at end of file diff --git a/examples/sync-org-with-url/src/app/utils/organization-sync.tsx b/examples/sync-org-with-url/src/app/utils/organization-sync.tsx deleted file mode 100644 index 9d90401..0000000 --- a/examples/sync-org-with-url/src/app/utils/organization-sync.tsx +++ /dev/null @@ -1,61 +0,0 @@ -"use client" - -import {useEffect, useLayoutEffect, useState} from "react" -import {useParams} from "next/navigation" -import {OrganizationList, useAuth, useOrganizationList, useUser} from "@clerk/nextjs" - - - -export function OrganizationSync( - { children, pathnameSlug }: { children: React.ReactNode, pathnameSlug: string } -): React.ReactElement | null { - const { setActive, isLoaded } = useOrganizationList(); - - // Get the organization slug from the session - const {orgSlug} = useAuth(); - - const {user} = useUser() - - // Get the organization slug from the URL - - const [isMember, setIsMember] = useState(false); - - useLayoutEffect(() => { - if (!isLoaded) return; - - if (pathnameSlug) { - const reallyIsMember = user?.organizationMemberships?.some((mem) => - mem.organization.slug === pathnameSlug - ) - setIsMember(reallyIsMember || false); - } - - // If the org slug in the URL is not the same as the org slug in the session (the active organization), - // set the active organization to be the org from the URL. - if (pathnameSlug !== orgSlug) { - void setActive({ - organization: pathnameSlug - }); - } - }, [orgSlug, isLoaded, setActive, pathnameSlug]) - - if (pathnameSlug !== orgSlug) { - return null - } - - return ( - <> - {pathnameSlug && !isMember && -
- -
- } - {children} - - ) -} \ No newline at end of file diff --git a/examples/sync-org-with-url/src/middleware.ts b/examples/sync-org-with-url/src/middleware.ts index 37cecb7..a157515 100644 --- a/examples/sync-org-with-url/src/middleware.ts +++ b/examples/sync-org-with-url/src/middleware.ts @@ -1,13 +1,23 @@ import { clerkMiddleware, createRouteMatcher } from "@clerk/nextjs/server"; const isProtectedRoute = createRouteMatcher(["(.*)"]); -const isOrgSlugPrefix = createRouteMatcher(["/orgs/"]); export default clerkMiddleware((auth, req) => { if (isProtectedRoute(req)) auth().protect(); -}, { - orgSlugPrefix: isOrgSlugPrefix, -}); +}, + { + organizationSyncOptions: { + organizationPatterns: [ + "/orgs/:slug", // Matches any organization home page, e.g. /orgs/acmecorp + "/orgs/:slug/(.*)", // Matches any organization sub-page, e.g. /orgs/acmecorp/settings + ], + personalAccountPatterns: [ + "/me", // Matches the personal account home page + "/me/(.*)" // Matches any personal account sub-page, e.g. /me/settings + ], + }, + } +); export const config = { matcher: [ @@ -16,4 +26,4 @@ export const config = { // Always run for API routes "/(api|trpc)(.*)", ], -}; +}; \ No newline at end of file