mroxso 179d3682f8 feat: bookmarks for notes and articles (NIP-51) (#29)
* feat: bookmarks for notes and articles (NIP-51)

Adds a Bookmarks app backed by a kind 10003 NIP-51 bookmark list:
- BookmarkButton toggles a note (`e` tag) or article (`a` tag) in and
  out of the signed-in user's list, reading it back before publishing
  so an update never clobbers other entries — the same whole-list
  replacement trap follow lists have.
- Wired into NoteCard's action row and the Reader's article toolbar.
- The new Bookmarks app lists saved notes and articles, opening
  articles back in the Reader.

Closes #21

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BYiUtZMQeA5RHggQw73wto

* fix: address review feedback and add a Bookmarked tab to the Reader

Per review:
- useToggleBookmark now fetches the bookmark list fresh from relays
  right before writing instead of trusting the query cache (60s
  staleTime), which could otherwise clobber concurrent edits from
  another tab or device.
- The article BookmarkButton only renders when the article actually
  has a `d` tag, instead of falling back to an unresolvable
  "kind:pubkey:" address.
- Bookmarked note/article ids are filtered for a non-empty tag value
  before use, and article addresses are parsed properly (kind,
  author, `d`) instead of a naive split(':')[2] — the relay query is
  now also constrained by kind and author, not just `d`, and
  identifiers containing ':' round-trip correctly.
- BookmarkButton sets type="button" so it can't misbehave as a form
  submit button.

Per a reviewer comment: added a "Recent" / "Bookmarked" tab to the
Reader's sidebar (src/apps/articles/index.tsx) so bookmarked articles
are reachable without leaving the app — the dedicated Bookmarks app
stays as-is. Both now share useMyBookmarkedArticles from
src/hooks/useBookmarks.ts rather than duplicating the address-parsing
logic.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BYiUtZMQeA5RHggQw73wto

* fix: reject empty-identifier addresses and surface bookmark load errors

Per review:
- parseAddress() now rejects an empty d-identifier as malformed
  (e.g. "30023:<pubkey>:") instead of producing a "#d: ['']" relay
  query and an unopenable bookmark.
- useMyBookmarkedArticles() filters out matched events with empty
  content, the same non-renderable criteria the Reader's own list
  uses, so a broken/blank article can't land in the Bookmarked view.
- BookmarksApp now distinguishes "the query failed" from "there are
  no bookmarks" — React Query leaves data undefined in both cases, so
  a relay/network failure no longer reads as an empty list.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BYiUtZMQeA5RHggQw73wto

---------

Co-authored-by: highperfocused <highperfocused@pm.me>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-06 18:45:21 +02:00
2026-09-06 11:37:43 +02:00
2025-12-27 21:42:31 +01:00
2025-12-27 21:42:31 +01:00
2026-09-06 11:37:43 +02:00
2026-09-06 11:37:43 +02:00
2025-12-27 21:42:31 +01:00
2025-12-27 21:42:31 +01:00
2026-09-06 11:37:43 +02:00
2026-09-06 11:37:43 +02:00
2026-09-06 11:37:43 +02:00
2026-09-06 11:37:43 +02:00
2026-09-06 11:37:43 +02:00
2026-09-06 11:37:43 +02:00
2026-09-06 11:37:43 +02:00
2026-09-06 11:37:43 +02:00
2026-09-06 11:37:43 +02:00
2026-09-06 11:37:43 +02:00

MKStack

The Complete Framework for Building Nostr Clients with AI

MKStack is an AI-powered framework for building Nostr applications with React 18.x, TailwindCSS 3.x, Vite, shadcn/ui, and Nostrify. Build powerful Nostr applications with AI-first development - from social feeds to private messaging, MKStack provides everything you need to create decentralized apps on the Nostr protocol.

🚀 Quick Start

Build your Nostr app in 3 simple steps:

1. Install & Create

npm install -g @getstacks/stacks
stacks mkstack

2. Build with AI

stacks agent
# Tell Dork AI what you want: "Build a group chat application"

3. Deploy Instantly

npm run deploy
# ✅ App deployed to NostrDeploy.com!

What Makes MKStack Special

  • 🤖 AI-First Development: Build complete Nostr apps with just one prompt using Dork AI agent
  • 8 Minutes Average: From idea to deployed application in minutes, not months
  • 🔗 50+ NIPs Supported: Comprehensive Nostr protocol implementation
  • 🎨 Beautiful UI: 48+ shadcn/ui components with light/dark theme support
  • 🔐 Built-in Security: NIP-07 browser signing, NIP-44 encryption, event validation
  • 💰 Payments Ready: Lightning zaps (NIP-57), Cashu wallets (NIP-60), Wallet Connect (NIP-47)
  • 📱 Production Ready: TypeScript, testing, deployment, and responsive design included

🛠 Technology Stack

  • React 18.x: Stable version with hooks, concurrent rendering, and improved performance
  • TailwindCSS 3.x: Utility-first CSS framework for styling
  • Vite: Fast build tool and development server
  • shadcn/ui: 48+ unstyled, accessible UI components built with Radix UI
  • Nostrify: Nostr protocol framework for Deno and web
  • React Router: Client-side routing with BrowserRouter
  • TanStack Query: Data fetching, caching, and state management
  • TypeScript: Type-safe JavaScript development

🎯 Real-World Examples

Built with One Prompt

Each of these applications was created with just a single prompt to Dork AI:

  • Group Chat Application: "Build me a group chat application"

  • Decentralized Goodreads: "Build a decentralized goodreads alternative. Use OpenLibrary API for book data."

  • Chess Game: "Build a chess game with NIP 64"

Production Apps

Real Nostr applications built using MKStack:

  • Chorus: Facebook-style groups on Nostr with built-in eCash wallet
  • Blobbi: Digital pet companions that live forever on the decentralized web
  • Treasures: Decentralized geocaching adventure powered by Nostr

Browse more apps made with MKStack →

🔧 Core Features

Authentication & Users

  • LoginArea component with account switching
  • useCurrentUser hook for authentication state
  • useAuthor hook for fetching user profiles
  • NIP-07 browser signing support
  • Multi-account management

Nostr Protocol Support

  • Social Features: User profiles (NIP-01), follow lists (NIP-02), reactions (NIP-25), reposts (NIP-18)
  • Messaging: Private DMs (NIP-17), public chat (NIP-28), group chat (NIP-29), encryption (NIP-44)
  • Payments: Lightning zaps (NIP-57), Cashu wallets (NIP-60), Nutzaps (NIP-61), Wallet Connect (NIP-47)
  • Content: Long-form articles (NIP-23), file metadata (NIP-94), live events (NIP-53), calendars (NIP-52)

Data Management

  • useNostr hook for querying and publishing
  • useNostrPublish hook with automatic client tagging
  • Event validation and filtering
  • Infinite scroll with TanStack Query
  • Multi-relay support

UI Components

  • 48+ shadcn/ui components (buttons, forms, dialogs, etc.)
  • NoteContent component for rich text rendering
  • EditProfileForm for profile management
  • RelaySelector for relay switching
  • CommentsSection for threaded discussions
  • Light/dark theme system

Media & Files

  • useUploadFile hook with Blossom server integration
  • NIP-94 compatible file metadata
  • Image and video support
  • File attachment to events

Advanced Features

  • NIP-19 identifier routing (npub1, note1, nevent1, naddr1)
  • Cryptographic operations (encryption/decryption)
  • Lightning payments and zaps
  • Real-time event subscriptions
  • Responsive design with mobile support

🤖 AI Development with Dork

MKStack includes Dork, a built-in AI agent that understands your codebase and Nostr protocols:

Supported AI Providers

Configure your AI provider with stacks configure:

  • OpenRouter (openrouter.ai): Enter your API key from settings
  • Routstr (routstr.com): Use Cashu tokens for payment
  • PayPerQ (ppq.ai): OpenAI-compatible API

How Dork Works

  • Context-Aware: Understands your entire codebase and project structure
  • Nostr Expert: Built-in knowledge of 50+ NIPs and best practices
  • Instant Implementation: Makes changes directly to your code following React/TypeScript best practices

Example prompts:

"Add user profiles with avatars and bio"
"Implement NIP-17 private messaging"
"Add a dark mode toggle"
"Create a marketplace with NIP-15"

📁 Project Structure

src/
├── components/           # UI components
│   ├── ui/              # shadcn/ui components (48+ available)
│   ├── auth/            # Authentication components
│   └── comments/        # Comment system components
├── hooks/               # Custom React hooks
│   ├── useNostr         # Core Nostr integration
│   ├── useAuthor        # User profile data
│   ├── useCurrentUser   # Authentication state
│   ├── useNostrPublish  # Event publishing
│   ├── useUploadFile    # File uploads
│   └── useZaps          # Lightning payments
├── pages/               # Page components
├── lib/                 # Utility functions
├── contexts/            # React context providers
└── test/                # Testing utilities

🎨 UI Components

MKStack includes 48+ shadcn/ui components:

Layout: Card, Separator, Sheet, Sidebar, ScrollArea, Resizable Navigation: Breadcrumb, NavigationMenu, Menubar, Tabs, Pagination Forms: Button, Input, Textarea, Select, Checkbox, RadioGroup, Switch, Slider Feedback: Alert, AlertDialog, Toast, Progress, Skeleton Overlay: Dialog, Popover, HoverCard, Tooltip, ContextMenu, DropdownMenu Data Display: Table, Avatar, Badge, Calendar, Chart, Carousel **And many more...

🔐 Security & Best Practices

  • Never use any type: Always use proper TypeScript types
  • Event validation: Filter events through validator functions for custom kinds
  • Efficient queries: Minimize separate queries to avoid rate limiting
  • Proper error handling: Graceful handling of invalid NIP-19 identifiers
  • Secure authentication: Use signer interface, never request private keys directly

📱 Responsive Design

  • Mobile-first approach with Tailwind breakpoints
  • useIsMobile hook for responsive behavior
  • Touch-friendly interactions
  • Optimized for all screen sizes

🧪 Testing

  • Vitest with jsdom environment
  • React Testing Library with jest-dom matchers
  • TestApp component provides all necessary context providers
  • Mocked browser APIs (matchMedia, scrollTo, IntersectionObserver, ResizeObserver)

🚀 Deployment

Built-in deployment to NostrDeploy.com:

npm run deploy

Your app goes live instantly with:

  • Automatic builds
  • CDN distribution
  • HTTPS support
  • Custom domains available

📚 Documentation

For detailed documentation on building Nostr applications with MKStack:

🤝 Contributing

MKStack is open source and welcomes contributions. The framework is designed to be:

  • Extensible: Easy to add new NIPs and features
  • Maintainable: Clean architecture with TypeScript
  • Testable: Comprehensive testing setup included
  • Documented: Clear patterns and examples

📄 License

MKStack is dedicated to the public domain.

To the extent possible under law, the authors have waived all copyright and related or neighboring rights to MKStack. You are free to copy, modify, distribute, and use this software for any purpose, commercial or non-commercial, without asking permission and without attribution.

Build amazing Nostr applications and help grow the decentralized web!


"Vibed with MKStack" - Learn more about MKStack

Build your Nostr app in minutes, not months. Start with AI, deploy instantly.

Description
No description provided
Readme 1.6 MiB
Languages
TypeScript 98.1%
CSS 1%
JavaScript 0.8%
HTML 0.1%