├── .env.example ├── .gitignore ├── .nvmrc ├── README.md ├── app ├── _template │ ├── README.md │ ├── components │ │ ├── clerk-logo.tsx │ │ ├── deploy-button.tsx │ │ ├── footer.tsx │ │ ├── landing-hero.tsx │ │ ├── learn-more.tsx │ │ └── next-logo.tsx │ ├── content │ │ ├── cards.ts │ │ └── metadata.ts │ ├── images │ │ ├── logo.png │ │ ├── sign-in@2xrl.webp │ │ ├── sign-up@2xrl.webp │ │ ├── user-button-2@2xrl.webp │ │ ├── user-button@2xrl.webp │ │ └── verify@2xrl.webp │ └── styles │ │ └── landing.css ├── api │ └── protected │ │ └── route.ts ├── components │ ├── code-switcher.tsx │ ├── theme.ts │ └── user-details.tsx ├── dashboard │ └── page.tsx ├── favicon.ico ├── fonts │ ├── GeistMonoVF.woff │ └── GeistVF.woff ├── globals.css ├── layout.tsx ├── page.tsx └── sign-in │ └── [[...sign-in]] │ └── page.tsx ├── middleware.ts ├── package-lock.json ├── package.json ├── postcss.config.js ├── public ├── clerk.svg ├── dark-logo.png ├── light-logo.png ├── next.svg ├── og.png └── vercel.svg ├── tailwind.config.js └── tsconfig.json /.env.example: -------------------------------------------------------------------------------- 1 | # To access your Clerk keys, first create a clerk.com account then open dashboard.clerk.com. Create a new Clerk application and copy the Keys from step 2 in the Next.js quickstart tab. 2 | CLERK_SECRET_KEY= 3 | NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY= 4 | 5 | # The route at which your authentication flow lives, for more information see: https://clerk.com/docs/deployments/clerk-environment-variables 6 | NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in 7 | 8 | # Redirect URLs for after authenticating, for more information see: https://clerk.com/docs/guides/custom-redirects 9 | NEXT_PUBLIC_CLERK_SIGN_IN_FORCE_REDIRECT_URL=/dashboard 10 | NEXT_PUBLIC_CLERK_SIGN_UP_FORCE_REDIRECT_URL=/dashboard 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | 38 | # clerk configuration (can include secrets) 39 | /.clerk/ 40 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v20 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 |

10 |
11 |

12 | Next.js Clerk auth starter template 13 |

14 | 15 | 16 | 17 | 18 | Discord 19 | 20 | 21 | Twitter 22 | 23 |
24 |
25 | Clerk Hero Image 26 |
27 | 28 | ## Introduction 29 | 30 | Clerk is a developer-first authentication and user management solution. It provides pre-built React components and hooks for sign-in, sign-up, user profile, and organization management. Clerk is designed to be easy to use and customize, and can be dropped into any React or Next.js application. 31 | 32 | This template allows you to get started with Clerk and Next.js (App Router) in a matter of minutes, and demonstrates features of Clerk such as: 33 | 34 | - Fully functional auth flow with sign-in, sign-up, and a protected page 35 | - Customized Clerk components with Tailwind CSS 36 | - Hooks for accessing user data and authentication state 37 | - Organizations for multi-tenant applications 38 | 39 | ## Demo 40 | 41 | A hosted demo of this example is available at https://clerk-nextjs-app-router.vercel.app/ 42 | 43 | ## Deploy 44 | 45 | Easily deploy the template to Vercel with the button below. You will need to set the required environment variables in the Vercel dashboard. 46 | 47 | [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fclerk%2Fnextjs-auth-starter-template&project-name=nextjs-clerk&repository-name=nextjs-with-clerk&demo-title=Next.js+Clerk+Template&demo-description=A+Next.js+application+pre-configured+to+authenticate+users+with+Clerk.&demo-url=https%3A%2F%2Fnextjs-auth-starter-template-kit.vercel.app%2F&demo-image=%2F%2Fraw.githubusercontent.com%2Fclerk%2Fnextjs-auth-starter-template%2Frefs%2Fheads%2Fmain%2Fpublic%2Fog.png&products=%5B%7B%22type%22%3A%22integration%22%2C%22integrationSlug%22%3A%22clerk%22%2C%22productSlug%22%3A%22clerk%22%2C%22protocol%22%3A%22authentication%22%2C%22group%22%3A%22%22%7D%5D) 48 | 49 | ## Running the template 50 | 51 | ```bash 52 | git clone https://github.com/clerk/clerk-nextjs-demo-app-router 53 | ``` 54 | 55 | To run the example locally, you need to: 56 | 57 | 1. Sign up for a Clerk account at [https://clerk.com](https://go.clerk.com/31bREJU). 58 | 2. Go to the [Clerk dashboard](https://go.clerk.com/4I5LXFj) and create an application. 59 | 3. Set the required Clerk environment variables as shown in [the example `env` file](./.env.example). 60 | 4. Go to "Organization Settings" in your sidebar and enable Organizations 61 | 5. `npm install` the required dependencies. 62 | 6. `npm run dev` to launch the development server. 63 | 64 | ## Learn more 65 | 66 | To learn more about Clerk and Next.js, check out the following resources: 67 | 68 | - [Quickstart: Get started with Next.js and Clerk](https://go.clerk.com/vgWhQ7B) 69 | - [Clerk Documentation](https://go.clerk.com/aNiTioa) 70 | - [Next.js Documentation](https://nextjs.org/docs) 71 | 72 | ## Found an issue or have feedback? 73 | 74 | If you have found an issue with this repo or have feedback, please join our Discord and create a new thread inside of our [support](https://clerk.com/discord) channel. 75 | 76 | If it's a quick fix, such as a misspelled word or a broken link, feel free to skip creating a thread. 77 | Go ahead and create a [pull request](https://github.com/clerk/clerk-nextjs-demo-app-router/pulls) with the solution. :rocket: 78 | 79 | ## Connect with us 80 | 81 | You can discuss ideas, ask questions, and meet others from the community in our [Discord](https://clerk.com/discord). 82 | 83 | If you prefer, you can also find support through our [Twitter](https://twitter.com/ClerkDev), or you can [email](mailto:support@clerk.dev) us! 84 | -------------------------------------------------------------------------------- /app/_template/README.md: -------------------------------------------------------------------------------- 1 | # Template Directory 2 | 3 | This directory contains all template-specific code for the Clerk + Next.js starter template. It's designed to be easily removable when you're ready to build your own application. 4 | -------------------------------------------------------------------------------- /app/_template/components/clerk-logo.tsx: -------------------------------------------------------------------------------- 1 | export function ClerkLogo() { 2 | return ( 3 | 7 | 14 | 18 | 22 | 27 | 28 | 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /app/_template/components/deploy-button.tsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | import { clsx } from "clsx"; 3 | 4 | const DEPLOY_URL = 5 | "https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fclerk%2Fnextjs-auth-starter-template&project-name=nextjs-clerk&repository-name=nextjs-with-clerk&demo-title=Next.js+Clerk+Template&demo-description=A+Next.js+application+pre-configured+to+authenticate+users+with+Clerk.&demo-url=https%3A%2F%2Fnextjs-auth-starter-template-kit.vercel.app%2F&demo-image=%2F%2Fraw.githubusercontent.com%2Fclerk%2Fnextjs-auth-starter-template%2Frefs%2Fheads%2Fmain%2Fpublic%2Fog.png&products=%5B%7B%22type%22%3A%22integration%22%2C%22integrationSlug%22%3A%22clerk%22%2C%22productSlug%22%3A%22clerk%22%2C%22protocol%22%3A%22authentication%22%2C%22group%22%3A%22%22%7D%5D"; 6 | 7 | export function DeployButton({ className }: { className?: string }) { 8 | return ( 9 | 17 | 23 | 24 | 25 | Deploy to Vercel 26 | 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /app/_template/components/footer.tsx: -------------------------------------------------------------------------------- 1 | export function Footer() { 2 | return ( 3 | 145 | ); 146 | } 147 | -------------------------------------------------------------------------------- /app/_template/components/landing-hero.tsx: -------------------------------------------------------------------------------- 1 | import { SignInButton, SignedIn, SignedOut } from "@clerk/nextjs"; 2 | import screenshotDevices from "../images/user-button@2xrl.webp"; 3 | import signIn from "../images/sign-in@2xrl.webp"; 4 | import verify from "../images/verify@2xrl.webp"; 5 | import userButton2 from "../images/user-button-2@2xrl.webp"; 6 | import signUp from "../images/sign-up@2xrl.webp"; 7 | import logo from "../images/logo.png"; 8 | import "../styles/landing.css"; 9 | import Image from "next/image"; 10 | import Link from "next/link"; 11 | import { ClerkLogo } from "./clerk-logo"; 12 | import { NextLogo } from "./next-logo"; 13 | import { DeployButton } from "./deploy-button"; 14 | 15 | export function LandingHero() { 16 | return ( 17 |
18 |
19 |
20 | 21 |
22 |
23 |
24 | 25 |
26 | 27 |
28 | 29 |
30 |
31 | 32 | Device 38 | 39 |
40 |

41 | Auth starts here 42 |

43 | 44 |

45 | A simple and powerful Next.js template featuring authentication and 46 | user management powered by Clerk. 47 |

48 |
49 | 50 | 54 | Dashboard 55 | 56 | 57 | 58 | 59 | 62 | 63 | 64 |
65 |
66 |
67 |
68 | Device 74 |
75 |
76 | Device 82 | Device 88 |
89 |
90 | Device 96 | Device 102 |
103 |
104 |
105 |
106 |
107 | ); 108 | } 109 | -------------------------------------------------------------------------------- /app/_template/components/learn-more.tsx: -------------------------------------------------------------------------------- 1 | interface Card { 2 | title: string; 3 | description: string; 4 | href: string; 5 | linkText: string; 6 | } 7 | 8 | export function LearnMore({ cards }: { cards: Card[] }) { 9 | return ( 10 |
11 |
12 |
13 | 14 | What's next 15 | 16 |

17 | Learn more from our resources 18 |

19 |

20 | Prebuilt components to handle essential functionality like user 21 | sign-in, sign-up, and account management. 22 |

23 |
24 |
25 | {cards.map((card) => ( 26 | 32 |
33 |

34 | {card.title} 35 |

36 |

37 | {card.description} 38 |

39 |
40 |
41 | {card.linkText} 42 | 49 | 57 | 64 | 65 |
66 |
67 | ))} 68 |
69 |
70 |
71 | ); 72 | } 73 | -------------------------------------------------------------------------------- /app/_template/components/next-logo.tsx: -------------------------------------------------------------------------------- 1 | export function NextLogo() { 2 | return ( 3 | 4 | 11 | 12 | 21 | 25 | 26 | 27 | 31 | 35 | 39 | 40 | 41 | 42 | 50 | 51 | 52 | 53 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | ); 71 | } 72 | -------------------------------------------------------------------------------- /app/_template/content/cards.ts: -------------------------------------------------------------------------------- 1 | export const CARDS = [ 2 | { 3 | title: "Customizable Components", 4 | description: 5 | "Prebuilt components to handle essential functionality like user sign-in, sign-up, and account management.", 6 | href: "https://clerk.com/docs/components/overview?utm_source=vercel-template&utm_medium=partner&utm_term=component_reference", 7 | linkText: "Component Reference", 8 | }, 9 | { 10 | title: "React Hooks", 11 | description: `Build custom functionality by accessing auth state, user and session data, and more with Clerk's React Hooks.`, 12 | href: "https://clerk.com/docs/references/react/use-user?utm_source=vercel-template&utm_medium=partner&utm_term=react_hooks", 13 | linkText: "React Hooks", 14 | }, 15 | { 16 | title: "Organizations", 17 | description: 18 | "Built for B2B SaaS: create and switch between orgs, manage and invite members, and assign custom roles.", 19 | href: "https://clerk.com/docs/organizations/overview?utm_source=vercel-template&utm_medium=partner&utm_term=organizations", 20 | linkText: "Organizations", 21 | }, 22 | { 23 | title: "Billing", 24 | description: 25 | "Subscription billing without the headache: add subscription billing to your application with a few clicks and start collecting money.", 26 | href: "https://clerk.com/docs/billing/overview?utm_source=vercel-template&utm_medium=partner&utm_term=billing", 27 | linkText: "Billing", 28 | }, 29 | ]; 30 | 31 | export const DASHBOARD_CARDS = [ 32 | { 33 | title: "Authenticate requests with JWT's", 34 | description: 35 | "Clerk empowers you to authenticate same and cross origin requests using a Clerk generated JWT", 36 | href: "https://clerk.com/docs/backend-requests/overview?utm_source=vercel-template&utm_medium=partner&utm_term=JWT", 37 | linkText: "Request authentication", 38 | }, 39 | { 40 | title: "Build an onboarding flow", 41 | description: `Leverage customizable session tokens, public metadata, and Middleware to create a custom onboarding experience.`, 42 | href: "https://clerk.com/docs/guides/add-onboarding-flow?utm_source=vercel-template&utm_medium=partner&utm_term=onboarding", 43 | linkText: "Onboarding flow", 44 | }, 45 | { 46 | title: "Customize components", 47 | description: 48 | "Customize the look and feel of your application with Clerk's prebuilt components.", 49 | href: "https://clerk.com/docs/customization/overview?utm_source=vercel-template&utm_medium=partner&utm_term=customization", 50 | linkText: "Customization", 51 | }, 52 | { 53 | title: "Support subscriptions", 54 | description: 55 | "Subscription billing without the headache: add subscription billing to your application with a few clicks and start collecting money.", 56 | href: "https://clerk.com/docs/billing/overview?utm_source=vercel-template&utm_medium=partner&utm_term=billing", 57 | linkText: "Billing", 58 | }, 59 | { 60 | title: "Explore the B2B suite", 61 | description: 62 | "Built for B2B SaaS: create and switch between orgs, manage and invite members, and assign custom roles.", 63 | href: "https://clerk.com/docs/organizations/overview?utm_source=vercel-template&utm_medium=partner&utm_term=organizations", 64 | linkText: "Organizations", 65 | }, 66 | { 67 | title: "Deploy to Production", 68 | description: 69 | "Production instances are meant to support high volumes of traffic and by default, have a more strict security posture.", 70 | href: "https://clerk.com/docs/deployments/overview?utm_source=vercel-template&utm_medium=partner&utm_term=deploy-to-prod", 71 | linkText: "Production", 72 | }, 73 | ]; 74 | -------------------------------------------------------------------------------- /app/_template/content/metadata.ts: -------------------------------------------------------------------------------- 1 | import { Metadata } from "next"; 2 | 3 | export const templateMetadata: Metadata = { 4 | metadataBase: new URL("https://clerk-nextjs-app-router.vercel.app/"), 5 | title: "Next.js Clerk Template", 6 | description: 7 | "A simple and powerful Next.js template featuring authentication and user management powered by Clerk.", 8 | openGraph: { images: ["/og.png"] }, 9 | }; 10 | 11 | // Default metadata for when template is removed 12 | export const defaultMetadata: Metadata = { 13 | title: "My App", 14 | description: "My Next.js app with Clerk authentication", 15 | }; 16 | -------------------------------------------------------------------------------- /app/_template/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clerk/nextjs-auth-starter-template/d0aeb1078ddfe9b189c32c4e721e92660f505adb/app/_template/images/logo.png -------------------------------------------------------------------------------- /app/_template/images/sign-in@2xrl.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clerk/nextjs-auth-starter-template/d0aeb1078ddfe9b189c32c4e721e92660f505adb/app/_template/images/sign-in@2xrl.webp -------------------------------------------------------------------------------- /app/_template/images/sign-up@2xrl.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clerk/nextjs-auth-starter-template/d0aeb1078ddfe9b189c32c4e721e92660f505adb/app/_template/images/sign-up@2xrl.webp -------------------------------------------------------------------------------- /app/_template/images/user-button-2@2xrl.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clerk/nextjs-auth-starter-template/d0aeb1078ddfe9b189c32c4e721e92660f505adb/app/_template/images/user-button-2@2xrl.webp -------------------------------------------------------------------------------- /app/_template/images/user-button@2xrl.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clerk/nextjs-auth-starter-template/d0aeb1078ddfe9b189c32c4e721e92660f505adb/app/_template/images/user-button@2xrl.webp -------------------------------------------------------------------------------- /app/_template/images/verify@2xrl.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clerk/nextjs-auth-starter-template/d0aeb1078ddfe9b189c32c4e721e92660f505adb/app/_template/images/verify@2xrl.webp -------------------------------------------------------------------------------- /app/_template/styles/landing.css: -------------------------------------------------------------------------------- 1 | /* Template-specific landing page styles */ 2 | .landing-hero { 3 | background: #fafafa; 4 | } 5 | 6 | .landing-container { 7 | background: white; 8 | max-width: 75rem; 9 | margin: 0 auto; 10 | display: flex; 11 | flex-direction: column; 12 | border-left: 1px solid #f2f2f2; 13 | border-right: 1px solid #f2f2f2; 14 | grid-row: span 3; 15 | } 16 | 17 | .landing-divider { 18 | position: absolute; 19 | top: 0; 20 | bottom: 0; 21 | left: 50%; 22 | transform: translateX(-50%); 23 | width: 1px; 24 | background: #f2f2f2; 25 | } 26 | 27 | .landing-logo { 28 | width: 16rem; 29 | height: 16rem; 30 | background: transparent; 31 | position: absolute; 32 | left: 50%; 33 | transform: translateX(-23.75rem); 34 | top: -1.5rem; 35 | height: 51.375rem; 36 | object-fit: contain; 37 | width: 39.0625rem; 38 | } 39 | 40 | .landing-gradient { 41 | position: absolute; 42 | left: 0; 43 | right: 0; 44 | bottom: 0; 45 | height: 18.75rem; 46 | background: linear-gradient(to top, white, transparent); 47 | } 48 | -------------------------------------------------------------------------------- /app/api/protected/route.ts: -------------------------------------------------------------------------------- 1 | import { auth } from "@clerk/nextjs/server"; 2 | import { NextResponse } from "next/server"; 3 | 4 | export async function GET() { 5 | await auth.protect(); 6 | 7 | return NextResponse.json({ 8 | message: "This is a protected route", 9 | timestamp: new Date().toISOString(), 10 | }); 11 | } 12 | 13 | export async function POST() { 14 | await auth.protect(); 15 | 16 | return NextResponse.json({ 17 | message: "Protected POST endpoint accessed successfully", 18 | timestamp: new Date().toISOString(), 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /app/components/code-switcher.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useOrganization, useSession, useUser } from "@clerk/nextjs"; 4 | import clsx from "clsx"; 5 | import { useState } from "react"; 6 | import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; 7 | import theme from "./theme"; 8 | 9 | const TYPES = ["user", "session", "organization"]; 10 | 11 | export function CodeSwitcher() { 12 | const [selectedType, setSelectedType] = useState(TYPES[0]); 13 | const { user } = useUser(); 14 | const { session } = useSession(); 15 | const { organization } = useOrganization(); 16 | 17 | const selectedCode = JSON.stringify( 18 | { 19 | user, 20 | session, 21 | organization, 22 | }[selectedType], 23 | null, 24 | 2 25 | ); 26 | 27 | const typesToShow = organization 28 | ? TYPES 29 | : TYPES.filter((type) => type !== "organization"); 30 | 31 | return ( 32 |
33 |
34 | {typesToShow.map((type) => ( 35 | 47 | ))} 48 |
49 |
50 |
51 | {/* @ts-expect-error */} 52 | 53 | {selectedCode} 54 | 55 |
56 |
57 |
58 |
59 |
60 | ); 61 | } 62 | -------------------------------------------------------------------------------- /app/components/theme.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'code[class*="language-"]': { 3 | color: '#c5c8c6', 4 | fontFamily: 'var(--font-geist-mono)', 5 | direction: 'ltr', 6 | textAlign: 'left', 7 | whiteSpace: 'pre', 8 | wordSpacing: 'normal', 9 | wordBreak: 'normal', 10 | lineHeight: '1.5', 11 | MozTabSize: '4', 12 | OTabSize: '4', 13 | tabSize: '4', 14 | WebkitHyphens: 'none', 15 | MozHyphens: 'none', 16 | msHyphens: 'none', 17 | hyphens: 'none', 18 | fontSize: 12, 19 | }, 20 | 'pre[class*="language-"]': { 21 | color: '#c5c8c6', 22 | fontFamily: 'var(--font-geist-mono)', 23 | direction: 'ltr', 24 | textAlign: 'left', 25 | whiteSpace: 'pre', 26 | wordSpacing: 'normal', 27 | wordBreak: 'normal', 28 | lineHeight: '1.5', 29 | MozTabSize: '4', 30 | OTabSize: '4', 31 | tabSize: '4', 32 | WebkitHyphens: 'none', 33 | MozHyphens: 'none', 34 | msHyphens: 'none', 35 | hyphens: 'none', 36 | padding: '16px 0px 32px', 37 | margin: '.5em 0', 38 | overflow: 'auto', 39 | borderRadius: '0.3em', 40 | background: 'white', 41 | fontSize: 12, 42 | height: '100%', 43 | }, 44 | ':not(pre) > code[class*="language-"]': { 45 | background: 'white', 46 | padding: '.1em', 47 | borderRadius: '.3em', 48 | }, 49 | comment: { 50 | color: '#7C7C7C', 51 | }, 52 | prolog: { 53 | color: '#7C7C7C', 54 | }, 55 | doctype: { 56 | color: '#7C7C7C', 57 | }, 58 | cdata: { 59 | color: '#7C7C7C', 60 | }, 61 | punctuation: { 62 | color: '#c5c8c6', 63 | }, 64 | '.namespace': { 65 | Opacity: '.7', 66 | }, 67 | property: { 68 | color: '#676767', 69 | }, 70 | keyword: { 71 | color: '#676767', 72 | }, 73 | tag: { 74 | color: '#676767', 75 | }, 76 | 'class-name': { 77 | color: '#FFFFB6', 78 | textDecoration: 'underline', 79 | }, 80 | boolean: { 81 | color: '#DB3FB9', 82 | }, 83 | constant: { 84 | color: '#DB3FB9', 85 | }, 86 | symbol: { 87 | color: '#f92672', 88 | }, 89 | deleted: { 90 | color: '#f92672', 91 | }, 92 | number: { 93 | color: '#FF73FD', 94 | }, 95 | selector: { 96 | color: '#4248DA', 97 | }, 98 | 'attr-name': { 99 | color: '#4248DA', 100 | }, 101 | string: { 102 | color: '#4248DA', 103 | }, 104 | char: { 105 | color: '#4248DA', 106 | }, 107 | builtin: { 108 | color: '#4248DA', 109 | }, 110 | inserted: { 111 | color: '#4248DA', 112 | }, 113 | variable: { 114 | color: '#C6C5FE', 115 | }, 116 | operator: { 117 | color: '#EDEDED', 118 | }, 119 | entity: { 120 | color: '#FFFFB6', 121 | cursor: 'help', 122 | }, 123 | url: { 124 | color: '#676767', 125 | }, 126 | '.language-css .token.string': { 127 | color: '#C1C1C1', 128 | }, 129 | '.style .token.string': { 130 | color: '#C1C1C1', 131 | }, 132 | atrule: { 133 | color: '#F9EE98', 134 | }, 135 | 'attr-value': { 136 | color: '#F9EE98', 137 | }, 138 | function: { 139 | color: '#DAD085', 140 | }, 141 | regex: { 142 | color: '#E9C062', 143 | }, 144 | important: { 145 | color: '#fd971f', 146 | fontWeight: 'bold', 147 | }, 148 | bold: { 149 | fontWeight: 'bold', 150 | }, 151 | italic: { 152 | fontStyle: 'italic', 153 | }, 154 | }; 155 | -------------------------------------------------------------------------------- /app/components/user-details.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useOrganization, useSession, useUser } from "@clerk/nextjs"; 4 | 5 | function Row({ 6 | desc, 7 | value, 8 | children, 9 | }: { 10 | desc: string; 11 | value: string; 12 | children: React.ReactNode; 13 | }) { 14 | return ( 15 |
16 | {desc} 17 | 18 | {value} 19 | {children} 20 | 21 |
22 | ); 23 | } 24 | 25 | function PointerC({ label }: { label: string }) { 26 | return ( 27 |
28 |
29 |
30 |
31 |
32 |
33 | {label} 34 |
35 |
36 | ); 37 | } 38 | 39 | function formatDate(date: Date) { 40 | return date.toLocaleDateString("en-US", { 41 | month: "short", 42 | day: "numeric", 43 | year: "numeric", 44 | }); 45 | } 46 | 47 | function formatDateWithNumbers(date: Date): string { 48 | return date.toLocaleString("en-US", { 49 | month: "numeric", 50 | day: "numeric", 51 | year: "numeric", 52 | hour: "numeric", 53 | minute: "2-digit", 54 | second: "2-digit", 55 | hour12: true, 56 | }); 57 | } 58 | 59 | export function UserDetails() { 60 | const { user } = useUser(); 61 | const { session } = useSession(); 62 | const { organization } = useOrganization(); 63 | 64 | if (!user || !session) return null; 65 | 66 | return ( 67 |
68 |
69 |
70 |
71 | 72 |
73 |
74 |
75 |
76 |
77 |
78 | user.imageUrl 79 |
80 |
81 |
82 | {user.firstName && user.lastName ? ( 83 |

84 | {user.firstName} {user.lastName} 85 |
86 |
87 |
88 |
89 |
90 |
91 | user.firstName 92 |
93 |
94 | user.lastName 95 |
96 |
97 |

98 | ) : ( 99 |
100 | )} 101 |
102 | 103 |
104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 |
117 |

118 | Session details 119 |

120 |
121 | 122 | 123 | 124 | 125 | 126 | 127 | 131 | 132 | 133 | 137 | 138 | 139 |
140 | {organization ? ( 141 | <> 142 |

143 | Organization detail 144 |

145 |
146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 159 | 160 | 161 |
162 | 163 | ) : null} 164 |
165 |
166 | ); 167 | } 168 | -------------------------------------------------------------------------------- /app/dashboard/page.tsx: -------------------------------------------------------------------------------- 1 | import { UserDetails } from "../components/user-details"; 2 | import { UserButton } from "@clerk/nextjs"; 3 | import { auth } from "@clerk/nextjs/server"; 4 | import { CodeSwitcher } from "../components/code-switcher"; 5 | import { LearnMore } from "../_template/components/learn-more"; 6 | import { Footer } from "../_template/components/footer"; 7 | import { ClerkLogo } from "../_template/components/clerk-logo"; 8 | import { NextLogo } from "../_template/components/next-logo"; 9 | import Link from "next/link"; 10 | 11 | import { DASHBOARD_CARDS } from "../_template/content/cards"; 12 | import { DeployButton } from "../_template/components/deploy-button"; 13 | 14 | export default async function DashboardPage() { 15 | await auth.protect(); 16 | 17 | return ( 18 | <> 19 |
20 |
21 |
22 |
23 |
24 |
25 | 26 |
27 | 28 |
29 | 33 | 39 | 45 | 46 | Back to Home 47 | 48 |
49 |
50 | 57 |
58 |
59 | 60 |
61 |
62 |
63 | 64 |
65 | 66 |
67 |
68 |
69 | 70 |