Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 11 additions & 0 deletions .changeset/canonical-dashboard-links.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@clerk/backend': patch
'@clerk/chrome-extension': patch
'@clerk/expo': patch
'@clerk/express': patch
'@clerk/shared': patch
'@clerk/ui': patch
'@clerk/upgrade': patch
---

Update Clerk Dashboard links in option descriptions, error messages, and READMEs to use the active-instance shortcut (`https://dashboard.clerk.com/~/…`) instead of the legacy `/last-active?path=…` URL.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ jobs:
- name: Check Formatting
run: pnpm format:check

- name: Check Dashboard links
run: pnpm lint:dashboard-links

- name: Verify localizations are generated
run: |
pnpm --filter @clerk/localizations generate
Expand Down
2 changes: 1 addition & 1 deletion integration/tests/next-quickstart-keyless.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ test.describe('Keyless mode @quickstart', () => {
publishableKey,
secretKey,
claimUrl: 'https://dashboard.clerk.com/apps/claim',
apiKeysUrl: 'https://dashboard.clerk.com/last-active?path=api-keys',
apiKeysUrl: 'https://dashboard.clerk.com/~/api-keys',
});
await app.keylessToEnv();
/**
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"integration:secrets": "node ./scripts/1password-keys.mjs",
"lint": "node ./scripts/lint.mjs",
"lint:attw": "FORCE_COLOR=1 turbo lint:attw",
"lint:dashboard-links": "node ./scripts/check-dashboard-links.mjs",
"lint:fix": "FORCE_COLOR=1 turbo lint -- --fix",
"lint:inspect": "pnpx @eslint/config-inspector@latest",
"lint:packages": "FORCE_COLOR=1 turbo lint",
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/tokens/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export type LoadClerkJWKFromRemoteOptions = {
*/
skipJwksCache?: boolean;
/**
* The Clerk Secret Key from the [**API keys**](https://dashboard.clerk.com/last-active?path=api-keys) page in the Clerk Dashboard.
* The Clerk Secret Key from the [**API keys**](https://dashboard.clerk.com/~/api-keys) page in the Clerk Dashboard.
*/
secretKey?: string;
/**
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/tokens/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import type { VerifyTokenOptions } from './verify';
*/
export type AuthenticateRequestOptions = {
/**
* The Clerk Publishable Key from the [**API keys**](https://dashboard.clerk.com/last-active?path=api-keys) page in the Clerk Dashboard.
* The Clerk Publishable Key from the [**API keys**](https://dashboard.clerk.com/~/api-keys) page in the Clerk Dashboard.
*/
publishableKey?: string;
/**
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/tokens/verify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export type VerifyTokenOptions = Simplify<
Omit<VerifyJwtOptions, 'key'> &
Omit<LoadClerkJWKFromRemoteOptions, 'kid'> & {
/**
* Used to verify the session token in a networkless manner. Supply the PEM public key from the **[**API keys**](https://dashboard.clerk.com/last-active?path=api-keys) page -> Show JWT public key -> PEM Public Key** section in the Clerk Dashboard. **It's recommended to use [the environment variable](https://clerk.com/docs/guides/development/clerk-environment-variables) instead.** For more information, refer to [Manual JWT verification](https://clerk.com/docs/guides/sessions/manual-jwt-verification).
* Used to verify the session token in a networkless manner. Supply the PEM public key from the **[**API keys**](https://dashboard.clerk.com/~/api-keys) page -> Show JWT public key -> PEM Public Key** section in the Clerk Dashboard. **It's recommended to use [the environment variable](https://clerk.com/docs/guides/development/clerk-environment-variables) instead.** For more information, refer to [Manual JWT verification](https://clerk.com/docs/guides/sessions/manual-jwt-verification).
*/
jwtKey?: string;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/chrome-extension/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Please see the latest extension [authentication support matrix](https://clerk.co
-d '{"allowed_origins": ["chrome-extension://<YOUR_EXTENSION_KEY>"]}'
```

4. **Set Environment Variables:** Retrieve the **Publishable key** from your [Clerk dashboard](https://dashboard.clerk.com/last-active?path=api-keys&utm_source=github&utm_medium=clerk_chrome_extension) and set it as an environment variable.
4. **Set Environment Variables:** Retrieve the **Publishable key** from your [Clerk dashboard](https://dashboard.clerk.com/~/api-keys?utm_source=github&utm_medium=clerk_chrome_extension) and set it as an environment variable.

```sh
# Vite
Expand Down
2 changes: 1 addition & 1 deletion packages/chrome-extension/docs/manifest.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,4 @@ You must enable the following host permissions in your `manifest.json` file. Thi
- Please make sure to include `/*` at the end of each `host_permission`. Feel free to later scope this down, if your usage sees fit.
- The `YOUR_PRODUCTION_APP_DOMAIN` and `YOUR_CLERK_PRODUCTION_FRONTEND_API` are only required when you're ready to go to production.

Your Frontend API URLs can be found in [Clerk Dashboard](https://dashboard.clerk.com/last-active?path=api-keys) under the **Show API URLs** option.
Your Frontend API URLs can be found in [Clerk Dashboard](https://dashboard.clerk.com/~/api-keys) under the **Show API URLs** option.
2 changes: 1 addition & 1 deletion packages/chrome-extension/src/react/ClerkProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type { StorageCache } from '../internal/utils/storage';

type ChromeExtensionClerkProviderProps = Omit<ClerkReactProviderProps, 'publishableKey'> & {
/**
* Your Clerk Publishable Key, available in the [Clerk Dashboard](https://dashboard.clerk.com/last-active?path=api-keys).
* Your Clerk Publishable Key, available in the [Clerk Dashboard](https://dashboard.clerk.com/~/api-keys).
* Required for Chrome Extensions, which cannot use `@clerk/react`'s environment-variable fallback.
*/
publishableKey: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ export function createClerkInstance(ClerkClass: typeof Clerk) {

if (__DEV__ && !nativeApiErrorShown && response.payload?.errors?.[0]?.code === 'native_api_disabled') {
console.error(
'The Native API is disabled for this instance.\nGo to Clerk Dashboard > Configure > Native applications to enable it.\nOr, navigate here: https://dashboard.clerk.com/last-active?path=native-applications',
'The Native API is disabled for this instance.\nGo to Clerk Dashboard > Configure > Native applications to enable it.\nOr, navigate here: https://dashboard.clerk.com/~/native-applications',
);
nativeApiErrorShown = true;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/express/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ npm install @clerk/express

## Usage

Navigate to the [Clerk Dashboard](https://dashboard.clerk.com/last-active?path=api-keys) and inside the **API Keys** section copy the publishable key and secret key.
Navigate to the [Clerk Dashboard](https://dashboard.clerk.com/~/api-keys) and inside the **API Keys** section copy the publishable key and secret key.

Paste your keys into an `.env` file:

Expand Down
6 changes: 3 additions & 3 deletions packages/shared/src/errors/errorThrower.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,21 @@ npx clerk@latest init

\`npx clerk@latest init\` creates a Clerk application and writes keys to your .env file. No Clerk account or login required and the command is non-interactive.

If you have a Clerk application, run \`npx clerk@latest env pull\` to write the keys (\`--instance prod\` for production keys). Or copy its Publishable key from https://dashboard.clerk.com/last-active?path=api-keys.`,
If you have a Clerk application, run \`npx clerk@latest env pull\` to write the keys (\`--instance prod\` for production keys). Or copy its Publishable key from https://dashboard.clerk.com/~/api-keys.`,
MissingPublishableKeyErrorMessage: `Missing publishableKey. To set up Clerk for this project, in your terminal run:

npx clerk@latest init

\`npx clerk@latest init\` creates a Clerk application and writes keys to your .env file. No Clerk account or login required and the command is non-interactive.

If you have a Clerk application, run \`npx clerk@latest env pull\` to write the keys. Or copy them from https://dashboard.clerk.com/last-active?path=api-keys. Deploy a production instance by running \`npx clerk@latest deploy\`, or \`npx clerk@latest env pull --instance prod\` to use an existing one.`,
If you have a Clerk application, run \`npx clerk@latest env pull\` to write the keys. Or copy them from https://dashboard.clerk.com/~/api-keys. Deploy a production instance by running \`npx clerk@latest deploy\`, or \`npx clerk@latest env pull --instance prod\` to use an existing one.`,
MissingSecretKeyErrorMessage: `Missing secretKey. To set up Clerk for this project, in your terminal run:

npx clerk@latest init

\`npx clerk@latest init\` creates a Clerk application and writes keys to your .env file. No Clerk account or login required and the command is non-interactive.

If you have a Clerk application, run \`npx clerk@latest env pull\` to write the keys. Or copy them from https://dashboard.clerk.com/last-active?path=api-keys. Deploy a production instance by running \`npx clerk@latest deploy\`, or \`npx clerk@latest env pull --instance prod\` to use an existing one.`,
If you have a Clerk application, run \`npx clerk@latest env pull\` to write the keys. Or copy them from https://dashboard.clerk.com/~/api-keys. Deploy a production instance by running \`npx clerk@latest deploy\`, or \`npx clerk@latest env pull --instance prod\` to use an existing one.`,
MissingClerkProvider: `{{source}} can only be used within the <ClerkProvider /> component. Learn more: https://clerk.com/docs/components/clerk-provider`,
});

Expand Down
2 changes: 1 addition & 1 deletion packages/shared/src/internal/clerk-js/warnings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const createCannotRenderComponentWhenPermissionIsMissing = (componentName: 'Invi

const createMessageForDisabledBilling = (componentName: 'PricingTable' | 'Checkout' | 'PlanDetails') => {
return formatWarning(
`The <${componentName}/> component cannot be rendered when billing is disabled. Visit 'https://dashboard.clerk.com/last-active?path=billing/settings' to follow the necessary steps to enable billing. Since billing is disabled, this is no-op.`,
`The <${componentName}/> component cannot be rendered when billing is disabled. Visit 'https://dashboard.clerk.com/~/billing/settings' to follow the necessary steps to enable billing. Since billing is disabled, this is no-op.`,
);
};

Expand Down
2 changes: 1 addition & 1 deletion packages/shared/src/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ npx clerk@latest init

\`npx clerk@latest init\` creates a Clerk application and writes keys to your .env file. No Clerk account or login required and the command is non-interactive.

If you have a Clerk application, run \`npx clerk@latest env pull\` to write the keys (\`--instance prod\` for production keys). Or copy them from https://dashboard.clerk.com/last-active?path=api-keys.`;
If you have a Clerk application, run \`npx clerk@latest env pull\` to write the keys (\`--instance prod\` for production keys). Or copy them from https://dashboard.clerk.com/~/api-keys.`;

export function parsePublishableKey(
key: string | undefined,
Expand Down
2 changes: 1 addition & 1 deletion packages/shared/src/types/clerk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3184,7 +3184,7 @@ export type IsomorphicClerkOptions = Without<ClerkOptions, 'isSatellite'> & {
*/
__internal_clerkUIVersion?: string;
/**
* The Clerk Publishable Key for your instance. This can be found on the [API keys](https://dashboard.clerk.com/last-active?path=api-keys) page in the Clerk Dashboard.
* The Clerk Publishable Key for your instance. This can be found on the [API keys](https://dashboard.clerk.com/~/api-keys) page in the Clerk Dashboard.
*/
publishableKey: string;
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function withLastActiveFallback(callback: () => string): string {
try {
return callback();
} catch {
return 'https://dashboard.clerk.com/last-active';
return 'https://dashboard.clerk.com/~';
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ The new version ships with improved design and UX across all of Clerk's [UI comp

The sections below contain more info on each change made to the customization ids and localization keys for reference. Regardless of how thoroughly you have reviewed the following information, we still recommend that you ensure that you have taken some time to manually look through each of your views to ensure that everything looks good still.

Also worth noting - if you are using Clerk's account portal (hosted sign in page), and would like to enable the new design there, you can do so via the "customization" tab on the [account portal page](https://dashboard.clerk.com/last-active?path=account-portal) in your dashboard. Selecting "Core 2" from the "ClerkJS Components" dropdown will enable the new designs.
Also worth noting - if you are using Clerk's account portal (hosted sign in page), and would like to enable the new design there, you can do so via the "customization" tab on the [account portal page](https://dashboard.clerk.com/~/account-portal) in your dashboard. Selecting "Core 2" from the "ClerkJS Components" dropdown will enable the new designs.
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ category: 'deprecation-removal'
matcher: 'CLERK_API_KEY'
---

The `CLERK_API_KEY` environment variable was renamed to `CLERK_SECRET_KEY`. You can visit your [Clerk dashboard](https://dashboard.clerk.com/last-active?path=api-keys) to copy/paste the new keys after choosing your framework. Make sure to update this in all environments (e.g. dev, staging, production).
The `CLERK_API_KEY` environment variable was renamed to `CLERK_SECRET_KEY`. You can visit your [Clerk dashboard](https://dashboard.clerk.com/~/api-keys) to copy/paste the new keys after choosing your framework. Make sure to update this in all environments (e.g. dev, staging, production).
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ category: 'deprecation-removal'
matcherFlags: 'm'
---

The `frontendApi` prop passed to `<ClerkProvider>` was renamed to `publishableKey`. **Note:** The values are different, so this is not just a key replacement. You can visit your [Clerk dashboard](https://dashboard.clerk.com/last-active?path=api-keys) to copy/paste the new keys after choosing your framework. Make sure to update this in all environments (e.g. dev, staging, production). [More information](/docs/deployments/overview#api-keys-and-environment-variables).
The `frontendApi` prop passed to `<ClerkProvider>` was renamed to `publishableKey`. **Note:** The values are different, so this is not just a key replacement. You can visit your [Clerk dashboard](https://dashboard.clerk.com/~/api-keys) to copy/paste the new keys after choosing your framework. Make sure to update this in all environments (e.g. dev, staging, production). [More information](/docs/deployments/overview#api-keys-and-environment-variables).
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ category: 'deprecation-removal'
matcher: 'CLERK_FRONTEND_API'
---

The `CLERK_FRONTEND_API` environment variable was renamed to `CLERK_PUBLISHABLE_KEY`. You can visit your [Clerk dashboard](https://dashboard.clerk.com/last-active?path=api-keys) to copy/paste the new keys after choosing your framework. Make sure to update this in all environments (e.g. dev, staging, production). **Note:** The values are different, so this is not just a key replacement. [More information](/docs/deployments/overview#api-keys-and-environment-variables).
The `CLERK_FRONTEND_API` environment variable was renamed to `CLERK_PUBLISHABLE_KEY`. You can visit your [Clerk dashboard](https://dashboard.clerk.com/~/api-keys) to copy/paste the new keys after choosing your framework. Make sure to update this in all environments (e.g. dev, staging, production). **Note:** The values are different, so this is not just a key replacement. [More information](/docs/deployments/overview#api-keys-and-environment-variables).
90 changes: 90 additions & 0 deletions scripts/check-dashboard-links.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/usr/bin/env node

import { execFileSync } from 'node:child_process';
import { readFile } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';

// `/last-active?path=…` is a legacy Dashboard route that still resolves, so downstream route
// validation (clerk-docs) can't tell it apart from a broken link. Ban it at the source instead.
const DASHBOARD_ORIGIN = 'https://dashboard.clerk.com';
const DASHBOARD_URL_PATTERN = /https:\/\/dashboard\.clerk\.com[^\s<>"'`)\]}*\\]*/g;
const LEGACY_PATH = '/last-active';
const IGNORED_FILES = new Set(['scripts/check-dashboard-links.mjs', 'scripts/check-dashboard-links.test.mjs']);

function trimUrl(url) {
return url.replace(/[),.;:]+$/, '');
}

function isLegacyDashboardUrl(rawUrl) {
let url;
try {
url = new URL(rawUrl);
} catch {
return false;
}
return url.origin === DASHBOARD_ORIGIN && (url.pathname === LEGACY_PATH || url.pathname === `${LEGACY_PATH}/`);
}

export function isIgnoredFile(file) {
return IGNORED_FILES.has(file) || file.startsWith('.changeset/') || /(^|\/)CHANGELOG\.md$/.test(file);
}

export function findLegacyDashboardLinks(file, content) {
const findings = [];
const lines = content.split('\n');

lines.forEach((text, index) => {
for (const match of text.matchAll(DASHBOARD_URL_PATTERN)) {
const url = trimUrl(match[0]);
if (isLegacyDashboardUrl(url)) {
findings.push({ file, line: index + 1, column: match.index + 1, url });
}
}
});

return findings;
}

export function formatLegacyLinkError({ file, line, column, url }) {
const parsed = new URL(url);
const path = parsed.searchParams.get('path');
parsed.searchParams.delete('path');
parsed.pathname = path ? `/~/${path.replace(/^\/+/, '')}` : '/~';

return `${file}:${line}:${column} ${url} → ${parsed.toString()}`;
}

async function main() {
const files = execFileSync('git', ['ls-files', '-z'], { encoding: 'utf8' })
.split('\0')
.filter(file => file && !isIgnoredFile(file));

const findings = [];
for (const file of files) {
let content;
try {
content = await readFile(file, 'utf8');
} catch {
continue;
}
if (!content.includes(`${DASHBOARD_ORIGIN}${LEGACY_PATH}`)) {
continue;
}
findings.push(...findLegacyDashboardLinks(file, content));
}

if (findings.length === 0) {
console.log('No legacy Dashboard links found.');
return;
}

console.error(`Found ${findings.length} legacy Dashboard link(s). Use the active-instance shortcut instead:\n`);
for (const finding of findings) {
console.error(` ${formatLegacyLinkError(finding)}`);
}
process.exit(1);
}

if (process.argv[1] === fileURLToPath(import.meta.url)) {
await main();
}
Loading
Loading