diff --git a/examples/user-page/.gitignore b/examples/user-page/.gitignore
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ b/examples/user-page/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/examples/user-page/index.html b/examples/user-page/index.html
new file mode 100644
index 0000000..69b426b
--- /dev/null
+++ b/examples/user-page/index.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+ Tsky - User Page Example
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/user-page/package.json b/examples/user-page/package.json
new file mode 100644
index 0000000..d138726
--- /dev/null
+++ b/examples/user-page/package.json
@@ -0,0 +1,28 @@
+{
+ "name": "examples-user-page",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc -b && vite build",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@tsky/client": "workspace:*",
+ "react": "^19.0.0",
+ "react-dom": "^19.0.0"
+ },
+ "devDependencies": {
+ "@tailwindcss/vite": "^4.0.12",
+ "@tsky/lexicons": "workspace:*",
+ "@types/react": "^19.0.10",
+ "@types/react-dom": "^19.0.4",
+ "@vitejs/plugin-react": "^4.3.4",
+ "globals": "^15.15.0",
+ "tailwindcss": "^4.0.12",
+ "typescript": "~5.7.2",
+ "typescript-eslint": "^8.24.1",
+ "vite": "^6.2.0"
+ }
+}
diff --git a/examples/user-page/public/tsky-logo.png b/examples/user-page/public/tsky-logo.png
new file mode 100644
index 0000000..0781db5
Binary files /dev/null and b/examples/user-page/public/tsky-logo.png differ
diff --git a/examples/user-page/src/App.tsx b/examples/user-page/src/App.tsx
new file mode 100644
index 0000000..8d23a57
--- /dev/null
+++ b/examples/user-page/src/App.tsx
@@ -0,0 +1,172 @@
+import { type ActorProfile, createAgent } from '@tsky/client';
+import type { At } from '@tsky/lexicons';
+import { useEffect, useState } from 'react';
+
+async function getUserProfile(identity: string) {
+ try {
+ const agent = await createAgent({
+ options: {
+ service: 'https://public.api.bsky.app',
+ },
+ });
+
+ let did = identity;
+
+ if (!did.startsWith('did:')) {
+ const _id = await agent.resolveDIDFromHandle(identity);
+ did = _id.did;
+ }
+
+ const actor = await agent.actor(did as At.DID);
+
+ return actor.profile();
+ } catch (err) {
+ console.error(err);
+ }
+}
+
+function App() {
+ const [search, setSearch] = useState();
+ const [user, setUser] = useState();
+
+ useEffect(() => {
+ if (search) {
+ getUserProfile(search).then(setUser);
+ }
+ }, [search]);
+
+ return (
+
+
+
+ {user && (
+
+

+
+
+
{user.displayName}
+
+ @{user.handle}
+
+
+
+ {user.followersCount}
+
+ {' '}
+ Followers
+
+
+
+ {user.followsCount}
+
+ {' '}
+ Following
+
+
+
+
{user.description}
+
+
+
+ )}
+
+
+ );
+}
+
+export default App;
diff --git a/examples/user-page/src/index.css b/examples/user-page/src/index.css
new file mode 100644
index 0000000..f1d8c73
--- /dev/null
+++ b/examples/user-page/src/index.css
@@ -0,0 +1 @@
+@import "tailwindcss";
diff --git a/examples/user-page/src/main.tsx b/examples/user-page/src/main.tsx
new file mode 100644
index 0000000..a0a3f66
--- /dev/null
+++ b/examples/user-page/src/main.tsx
@@ -0,0 +1,16 @@
+import { StrictMode } from 'react';
+import { createRoot } from 'react-dom/client';
+import './index.css';
+import App from './App.tsx';
+
+const root = document.getElementById('root');
+
+if (!root) {
+ throw new Error('No root element found');
+}
+
+createRoot(root).render(
+
+
+ ,
+);
diff --git a/examples/user-page/src/vite-env.d.ts b/examples/user-page/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/examples/user-page/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/examples/user-page/tsconfig.app.json b/examples/user-page/tsconfig.app.json
new file mode 100644
index 0000000..1903283
--- /dev/null
+++ b/examples/user-page/tsconfig.app.json
@@ -0,0 +1,22 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "jsx": "react-jsx",
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["src"]
+}
diff --git a/examples/user-page/tsconfig.json b/examples/user-page/tsconfig.json
new file mode 100644
index 0000000..1ffef60
--- /dev/null
+++ b/examples/user-page/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "files": [],
+ "references": [
+ { "path": "./tsconfig.app.json" },
+ { "path": "./tsconfig.node.json" }
+ ]
+}
diff --git a/examples/user-page/tsconfig.node.json b/examples/user-page/tsconfig.node.json
new file mode 100644
index 0000000..1dba6de
--- /dev/null
+++ b/examples/user-page/tsconfig.node.json
@@ -0,0 +1,20 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+ "target": "ES2022",
+ "lib": ["ES2023"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/examples/user-page/vite.config.ts b/examples/user-page/vite.config.ts
new file mode 100644
index 0000000..32faff6
--- /dev/null
+++ b/examples/user-page/vite.config.ts
@@ -0,0 +1,9 @@
+import tailwindcss from '@tailwindcss/vite';
+import react from '@vitejs/plugin-react';
+import { defineConfig } from 'vite';
+
+// https://vite.dev/config/
+export default defineConfig({
+ plugins: [react(), tailwindcss()],
+ base: '/examples/user-page/',
+});