Developer Guide
This guide walks you through building a first Pubky app against a local development stack. You will start a local Homeserver with Pubky Docker, create a Vite app, install the Pubky SDK, and connect your app to the local testnet.
By the end, you will have created a demo identity, signed up and signed in on the local Homeserver, written a JSON file to Pubky storage, and read it back in the browser. After that, you will also get to know the templates you can use to bootstrap your own Pubky app.
To follow along, you will need Docker and npm.
Step 1: Set Up Pubky Docker
Section titled “Step 1: Set Up Pubky Docker”In order to build our App we’ll need to setup a local homeserver and testnet - we’ll use Pubky Docker to spin up a local development environment.
Note: Pubky Docker can run a full pubky.app-compatible social stack too, but we will keep this setup minimal.
git clone https://github.com/pubky/pubky-docker.git && cd pubky-docker && cp .env-sample .envIn homeserver.config.toml set signup_mode to open. This is as opposed to requiring a signup token to signup - local setups do not need the token-based spam protection used by public Homeservers.
From the pubky-docker directory, run:
sed -i 's/^signup_mode = "token_required"/signup_mode = "open"/' homeserver.config.tomlRun the homeserver and tesnet via Docker compose:
docker compose up homeserver -dYou now have a local Pubky testnet ready for app development. An isolated DHT is running, the HTTP relay is local, and the Homeserver publishes its PKARR identity to the local DHT. This means local clients can discover your Homeserver the same way they would on the public network, but everything stays on your machine. Your testnet Homeserver’s pubky is always 8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo.
With .env set to the default NETWORK=testnet, these ports are exposed:
| Port | Service | Purpose |
|---|---|---|
15411 | PKARR relay | Used by the Pubky SDK to publish and resolve testnet PKARR records over HTTP, instead of using the Mainline DHT. |
15412 | HTTP relay | Runs the local relay used by Pubky authentication flows. |
6286 | Homeserver ICANN HTTP | Clear-text HTTP endpoint used for browser and localhost fallback. |
6287 | Homeserver PubkyTLS | Direct Pubky TLS endpoint for SDK and native clients. |
6288 | Homeserver admin HTTP | Local admin endpoint exposed by Pubky Docker. |
Optional: Build from source
For most app development, the public Docker images are enough. Build from source if you need exact control over which Pubky component versions run locally, or if you want to modify the stack itself.
To build from source, you need the Pubky component repositories. The easiest path is to let the helper script clone and prepare them for you:
./pubky-docker-cli.shThe script pulls the required repositories, lets you choose Git refs for each component, builds the images, and starts the stack. To inspect which component versions are running in your containers, use:
./list-component-versions.shSee the Pubky Docker source setup instructions for more details.
Step 2: Initialize Project with the SDK
Section titled “Step 2: Initialize Project with the SDK”What follows is a step-by-step guide to building your first Pubky app. If you prefer to start from a ready-made project, jump to the basic Pubky app template.
With the Homeserver running, clone this empty Vite template and install the Pubky SDK:
npx tiged pubky/pubky-app-templates/vite-starter pubky-hello-worldcd pubky-hello-worldnpm install && npm install @synonymdev/pubkyNPM package: @synonymdev/pubky
Other tools and platforms
If you are using another language, package manager, or framework, install the SDK like this. Dedicated guides for these will follow.
Yarn:
yarn add @synonymdev/pubkyRust (docs):
cargo add pubkyReact Native:
npm install @synonymdev/react-native-pubkycd ios && pod install # iOS onlyiOS/Android Native: See SDK Documentation for UniFFI bindings via pubky-core-ffi.
Step 3: Build Your First App
Section titled “Step 3: Build Your First App”Open src/main.ts and replace the document.querySelector('#app')!.textContent = 'Vite Starter' line with the snippets below.
3.1 Import the SDK and enable info logs
Section titled “3.1 Import the SDK and enable info logs”import { Keypair, Pubky, PublicKey, setLogLevel } from "@synonymdev/pubky";
try { setLogLevel("info");} catch (error) { console.warn( "Pubky log level must be set only once, before creating the client.", error, );}This loads the Pubky SDK and sends info logs to the browser console.
To see the logs in your browser console, make sure you have the right log level filtering configured in your browser as well.
3.2 Connect to the local testnet
Section titled “3.2 Connect to the local testnet”const pubky = Pubky.testnet();This tells the SDK to use the local testnet services started by Pubky Docker instead of the production Pubky network.
3.3 Create a new user identity
Section titled “3.3 Create a new user identity”const keypair = Keypair.random();const signer = pubky.signer(keypair);This creates a demo user identity for the hello-world app. The signer uses it to perform identity actions such as signup and signin.
3.4 Sign up on the local Homeserver
Section titled “3.4 Sign up on the local Homeserver”const homeserver = PublicKey.from( "pubky8pinxxgqs41n4aididenw5apqp1urfmzdztr8jt4abrkdn435ewo",);
await signer.signup(homeserver, null);This creates an account on the local Homeserver and publishes the user’s Homeserver mapping (PKARR). Because local signup is set to open, we pass null instead of a signup token.
Run npm run dev and open the printed URL in your browser. Look at the logs in your browser console. You should see that the signup request succeeded and that you successfully published your Homeserver configuration (= PKARR).
3.5 Sign in
Section titled “3.5 Sign in”const session = await signer.signin();This creates a Homeserver session for the demo user.
3.6 Write to Homeserver storage
Section titled “3.6 Write to Homeserver storage”const path = "/pub/hello-world/data.json";await session.storage.putJson(path, { message: "Hello Pubkyverse!" });This writes a simple JSON file onto the signed-in user’s Homeserver public storage.
3.7 Read the JSON back
Section titled “3.7 Read the JSON back”const data = await session.storage.getJson(path);document.querySelector<HTMLDivElement>("#app")!.textContent = JSON.stringify( data, null, 2,);This fetches the same JSON file from Homeserver storage and renders it in the template’s #app element, proving that signup, signin, write, and read all worked.
Run npm run dev again and open the page. You should now see the data displayed there.
Basic Pubky app template
Section titled “Basic Pubky app template”As a next step, try this template as a fuller starting point for a fresh Pubky app.
It includes a working browser app with local testnet configuration, identity creation, Homeserver signup and signin, and a Pubky auth flow. Treat it as a set of building blocks: copy the pieces your app needs, adapt the auth and storage flows, and replace the sample UI with your own experience.
npx tiged pubky/pubky-app-templates/basic-pubky-app my-pubky-appcd my-pubky-appnpm installSet a stable app ID in src/config.ts; it determines the storage path.
VITE_PUBKY_TESTNET=true npm run devHomeserver auth
Section titled “Homeserver auth”The basic app has two login paths. The right-side New identity panel is mainly a development shortcut that creates a keypair inside the app, signs up, and signs in all at once. The left-side Sign in with Pubky Ring panel is the more realistic flow: the app asks for authorization, while key management and Homeserver signup happen in a separate identity manager.
For local development, you can use the Pubky Ring Simulator as a browser-based stand-in for Pubky Ring.
The simulator is preconfigured to connect to your local testnet on localhost. Because the hosted version accesses services running on your device, your browser may ask whether pubky.github.io can access apps and services on your device or devices on your local network. Choose Allow to continue. If you prefer not to grant this permission, clone the simulator and follow its development instructions to run it locally.
- In
my-pubky-app, use the left-side Sign in with Pubky Ring panel and click Copy link. - In the simulator, select Shortcut mode and paste the link into Auth link.
- The simulator creates an identity, signs it up on your local Homeserver, then approves the request automatically.
- Switch back to
my-pubky-app. It polls the pending auth flow and signs in automatically once the simulator approves. - To test sign-in with different identities, use the Pubky Ring Simulator in Regular mode. It simulates Pubky Ring’s identity management, letting you create and select an identity before authorizing a request.
That flow is the security best practice: it keeps the user’s key material out of the application being tested. The Pubky app template receives a session after authorization, but the identity and Homeserver setup remain with the signer.
Step 4: Add Social Features
Section titled “Step 4: Add Social Features”Learn from working examples:
Social App (Pubky App Specs):
- pubky-app-specs - Data models for social features and interoperability with pubky.app
- npm: pubky-app-specs / crates.io: pubky-app-specs
Use Pubky Nexus for Social Features:
If building a social app, leverage Pubky Nexus for:
- Real-time feeds and timelines
- Search and discovery
- User recommendations
- Notifications
const response = await fetch("https://nexus.pubky.app/v0/feeds/global");const posts = await response.json();Add Payments (WIP):
Paykit protocol (work in progress) will enable:
- Payment discovery via Pubky public keys
- Public or private payment details for Bitcoin onchain, Lightning, and other rails
- Encrypted receipt access for payers
- Subscriptions and payment request workflows
Add Encryption (WIP):
Pubky Noise (work in progress) provides:
- Encrypted peer-to-peer channels
- Private messaging
- Secure data sharing
Step 5: Production Setup
Section titled “Step 5: Production Setup”To connect your app to the production Pubky network, replace the client from Step 3.2:
const pubky = Pubky.testnet();const pubky = new Pubky();new Pubky() stops using the local endpoints. The app instead resolves PKARR records from the Mainline DHT, connects to the Homeserver resolved from each user’s PKARR record, and uses a public HTTP relay for authentication.
Steps 3.3–3.5 use development-only identity and Homeserver shortcuts. For production, use Pubky Ring; the basic Pubky app template already implements that flow.
Optional: Configure custom relays
Browsers cannot query the UDP-based Mainline DHT directly, so the SDK uses HTTPS gateways called PKARR relays. See the current default relay list. To use custom PKARR relays:
const client = new Client({ pkarr: { relays: ["https://pkarr.pubky.org"], },});
const pubky = Pubky.withClient(client);PKARR relays are separate from the HTTP relay that transfers encrypted Pubky Ring authentication messages. To use a custom HTTP relay with the SDK:
const relay = "https://httprelay.example.com/inbox/";const flow = pubky.startAuthFlow( "/pub/myapp/:rw", AuthFlowKind.signin(), relay,);The basic template maps VITE_PUBKY_HTTP_RELAY to the same SDK option.
Test the Setup
Section titled “Test the Setup”- Start the production-configured app and authenticate through Pubky Ring with your production identity.
- Use the app to create some sample data.
- Enter your pubky in Pubky Explorer and verify the files created by the app.
Guides Coming Next
Section titled “Guides Coming Next”- Other languages and platforms: Build the same hello-world app with Rust, React Native, and native mobile tooling.
- Run the Homeserver natively: Start the local testnet without Docker Compose and configure local signup.
- Build social Pubky apps: Use the larger Pubky Docker stack with indexers, aggregators, and pubky.app-compatible data flows.
Next Steps
Section titled “Next Steps”- Read the docs: Pubky Core Overview
- Study the architecture: Architecture Overview
- Join the community: Telegram
- Check the FAQ: FAQ
- Review comparisons: Comparisons with other protocols
- Troubleshooting: Troubleshooting guide
Common First Questions
Section titled “Common First Questions”Q: Do users need to download Pubky Ring to use my app? A: Currently yes for secure key management, though apps can implement their own key storage. Pubky Ring provides the best UX for multi-app identity.
Q: Is Pubky compatible with Nostr/Bluesky/etc? A: Not directly. Pubky uses a different architecture (Homeservers + PKARR vs relays/PDSs). See Comparisons for details.
Q: How do I handle user authentication? A: The SDK handles it automatically via signature-based auth. No passwords, OAuth, or tokens needed. See Authentication.
Q: Can I build private apps? A: Currently Pubky is optimized for public data. Private/encrypted features are coming via Pubky Noise.
Q: How do I make money? A: Several models work: Homeserver hosting, indexing services (like Nexus), premium features, or payments via Paykit (WIP).
Resources
Section titled “Resources”Documentation
Section titled “Documentation”- Main Documentation: Complete knowledge base
- Glossary: Quick term reference
- FAQ: 63+ questions answered
- TLDR: 30-second overview
Technical
Section titled “Technical”- API Reference: HTTP API spec
- SDK Guide: Client library docs
- Rust Docs: Rust crate documentation
- Official Docs: Protocol specification
Community
Section titled “Community”- Telegram: t.me/pubkycore
- GitHub: github.com/pubky
- Live App: pubky.app