This document provides detailed information for developers who want to contribute to or understand the NoteDeck Columns codebase.
The NoteDeck Columns codebase is organized as follows:
notedeck_columns
├── src
│ ├── ui # UI components and views
│ │ ├── note # Note-related UI components (posts, replies, quotes)
│ │ ├── column # Column UI components
│ │ ├── search # Search functionality
│ │ ├── profile # Profile views and editing
│ │ └── ...
│ ├── timeline # Timeline data structures and logic
│ ├── storage # Persistence mechanisms
│ ├── accounts # Account management
│ ├── decks # Deck management
│ ├── app.rs # Main application logic
│ ├── app_creation.rs # Application initialization
│ ├── route.rs # Routing system
│ ├── nav.rs # Navigation logic
│ └── ...
- Rust toolchain (latest stable recommended)
- nostrdb and its dependencies
- egui and eframe
-
Clone the repository:
git clone https://github.com/damus-io/notedeck cd notedeck
-
Build the project:
cargo build --release
-
Run the application:
cargo run --release
For development, you might want to run with debug symbols:
cargo run
- Deck: A collection of columns that a user can switch between
- Column: A view into a specific type of Nostr content (timeline, profile, etc.)
Timelines are a fundamental concept in NoteDeck Columns:
Timeline
: Represents a stream of notes with filters and subscriptionsTimelineKind
: Defines the type of timeline (Universe, Profile, Notifications, etc.)TimelineTab
: Filtered views of a timeline (e.g., Notes only vs. Notes & Replies)TimelineCache
: Caches timeline data for efficient access
Route
: Represents application navigation targetsRouter
: Manages the navigation stack for each columnNavTitle
: Renders the title bar for navigationRenderNavAction
: Actions resulting from navigation events
The UI is built with egui and organized into components:
PostView
,PostReplyView
,QuoteRepostView
: Note creation UINoteView
: Displays Nostr notesProfileView
: Displays and edits profilesTimelineView
: Renders timelines in columnsDesktopSidePanel
: Side navigation panel
NoteDeck Columns manages Nostr subscriptions and relay connections to provide realtime updates:
MultiSubscriber
: Handles subscriptions to multiple relaysSubscriptions
: Tracks application-wide subscriptionsRelayPool
: Manages relay connections
- User actions create routes or trigger navigation
- Routes are mapped to timeline kinds or other UI views
- Timelines query nostrdb for notes matching their filters
- UI components render the note data
- Subscriptions keep the data updated in realtime
State is managed at different levels:
Damus
: Contains global application stateDecksCache
: Holds deck and column configurationsTimelineCache
: Caches timeline data- Various component-specific state structures
Run the test suite:
cargo test
The codebase includes unit tests for critical components.
- Add a new variant to
TimelineKind
enum intimeline/kind.rs
- Implement the necessary filter logic
- Update the serialization and parsing methods
- Add UI support in the AddColumn view
- Create a new Rust file in the appropriate ui directory
- Implement the component using egui
- Connect it to the routing system if needed
When implementing new features:
- Start by understanding the relevant parts of the codebase
- Look for similar implementations as reference
- Follow the existing patterns for state management and UI components
- Add appropriate tests
- Update documentation
- Render Issues: Check the egui-related code for layout problems
- Data Freshness: Verify subscription and filter setup
- Performance: Look for inefficient queries or rendering
- Use
tracing
macros (debug!
,info!
,error!
) for logging - Run with
RUST_LOG=debug
for verbose output - Use
cargo expand
to inspect macro expansion
egui was chosen for its immediate mode rendering approach and Rust integration, making it well-suited for a responsive multi-column UI.
nostrdb provides high-performance local storage and querying for Nostr events, which is essential for a responsive client.
The codebase is structured around timelines because they provide a natural abstraction for the different types of Nostr content views needed in a column-based interface.
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature
- Make your changes
- Run tests:
cargo test
- Submit a pull request
Please follow the existing code style and patterns.