Update your ATProto bio with what you're currently listening to

Log in to ATProto

Bryan 77d37de2 1afe50f3

Changed files
+197 -10
app
api
auth
atproto
+23
app/api/auth/atproto/route.ts
··· 1 + import AtpAgent from "@atproto/api"; 2 + import { NextRequest, NextResponse } from "next/server"; 3 + 4 + export async function POST(request: NextRequest) { 5 + try { 6 + const { hostingProvider, identifier, password } = await request.json(); 7 + const hostingProviderURL = hostingProvider || "https://bsky.social"; 8 + const agent = new AtpAgent({ service: hostingProviderURL }); 9 + 10 + await agent.login({ identifier, password }); 11 + 12 + return NextResponse.json({ 13 + did: agent.session?.did, 14 + handle: agent.session?.handle, 15 + success: true 16 + }); 17 + } catch (error) { 18 + return NextResponse.json( 19 + { error: error.message, success: false }, 20 + { status: 401 } 21 + ); 22 + } 23 + }
+26 -3
app/page.tsx
··· 8 8 const [atProtoIdentifier, setAtProtoIdentifier] = useState(""); 9 9 const [currentPlaying, setCurrentPlaying] = useState(""); 10 10 const [hostingProvider, setHostingProvider] = useState(""); 11 + const [isLoggingIn, setIsLoggingIn] = useState(false); 11 12 const [lastFMUsername, setLastFMUsername] = useState(""); 12 13 const [password, setPassword] = useState(""); 13 14 const [usernameInput, setUsernameInput] = useState(""); 14 15 16 + const loginToATProto = async () => { 17 + setIsLoggingIn(true); 18 + 19 + try { 20 + const response = await fetch("/api/auth/atproto", { 21 + body: JSON.stringify({ 22 + hostingProvide: hostingProvider || "https://bsky.social", 23 + identifier: atProtoIdentifier, 24 + password 25 + }), 26 + headers: { "Content-Type": "application/json" }, 27 + method: "POST" 28 + }); 29 + const data = await response.json(); 30 + 31 + console.log(data); 32 + } catch (error) { 33 + } finally { 34 + setIsLoggingIn(false); 35 + } 36 + }; 37 + 15 38 const scp = async () => { 16 39 const response = await fetch(`/api/lastfm?username=${usernameInput}`); 17 40 const data = await response.json(); ··· 19 42 setLastFMUsername(usernameInput); 20 43 setUsernameInput(""); 21 44 22 - console.log(data) 45 + console.log(data); 23 46 24 47 const mostRecentlyScrobbledTrack = data?.recenttracks?.track?.[0]; 25 48 ··· 83 106 /> 84 107 </div> 85 108 <Button 86 - label="Log In" 87 - onClick={async () => {}} 109 + label={isLoggingIn ? "Logging In..." : "Log In"} 110 + onClick={loginToATProto} 88 111 width="w-1/2" 89 112 /> 90 113 </div>
+140 -1
package-lock.json
··· 8 8 "name": "scrobbletobio", 9 9 "version": "0.1.0", 10 10 "dependencies": { 11 + "@atproto/api": "^0.17.7", 12 + "lucide-react": "^0.548.0", 11 13 "next": "16.0.1", 12 14 "react": "19.2.0", 13 15 "react-dom": "19.2.0" ··· 36 38 "url": "https://github.com/sponsors/sindresorhus" 37 39 } 38 40 }, 41 + "node_modules/@atproto/api": { 42 + "version": "0.17.7", 43 + "resolved": "https://registry.npmjs.org/@atproto/api/-/api-0.17.7.tgz", 44 + "integrity": "sha512-V+OJBZq9chcrD21xk1bUa6oc5DSKfQj5DmUPf5rmZncqL1w9ZEbS38H5cMyqqdhfgo2LWeDRdZHD0rvNyJsIaw==", 45 + "license": "MIT", 46 + "dependencies": { 47 + "@atproto/common-web": "^0.4.3", 48 + "@atproto/lexicon": "^0.5.1", 49 + "@atproto/syntax": "^0.4.1", 50 + "@atproto/xrpc": "^0.7.5", 51 + "await-lock": "^2.2.2", 52 + "multiformats": "^9.9.0", 53 + "tlds": "^1.234.0", 54 + "zod": "^3.23.8" 55 + } 56 + }, 57 + "node_modules/@atproto/api/node_modules/zod": { 58 + "version": "3.25.76", 59 + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", 60 + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", 61 + "license": "MIT", 62 + "funding": { 63 + "url": "https://github.com/sponsors/colinhacks" 64 + } 65 + }, 66 + "node_modules/@atproto/common-web": { 67 + "version": "0.4.3", 68 + "resolved": "https://registry.npmjs.org/@atproto/common-web/-/common-web-0.4.3.tgz", 69 + "integrity": "sha512-nRDINmSe4VycJzPo6fP/hEltBcULFxt9Kw7fQk6405FyAWZiTluYHlXOnU7GkQfeUK44OENG1qFTBcmCJ7e8pg==", 70 + "license": "MIT", 71 + "dependencies": { 72 + "graphemer": "^1.4.0", 73 + "multiformats": "^9.9.0", 74 + "uint8arrays": "3.0.0", 75 + "zod": "^3.23.8" 76 + } 77 + }, 78 + "node_modules/@atproto/common-web/node_modules/zod": { 79 + "version": "3.25.76", 80 + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", 81 + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", 82 + "license": "MIT", 83 + "funding": { 84 + "url": "https://github.com/sponsors/colinhacks" 85 + } 86 + }, 87 + "node_modules/@atproto/lexicon": { 88 + "version": "0.5.1", 89 + "resolved": "https://registry.npmjs.org/@atproto/lexicon/-/lexicon-0.5.1.tgz", 90 + "integrity": "sha512-y8AEtYmfgVl4fqFxqXAeGvhesiGkxiy3CWoJIfsFDDdTlZUC8DFnZrYhcqkIop3OlCkkljvpSJi1hbeC1tbi8A==", 91 + "license": "MIT", 92 + "dependencies": { 93 + "@atproto/common-web": "^0.4.3", 94 + "@atproto/syntax": "^0.4.1", 95 + "iso-datestring-validator": "^2.2.2", 96 + "multiformats": "^9.9.0", 97 + "zod": "^3.23.8" 98 + } 99 + }, 100 + "node_modules/@atproto/lexicon/node_modules/zod": { 101 + "version": "3.25.76", 102 + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", 103 + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", 104 + "license": "MIT", 105 + "funding": { 106 + "url": "https://github.com/sponsors/colinhacks" 107 + } 108 + }, 109 + "node_modules/@atproto/syntax": { 110 + "version": "0.4.1", 111 + "resolved": "https://registry.npmjs.org/@atproto/syntax/-/syntax-0.4.1.tgz", 112 + "integrity": "sha512-CJdImtLAiFO+0z3BWTtxwk6aY5w4t8orHTMVJgkf++QRJWTxPbIFko/0hrkADB7n2EruDxDSeAgfUGehpH6ngw==", 113 + "license": "MIT" 114 + }, 115 + "node_modules/@atproto/xrpc": { 116 + "version": "0.7.5", 117 + "resolved": "https://registry.npmjs.org/@atproto/xrpc/-/xrpc-0.7.5.tgz", 118 + "integrity": "sha512-MUYNn5d2hv8yVegRL0ccHvTHAVj5JSnW07bkbiaz96UH45lvYNRVwt44z+yYVnb0/mvBzyD3/ZQ55TRGt7fHkA==", 119 + "license": "MIT", 120 + "dependencies": { 121 + "@atproto/lexicon": "^0.5.1", 122 + "zod": "^3.23.8" 123 + } 124 + }, 125 + "node_modules/@atproto/xrpc/node_modules/zod": { 126 + "version": "3.25.76", 127 + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", 128 + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", 129 + "license": "MIT", 130 + "funding": { 131 + "url": "https://github.com/sponsors/colinhacks" 132 + } 133 + }, 39 134 "node_modules/@babel/code-frame": { 40 135 "version": "7.27.1", 41 136 "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", ··· 2399 2494 "url": "https://github.com/sponsors/ljharb" 2400 2495 } 2401 2496 }, 2497 + "node_modules/await-lock": { 2498 + "version": "2.2.2", 2499 + "resolved": "https://registry.npmjs.org/await-lock/-/await-lock-2.2.2.tgz", 2500 + "integrity": "sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==", 2501 + "license": "MIT" 2502 + }, 2402 2503 "node_modules/axe-core": { 2403 2504 "version": "4.11.0", 2404 2505 "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.0.tgz", ··· 3804 3905 "version": "1.4.0", 3805 3906 "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", 3806 3907 "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", 3807 - "dev": true, 3808 3908 "license": "MIT" 3809 3909 }, 3810 3910 "node_modules/has-bigints": { ··· 4399 4499 "dev": true, 4400 4500 "license": "ISC" 4401 4501 }, 4502 + "node_modules/iso-datestring-validator": { 4503 + "version": "2.2.2", 4504 + "resolved": "https://registry.npmjs.org/iso-datestring-validator/-/iso-datestring-validator-2.2.2.tgz", 4505 + "integrity": "sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==", 4506 + "license": "MIT" 4507 + }, 4402 4508 "node_modules/iterator.prototype": { 4403 4509 "version": "1.1.5", 4404 4510 "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", ··· 4861 4967 "yallist": "^3.0.2" 4862 4968 } 4863 4969 }, 4970 + "node_modules/lucide-react": { 4971 + "version": "0.548.0", 4972 + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.548.0.tgz", 4973 + "integrity": "sha512-63b16z63jM9yc1MwxajHeuu0FRZFsDtljtDjYm26Kd86UQ5HQzu9ksEtoUUw4RBuewodw/tGFmvipePvRsKeDA==", 4974 + "license": "ISC", 4975 + "peerDependencies": { 4976 + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" 4977 + } 4978 + }, 4864 4979 "node_modules/magic-string": { 4865 4980 "version": "0.30.21", 4866 4981 "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", ··· 4934 5049 "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 4935 5050 "dev": true, 4936 5051 "license": "MIT" 5052 + }, 5053 + "node_modules/multiformats": { 5054 + "version": "9.9.0", 5055 + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", 5056 + "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==", 5057 + "license": "(Apache-2.0 AND MIT)" 4937 5058 }, 4938 5059 "node_modules/nanoid": { 4939 5060 "version": "3.3.11", ··· 6112 6233 "url": "https://github.com/sponsors/jonschlinkert" 6113 6234 } 6114 6235 }, 6236 + "node_modules/tlds": { 6237 + "version": "1.261.0", 6238 + "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.261.0.tgz", 6239 + "integrity": "sha512-QXqwfEl9ddlGBaRFXIvNKK6OhipSiLXuRuLJX5DErz0o0Q0rYxulWLdFryTkV5PkdZct5iMInwYEGe/eR++1AA==", 6240 + "license": "MIT", 6241 + "bin": { 6242 + "tlds": "bin.js" 6243 + } 6244 + }, 6115 6245 "node_modules/to-regex-range": { 6116 6246 "version": "5.0.1", 6117 6247 "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", ··· 6297 6427 "peerDependencies": { 6298 6428 "eslint": "^8.57.0 || ^9.0.0", 6299 6429 "typescript": ">=4.8.4 <6.0.0" 6430 + } 6431 + }, 6432 + "node_modules/uint8arrays": { 6433 + "version": "3.0.0", 6434 + "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", 6435 + "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", 6436 + "license": "MIT", 6437 + "dependencies": { 6438 + "multiformats": "^9.4.2" 6300 6439 } 6301 6440 }, 6302 6441 "node_modules/unbox-primitive": {
+8 -6
package.json
··· 9 9 "lint": "eslint" 10 10 }, 11 11 "dependencies": { 12 + "@atproto/api": "^0.17.7", 13 + "lucide-react": "^0.548.0", 14 + "next": "16.0.1", 12 15 "react": "19.2.0", 13 - "react-dom": "19.2.0", 14 - "next": "16.0.1" 16 + "react-dom": "19.2.0" 15 17 }, 16 18 "devDependencies": { 17 - "typescript": "^5", 19 + "@tailwindcss/postcss": "^4", 18 20 "@types/node": "^20", 19 21 "@types/react": "^19", 20 22 "@types/react-dom": "^19", 21 - "@tailwindcss/postcss": "^4", 23 + "eslint": "^9", 24 + "eslint-config-next": "16.0.1", 22 25 "tailwindcss": "^4", 23 - "eslint": "^9", 24 - "eslint-config-next": "16.0.1" 26 + "typescript": "^5" 25 27 } 26 28 }