ATlast — you'll never need to find your favorites on another platform again. Find your favs in the ATmosphere.
atproto
1import { generateKeyPair, exportJWK, exportPKCS8 } from "jose";
2import { writeFileSync } from "fs";
3
4async function generateKeys() {
5 // Generate ES256 key pair (recommended by atproto)
6 const { publicKey, privateKey } = await generateKeyPair("ES256", {
7 extractable: true,
8 });
9
10 // Export public key as JWK (for client-metadata.json)
11 const publicJWK = await exportJWK(publicKey);
12 publicJWK.kid = "main-key"; // Key ID
13 publicJWK.use = "sig"; // Signature use
14 publicJWK.alg = "ES256";
15
16 // Export private key as PKCS8 (for environment variable)
17 const privateKeyPem = await exportPKCS8(privateKey);
18
19 console.log("\n=== PUBLIC KEY (JWK) ===");
20 console.log("Add this to your client-metadata.json jwks.keys array:");
21 console.log(JSON.stringify(publicJWK, null, 2));
22
23 console.log("\n=== PRIVATE KEY (PEM) ===");
24 console.log(
25 "Add this to Netlify environment variables as OAUTH_PRIVATE_KEY:",
26 );
27 console.log(privateKeyPem);
28
29 // Save to files for reference
30 writeFileSync("public-jwk.json", JSON.stringify(publicJWK, null, 2));
31 writeFileSync("private-key.pem", privateKeyPem);
32
33 console.log("\n✅ Keys saved to public-jwk.json and private-key.pem");
34 console.log("⚠️ Keep private-key.pem SECRET! Add it to .gitignore");
35}
36
37generateKeys().catch(console.error);