Skip to content

Commit 755ba24

Browse files
authored
Update the browser extension playground (clerk#5080)
1 parent 093f557 commit 755ba24

21 files changed

+255
-98
lines changed

.changeset/fair-pianos-provide.md

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
---
2+
---

playground/browser-extension/README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ After following the quickstart you'll have learned how to:
3232
Run the development server:
3333
```bash
3434
> cd playground/browser-extension
35+
> n 18.17
3536
> npm i
36-
> npm dev
37+
> npm run dev
3738
```
3839

3940
In a separate terminal, build and publish the development package to your local registry:

playground/browser-extension/package.json

+6-2
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,30 @@
1313
"dev": "plasmo dev",
1414
"dev:firefox": "plasmo dev --target=firefox-mv2",
1515
"start:firefox": "web-ext run --source-dir ./build/firefox-mv2-dev",
16-
"yalc:add": "pnpm yalc add @clerk/chrome-extension"
16+
"yalc:add": "pnpm yalc add @clerk/chrome-extension @clerk/clerk-js"
1717
},
1818
"dependencies": {
1919
"@clerk/chrome-extension": "file:.yalc/@clerk/chrome-extension",
20+
"@radix-ui/react-slot": "^1.1.0",
21+
"class-variance-authority": "^0.7.0",
22+
"clsx": "^2.1.1",
2023
"plasmo": "0.89.4",
2124
"react": "^18.3.1",
2225
"react-dom": "^18.3.1",
2326
"react-router-dom": "^6.27.0",
27+
"tailwind-merge": "^2.5.4",
2428
"tailwindcss": "3.4.14",
2529
"webextension-polyfill": "^0.12.0"
2630
},
2731
"devDependencies": {
32+
"@ianvs/prettier-plugin-sort-imports": "4.1.1",
2833
"@types/chrome": "0.0.280",
2934
"@types/node": "20.16.14",
3035
"@types/react": "18.3.12",
3136
"@types/react-dom": "18.3.1",
3237
"@types/webextension-polyfill": "^0.12.1",
3338
"postcss": "8.4.49",
3439
"prettier": "3.3.3",
35-
"prettier-plugin-tailwindcss": "^0.6.8",
3640
"typescript": "5.6.3"
3741
},
3842
"manifest": {
Loading
Loading
4.62 KB
Loading
Loading
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,44 @@
11
import { createClerkClient } from '@clerk/chrome-extension/background';
22

3-
console.log('Background Script w/ Clerk createClerkClient() demo loaded');
3+
console.log('[Service Worker]: Loaded')
44

5-
const publishableKey = process.env.PLASMO_PUBLIC_CLERK_PUBLISHABLE_KEY;
5+
const publishableKey = process.env.PLASMO_PUBLIC_CLERK_PUBLISHABLE_KEY
66
if (!publishableKey) {
7-
throw new Error('Please add the PLASMO_PUBLIC_CLERK_PUBLISHABLE_KEY to the .env.development file');
7+
throw new Error('Please add the PLASMO_PUBLIC_CLERK_PUBLISHABLE_KEY to the .env.development file')
88
}
99

1010
async function getToken() {
1111
const clerk = await createClerkClient({
1212
publishableKey,
13-
syncHost: process.env.PLASMO_PUBLIC_CLERK_SYNC_HOST,
13+
syncHost: process.env.PLASMO_PUBLIC_CLERK_SYNC_HOST
1414
});
1515

16+
// is there is no signed in user then return null
1617
if (!clerk.session) {
1718
return null;
1819
}
1920

20-
return await clerk.session?.getToken();
21+
const token = await clerk.session?.getToken();
22+
return `${token} - ${clerk.user.id}`
2123
}
22-
24+
// asdf
2325
// create a listener to listen for messages from content scripts
2426
// NOTE: A runtime listener cannot be async.
2527
// It must return true, in order to keep the connection open and send a response later.
2628
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
27-
if (request.greeting === 'get-token') {
28-
console.log("Handling request for the user's current token");
29-
getToken()
30-
.then(token => sendResponse({ token }))
31-
.catch(error => console.error(JSON.stringify(error)));
32-
}
29+
console.log('[Service Worker]: Handling request for the user\'s current token')
30+
getToken()
31+
.then((token) => {
32+
console.log('[Service Worker]: Sending token in response')
33+
console.log('[Service Worker]:', token)
34+
sendResponse({ token })
35+
})
36+
.catch((error) => {
37+
console.error('[Service Worker]: Error occured -> ', JSON.stringify(error))
38+
// Send `null` when there is no authenticated user
39+
sendResponse({ token: null })
40+
});
3341
return true;
3442
});
43+
44+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { SignedIn, SignedOut, UserButton } from "@clerk/chrome-extension"
2+
import { Link } from "react-router-dom"
3+
import { Button } from "./ui/button"
4+
5+
export const NavBar = () => {
6+
return (
7+
<>
8+
<SignedIn>
9+
<div className="plasmo-flex plasmo-flex-row plasmo-w-full plasmo-items-center plasmo-bg-gray-800 plasmo-border-t plasmo-border-t-gray-600 plasmo-py-2">
10+
<Button variant="link" asChild>
11+
<Link to="/" className="plasmo-mx-2">Home</Link>
12+
</Button>
13+
<Button variant="link" asChild className="plasmo-mx-2">
14+
<Link to="/sdk-features">SDK Features</Link>
15+
</Button>
16+
<div className="plasmo-grow plasmo-items-center plasmo-justify-end plasmo-flex plasmo-pr-2">
17+
<Button variant="link" asChild className="plasmo-mx-2">
18+
<Link to="/settings">Settings</Link>
19+
</Button>
20+
<UserButton />
21+
</div>
22+
</div>
23+
</SignedIn>
24+
<SignedOut>
25+
<div className="plasmo-flex plasmo-flex-row plasmo-w-full plasmo-items-center plasmo-bg-gray-800 plasmo-border-t plasmo-border-t-gray-600 plasmo-py-2">
26+
<Button variant="link" asChild>
27+
<Link to="/">Home</Link>
28+
</Button>
29+
<div className="plasmo-grow plasmo-items-center plasmo-justify-end plasmo-flex plasmo-pr-2">
30+
31+
<Button variant="link" asChild className="plasmo-mx-2">
32+
<Link to="/sign-in">Sign In</Link>
33+
</Button>
34+
<Button variant="link" asChild className="plasmo-mx-2">
35+
36+
<Link to="/sign-up">Sign Up</Link>
37+
</Button>
38+
</div>
39+
</div>
40+
</SignedOut>
41+
42+
</>
43+
)
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import * as React from 'react'
2+
import { Slot } from '@radix-ui/react-slot'
3+
import { cva, type VariantProps } from 'class-variance-authority'
4+
import { cn } from '~utils/components';
5+
6+
7+
const buttonVariants = cva(
8+
'plasmo-inline-flex plasmo-items-center plasmo-justify-center plasmo-rounded-md plasmo-text-sm plasmo-font-medium plasmo-ring-offset-background plasmo-transition-colors focus-visible:plasmo-outline-none focus-visible:plasmo-ring-2 focus-visible:plasmo-ring-ring focus-visible:plasmo-ring-offset-2 disabled:plasmo-pointer-events-none disabled:plasmo-opacity-50',
9+
{
10+
variants: {
11+
variant: {
12+
default: 'plasmo-bg-gray-200 plasmo-text-gray-700 hover:plasmo-bg-gray-200/90',
13+
destructive:
14+
'plasmo-bg-red-600 plasmo-text-white hover:plasmo-bg-red-600/90',
15+
outline:
16+
'plasmo-border plasmo-border-input plasmo-bg-background hover:plasmo-bg-accent hover:plasmo-text-accent-foreground',
17+
secondary:
18+
'plasmo-bg-secondary plasmo-text-secondary-foreground hover:plasmo-bg-secondary/80',
19+
ghost: 'hover:plasmo-bg-accent hover:plasmo-text-accent-foreground',
20+
link: 'plasmo-text-gray-200 plasmo-underline-offset-4 hover:plasmo-underline',
21+
},
22+
size: {
23+
default: 'plasmo-h-10 plasmo-px-4 plasmo-py-2',
24+
sm: 'plasmo-h-9 plasmo-rounded-md plasmo-px-3',
25+
lg: 'plasmo-h-11 plasmo-rounded-md plasmo-px-8',
26+
icon: 'plasmo-h-10 plasmo-w-10',
27+
},
28+
},
29+
defaultVariants: {
30+
variant: 'default',
31+
size: 'default',
32+
},
33+
},
34+
);
35+
36+
export interface ButtonProps
37+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
38+
VariantProps<typeof buttonVariants> {
39+
asChild?: boolean
40+
}
41+
42+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
43+
({ className, variant, size, asChild = false, ...props }, ref) => {
44+
const Comp = asChild ? Slot : 'button'
45+
return (
46+
<Comp
47+
className={cn(buttonVariants({ variant, size, className }))}
48+
ref={ref}
49+
{...props}
50+
/>
51+
)
52+
},
53+
)
54+
Button.displayName = 'Button'
55+
56+
export { Button, buttonVariants }
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,38 @@
1-
import '../style.css';
2-
import { RouterProvider, createMemoryRouter } from 'react-router-dom';
1+
2+
import "../style.css";
3+
import { RouterProvider, createMemoryRouter } from "react-router-dom";
34

45
// Import the layouts
5-
import { RootLayout } from './layouts/root-layout';
6+
import { RootLayout } from "./layouts/root-layout";
67

78
// Import the components
8-
import { SignInPage } from './routes/sign-in';
9-
import { SignUpPage } from './routes/sign-up';
10-
import { Index } from './routes';
11-
import { Settings } from './routes/settings';
12-
import { SDKFeatures } from './routes/sdk-features';
9+
import { SignInPage } from "./routes/sign-in";
10+
import { SignUpPage } from "./routes/sign-up";
11+
import { Settings } from "./routes/settings";
12+
import { SDKFeatures } from "./routes/sdk-features";
13+
import { Home } from "./routes/home";
1314

1415
// Create the router
1516
// This removes the need for an App.tsx file
1617
const router = createMemoryRouter([
1718
{
1819
element: <RootLayout />,
1920
children: [
20-
{ path: '/', element: <Index /> },
21-
{ path: '/sign-in', element: <SignInPage /> },
22-
{ path: '/sign-up', element: <SignUpPage /> },
23-
{ path: '/settings', element: <Settings /> },
24-
{ path: '/sdk-features', element: <SDKFeatures /> },
21+
{ path: "/", element: <Home /> },
22+
{ path: "/sign-in", element: <SignInPage /> },
23+
{ path: "/sign-up", element: <SignUpPage /> },
24+
{ path: "/settings", element: <Settings /> },
25+
{ path: "/sdk-features", element: <SDKFeatures /> }
2526
],
2627
},
27-
]);
28+
], {
29+
future: {
30+
v7_relativeSplatPath: true
31+
}
32+
});
2833

2934
export default function PopupIndex() {
30-
return <RouterProvider router={router} />;
35+
return (
36+
<RouterProvider router={router} future={{ v7_startTransition: true }} />
37+
)
3138
}

playground/browser-extension/src/popup/layouts/root-layout.tsx

+15-26
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,33 @@
1-
import { ClerkProvider, SignedIn, SignedOut, UserButton } from '@clerk/chrome-extension';
2-
import { Link, Outlet, useNavigate } from 'react-router-dom';
1+
import { Outlet, useNavigate } from "react-router-dom";
2+
import { ClerkProvider } from "@clerk/chrome-extension";
3+
import { NavBar } from "~components/nav-bar";
34

4-
const PUBLISHABLE_KEY = process.env.PLASMO_PUBLIC_CLERK_PUBLISHABLE_KEY;
5-
const SYNC_HOST = process.env.PLASMO_PUBLIC_CLERK_SYNC_HOST;
5+
const PUBLISHABLE_KEY = process.env.PLASMO_PUBLIC_CLERK_PUBLISHABLE_KEY
6+
const SYNC_HOST = process.env.PLASMO_PUBLIC_CLERK_SYNC_HOST
67

7-
if (!PUBLISHABLE_KEY) {
8-
throw new Error('Please add the PLASMO_PUBLIC_CLERK_PUBLISHABLE_KEY to the .env.development file');
9-
}
10-
11-
if (!SYNC_HOST) {
12-
console.warn('Initialized without PLASMO_PUBLIC_CLERK_SYNC_HOST');
8+
if (!PUBLISHABLE_KEY || !SYNC_HOST) {
9+
throw new Error('Please add the PLASMO_PUBLIC_CLERK_PUBLISHABLE_KEY and PLASMO_PUBLIC_CLERK_SYNC_HOST to the .env.development file')
1310
}
1411

1512
export const RootLayout = () => {
1613
const navigate = useNavigate();
1714

1815
return (
1916
<ClerkProvider
20-
routerPush={to => navigate(to)}
21-
routerReplace={to => navigate(to, { replace: true })}
17+
routerPush={(to) => navigate(to)}
18+
routerReplace={(to) => navigate(to, { replace: true })}
2219
publishableKey={PUBLISHABLE_KEY}
23-
afterSignOutUrl='/'
20+
afterSignOutUrl="/"
2421
syncHost={SYNC_HOST}
22+
debug
2523
__experimental_syncHostListener
2624
>
27-
<div className='plasmo-w-[785px] plasmo-h-[600px] plasmo-flex plasmo-flex-col'>
28-
<main className='plasmo-grow plasmo-border-2 plasmo-border-red-500'>
25+
<div className="plasmo-w-[785px] plasmo-h-[600px] plasmo-flex plasmo-flex-col plasmo-bg-black plasmo-text-white">
26+
<main className="plasmo-grow plasmo-h-[543px]">
2927
<Outlet />
3028
</main>
31-
<footer className='plasmo-border-2 plasmo-border-green-500'>
32-
<SignedIn>
33-
<Link to='/sdk-features'>SDK Features</Link>
34-
<Link to='/settings'>Settings</Link>
35-
<UserButton />
36-
</SignedIn>
37-
<SignedOut>
38-
<Link to='/'>Home</Link>
39-
<Link to='/sign-in'>Sign In</Link>
40-
<Link to='/sign-up'>Sign Up</Link>
41-
</SignedOut>
29+
<footer className="plasmo-fixed plasmo-bottom-0 plasmo-w-full">
30+
<NavBar />
4231
</footer>
4332
</div>
4433
</ClerkProvider>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import heroIamge from "data-base64:~assets/light-logo.png"
2+
3+
export const Home = () => {
4+
return (
5+
<div className="plasmo-flex plasmo-flex-col plasmo-items-center plasmo-justify-center plasmo-h-full plasmo-bg-black plasmo-text-white">
6+
<img className="plasmo-h-auto plasmo-mb-8" src={heroIamge} alt="Clerk Chrome Extension SDK 2.0" />
7+
<h1 className="plasmo-text-2xl plasmo-font-semibold">Clerk Chrome Extension Demo</h1>
8+
<p className="plasmo-text-[16px] plasmo-mx-20 plasmo-my-4">
9+
Sign in with the popup or sync your auth state with <a className="plasmo-underline" href="http://localhost:5173">http://localhost:5173</a>, explore an extension built with React Router for tabs and get a token from a tab-based content script using the new <a className="plasmo-underline" href="https://clerk.com/docs/references/chrome-extension/create-clerk-client">createClerkClient()</a> function just for service workers.
10+
</p>
11+
</div>
12+
);
13+
};

playground/browser-extension/src/popup/routes/index.tsx

-7
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
1+
import { Button } from "~components/ui/button"
2+
13
export const SDKFeatures = () => {
24
return (
3-
<>
4-
<p>Background Worker</p>
5-
<button
5+
<div className="plasmo-px-12 plasmo-pt-6 plasmo-pb-4">
6+
<h1 className="plasmo-text-2xl plasmo-mb-6">Background Service Worker Support</h1>
7+
<p className="plasmo-text-lg plasmo-py-2">The @clerk/chrome-extension v2.0 SDK now includes support for interacting with Clerk through a Background Service Worker.</p>
8+
<p className="plasmo-text-lg plasmo-py-2">v2.0 of the SDK introduces the new `createClerkClient()` helper function. This will also the Background Service Worker to initialize a new Clerk instance and attempt to refresh the user's session.</p>
9+
<p className="plasmo-text-lg plasmo-py-2">Once done, you can then get a token or interact with many of Clerk's <a className="plasmo-underline plasmo-cursor-pointer" onClick={() => chrome.tabs.create({ url: "https://clerk.com/docs/references/javascript/overview" })}>Javascript</a> functonality.</p>
10+
<p className="plasmo-text-lg plasmo-py-2">The button below will open a new tab and use a content script to send a message to a Background Servie Worker. Since you are signed in, you will end up seeing your session token displayed.</p>
11+
<Button
12+
variant="default"
13+
className="plasmo-mt-4 plasmo-text-xl"
614
onClick={() => {
715
chrome.tabs.create({
816
url: "./tabs/background-worker-demo.html"
917
})
1018
}}>
11-
open tab page
12-
</button>
19+
Open Demo Tab
20+
</Button>
1321

14-
</>
22+
</div>
1523
)
1624
}

playground/browser-extension/src/popup/routes/settings.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export const Settings = () => {
44
return (
55
<>
66
<h1>Settings</h1>
7-
<UserProfile routing="virtual" />
7+
<UserProfile />
88
</>
99
);
1010
};

0 commit comments

Comments
 (0)