// @jsx h // @jsxImportSource preact import eveApiExample from "../highlight/eve-api-example.ts" with { type: "text" }; import subscriptionExamples from "../highlight/subscription-examples.ts" with { type: "text" }; import websocketExample from "../highlight/websocket-example.ts" with { type: "text" }; import { useSyntaxHighlighting } from "../hooks/useSyntaxHighlighting.js"; import { CodeBlock } from "./CodeBlock.jsx"; /** * API Section - Comprehensive guide to available APIs * Covers window.eve API and WebSocket alternatives */ export const APISection = () => { useSyntaxHighlighting(); return (
Your Arxlet has access to powerful APIs that let you interact with Nostr data, manage user profiles, and create real-time applications. Think of these APIs as your toolkit for building social, decentralized applications within the CCN ecosystem.
Two approaches available: You can use the convenient window.eve
API
(recommended for most cases) or connect directly via WebSocket for advanced scenarios. Both give you full
access to Nostr events and CCN features.
Best for most Arxlets. This high-level API handles all the complex Nostr protocol details for you.
For advanced use cases. Direct connection to the Nostr relay with full protocol control.
window.eve
for your first Arxlet. You can
always switch to WebSocket later if you need more control or performance.
The window.eve
API is your primary interface for working with Nostr data in Arxlets. It
provides simple, promise-based functions that handle all the complex protocol details behind the scenes.
How it works: Each function communicates with the local Nostr relay, processes the results, and returns clean JavaScript objects. No need to understand Nostr protocol internals - just call the functions and get your data.
Publishes a Nostr event to the relay. This is how you save data, post messages, or create any content.
Use cases: Posting messages, saving user preferences, creating notes, updating profiles
Signs an unsigned Nostr event with the user's private key. Required before publishing most events.
Use cases: Preparing events for publication, authenticating user actions
Retrieves a specific event when you know its exact ID. Perfect for loading specific posts or data.
Use cases: Loading a specific message, fetching referenced content, getting event details
Gets the first event matching your criteria. Useful when you expect only one result or want the most recent.
Use cases: Getting a user's latest profile, finding the most recent post, checking if something exists
Gets all events matching your criteria. Use this for lists, feeds, or when you need multiple results.
Use cases: Building feeds, loading message history, getting all posts by a user
Creates a live stream of events matching your filter. Your app updates automatically when new events arrive.
Use cases: Live chat, real-time feeds, notifications, collaborative features
Watches for profile changes for a specific user. Updates automatically when they change their name, bio, avatar, etc.
Use cases: User profile displays, contact lists, member directories
Retrieves user profile information (name, bio, avatar, etc.) for any user by their public key.
Use cases: Displaying user info, building contact lists, showing message authors
Quick helper to get just the avatar URL from a user's profile. Saves you from parsing the full profile.
Use cases: Profile pictures, user avatars in lists, message author images
Gets the current user's public key. This identifies the user and is needed for many operations.
Use cases: Identifying the current user, filtering their content, permission checks
Here's how these functions work together in a real Arxlet. This example shows fetching events, displaying user profiles, and handling real-time updates:
What are subscriptions? Think of subscriptions as "live feeds" that automatically notify your Arxlet when new data arrives. Instead of repeatedly asking "is there new data?", subscriptions push updates to you instantly.
How they work: When you subscribe to events or profiles, you get an RxJS Observable - a stream of data that flows over time. Your Arxlet can "listen" to this stream and update the UI whenever new data arrives.
Why use them? Subscriptions make your Arxlet feel alive and responsive. Users see new messages instantly, profile changes update immediately, and collaborative features work in real-time.
subscribeToEvents(filter)
gives you a live stream of events matching your criteria.
subscribeToProfile(pubkey)
watches for changes to a specific user's profile.
Here's a complete example showing how to set up subscriptions, handle incoming data, and clean up properly:
Always call unsubscribe()
when:
Why? Prevents memory leaks and unnecessary disk i/o.
catchError
takeUntil
for automatic cleanup
What is the WebSocket approach? Instead of using the convenient window.eve
{" "}
API, you can connect directly to the Nostr relay at ws://localhost:6942
and speak the raw
Nostr protocol.
Why would you use this? Direct WebSocket gives you maximum control and performance. You can implement custom subscription logic, handle multiple concurrent subscriptions efficiently, or integrate with existing Nostr libraries.
The trade-off: You'll need to understand the Nostr protocol, handle JSON message parsing, manage connection states, and implement your own error handling. It's more work but gives you complete flexibility.
Here's how to establish a WebSocket connection and communicate using standard Nostr protocol messages:
Start with window.eve: Even if you think you might need WebSocket later, begin with the high-level API. You can always refactor specific parts to use WebSocket once you understand your performance requirements.
Hybrid approach: Many successful Arxlets use window.eve
for most
operations and WebSocket only for specific high-performance features like real-time chat or live
collaboration.
Migration path: The data structures are the same, so you can gradually migrate from{" "}
window.eve
to WebSocket for specific features without rewriting your entire application.
Network requests can fail, relays can be down, or data might be malformed. Wrap all API calls to prevent crashes.
Query methods return null
when no data is found. Always check before using the result.
Show loading states, error messages, and success confirmations. Users should know what's happening.
Publishing events or loading essential data should retry on failure with exponential backoff.
Instead of fetching all events and filtering in JavaScript, use precise Nostr filters to reduce data transfer.
Profile information, avatars, and static content should be cached to avoid repeated API calls.
Don't load thousands of events at once. Use limit
and until
parameters for
pagination.
If users can trigger API calls quickly (like typing in search), debounce to avoid overwhelming the relay.
Always clean up subscriptions to prevent memory leaks and unnecessary network traffic.
Use spinners, skeletons, or progress indicators while data loads. Empty screens feel broken.
When no data is found, show helpful messages or suggestions rather than blank areas.
Update the UI immediately when users take actions, then sync with the server. Makes apps feel faster.
Let users know when they're disconnected or when operations might not work.
Never trust user input. Validate, sanitize, and escape data before using it in events or UI.
Remember that events are visible to everyone in your CCN by default. Don't accidentally expose private information.
Users might reject signing requests. Always have fallbacks and clear error messages.
Some users prefer pseudonymous usage. Don't force real names or personal information.