nostr-blog-widget 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,223 @@
1
+ # Nostr Blog Widget
2
+
3
+ A drop-in JavaScript widget that transforms any webpage into a Nostr-powered blog. Display long-form articles (kind 30023) and short notes (kind 1) from Nostr with zero backend required.
4
+
5
+ ## Features
6
+
7
+ - 📝 **Dual Content Support**: Display both long-form articles (kind 30023) and short notes (kind 1)
8
+ - 👥 **Multi-Author Support**: Aggregate posts from multiple Nostr authors
9
+ - 🎨 **Three View Modes**: Grid, List, and Compact layouts
10
+ - 🖼️ **Rich Media**: Automatic image and video embedding
11
+ - 🔗 **Nostr Reference Embedding**: Embedded preview cards for referenced Nostr posts (nevent, naddr, note)
12
+ - 🎛️ **Built-in Controls**: Filter by author, content type, date range, and layout
13
+ - 🌓 **Theme Support**: Light, dark, and auto modes
14
+ - 📱 **Responsive Design**: Works on all devices
15
+ - ⚡ **No Backend Required**: Connects directly to Nostr relays
16
+
17
+ ## Installation
18
+
19
+ ### Via NPM
20
+
21
+ ```bash
22
+ npm install nostr-blog-widget
23
+ ```
24
+
25
+ Then include in your HTML:
26
+
27
+ ```html
28
+ <script src="node_modules/nostr-blog-widget/dist/nostr-blog.js"></script>
29
+ <link rel="stylesheet" href="node_modules/nostr-blog-widget/dist/nostr-blog.css">
30
+ ```
31
+
32
+ ### Via CDN
33
+
34
+ ```html
35
+ <script src="https://unpkg.com/nostr-blog-widget@latest/dist/nostr-blog.js"></script>
36
+ <link rel="stylesheet" href="https://unpkg.com/nostr-blog-widget@latest/dist/nostr-blog.css">
37
+ ```
38
+
39
+ ## Quick Start
40
+
41
+ Add this to your HTML:
42
+
43
+ ```html
44
+ <!DOCTYPE html>
45
+ <html>
46
+ <head>
47
+ <link rel="stylesheet" href="https://unpkg.com/nostr-blog-widget@latest/dist/nostr-blog.css">
48
+ </head>
49
+ <body>
50
+ <div
51
+ id="nostr-blog"
52
+ data-pubkey='["3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d", "npub1j8y6tcdfw3q3f3h794s6un0gyc5742s0k5h5s2yqj0r70cpklqeqjavrvg", "npub1k7cnst4fh4ajgg8w6ndcmqen4fnyc7ahhm3zpp255vdxqarrtekq5rrg96"]'
53
+ data-relays='["wss://relay.damus.io", "wss://nos.lol"]'
54
+ ></div>
55
+
56
+ <script src="https://unpkg.com/nostr-blog-widget@latest/dist/nostr-blog.js"></script>
57
+ </body>
58
+ </html>
59
+ ```
60
+
61
+ That's it! Your Nostr blog is live.
62
+
63
+ ## Configuration
64
+
65
+ Configure the widget using data attributes:
66
+
67
+ ```html
68
+ <div
69
+ id="nostr-blog"
70
+ data-pubkey='["npub1..."]'
71
+ data-relays='["wss://relay.damus.io", "wss://nos.lol"]'
72
+ data-layout="grid"
73
+ data-theme="light"
74
+ data-posts-per-page="10"
75
+ data-show-images="true"
76
+ data-date-format="relative"
77
+ data-content-type="all"
78
+ data-show-controls="true"
79
+ data-pagination="load-more"
80
+ ></div>
81
+ ```
82
+
83
+ ### Available Options
84
+
85
+ | Attribute | Type | Default | Description |
86
+ |-----------|------|---------|-------------|
87
+ | `data-pubkey` | string or array | *required* | Nostr pubkey(s) in hex or npub format |
88
+ | `data-relays` | array | *required* | Array of Nostr relay URLs |
89
+ | `data-layout` | `grid` \| `list` \| `compact` | `grid` | Display layout |
90
+ | `data-theme` | `light` \| `dark` \| `auto` | `light` | Color theme |
91
+ | `data-posts-per-page` | number | `10` | Number of posts to load |
92
+ | `data-show-images` | boolean | `true` | Show post images |
93
+ | `data-date-format` | `short` \| `long` \| `relative` | `relative` | Date display format |
94
+ | `data-content-type` | `all` \| `long-form` \| `short-form` | `all` | Filter by content type |
95
+ | `data-show-controls` | boolean | `true` | Show control panel |
96
+ | `data-pagination` | `infinite-scroll` \| `load-more` \| `none` | `load-more` | Pagination style |
97
+
98
+ ## View Modes
99
+
100
+ ### Grid View
101
+ Cards displayed in a responsive grid with images, titles, and summaries.
102
+
103
+ ### List View
104
+ Full-width cards with complete content preview.
105
+
106
+ ### Compact View
107
+ Minimal single-line entries with just date and title - perfect for blog archives.
108
+
109
+ ## Content Types
110
+
111
+ ### Long-form Articles (kind 30023)
112
+ - Displays title, summary, author, date, and feature image
113
+ - "Read more" button to view full article
114
+ - Full markdown support in article view
115
+
116
+ ### Short Notes (kind 1)
117
+ - Shows complete content in grid/list view
118
+ - Automatic media embedding (images and videos)
119
+ - Embedded preview cards for Nostr references
120
+ - No "Read more" button needed
121
+
122
+ ## Advanced Usage
123
+
124
+ ### Multiple Authors
125
+
126
+ ```html
127
+ data-pubkey='["npub1abc...", "npub1def...", "hex-pubkey-123"]'
128
+ ```
129
+
130
+ The widget automatically:
131
+ - Fetches posts from all authors
132
+ - Shows author filter dropdown
133
+ - Displays author avatars and names
134
+
135
+ ### Custom Styling
136
+
137
+ Override default styles with CSS:
138
+
139
+ ```css
140
+ /* Customize colors */
141
+ .nbw-bg-white { background: #f5f5f5 !important; }
142
+ .nbw-text-blue-600 { color: #0066cc !important; }
143
+
144
+ /* Customize card appearance */
145
+ .nbw-rounded-lg { border-radius: 8px !important; }
146
+ .nbw-shadow-md { box-shadow: 0 4px 6px rgba(0,0,0,0.1) !important; }
147
+ ```
148
+
149
+ All widget classes are prefixed with `nbw-` to avoid conflicts.
150
+
151
+ ### Embedding Options
152
+
153
+ The widget automatically handles:
154
+ - Image URLs (jpg, png, gif, webp, svg)
155
+ - Video URLs (mp4, webm, mov, avi)
156
+ - Nostr references (nevent1, naddr1, note1) - shows embedded post cards
157
+ - Nostr profiles (npub1, nprofile1) - shows clickable links
158
+
159
+ ## Examples
160
+
161
+ ### Personal Blog
162
+ ```html
163
+ <div
164
+ id="nostr-blog"
165
+ data-pubkey="npub1yourpubkey..."
166
+ data-relays='["wss://relay.damus.io"]'
167
+ data-layout="list"
168
+ data-content-type="long-form"
169
+ ></div>
170
+ ```
171
+
172
+ ### Multi-Author Publication
173
+ ```html
174
+ <div
175
+ id="nostr-blog"
176
+ data-pubkey='["npub1author1...", "npub1author2..."]'
177
+ data-relays='["wss://relay.damus.io", "wss://nos.lol"]'
178
+ data-layout="grid"
179
+ data-show-controls="true"
180
+ ></div>
181
+ ```
182
+
183
+ ### Compact Archive
184
+ ```html
185
+ <div
186
+ id="nostr-blog"
187
+ data-pubkey="npub1yourpubkey..."
188
+ data-relays='["wss://relay.damus.io"]'
189
+ data-layout="compact"
190
+ data-show-controls="false"
191
+ data-posts-per-page="50"
192
+ ></div>
193
+ ```
194
+
195
+ ## Browser Support
196
+
197
+ - Chrome/Edge: ✅
198
+ - Firefox: ✅
199
+ - Safari: ✅
200
+ - Mobile browsers: ✅
201
+
202
+ ## Technical Details
203
+
204
+ - Built with [SolidJS](https://www.solidjs.com/) for reactive UI
205
+ - Uses [nostr-tools](https://github.com/nbd-wtf/nostr-tools) for Nostr protocol
206
+ - Styled with [TailwindCSS](https://tailwindcss.com/)
207
+ - Markdown rendering via [marked](https://marked.js.org/)
208
+
209
+ ## License
210
+
211
+ MIT
212
+
213
+ ## Contributing
214
+
215
+ Issues and pull requests welcome at [github.com/bigmarh/nostr-blog-widget](https://github.com/bigmarh/nostr-blog-widget)
216
+
217
+ ## Author
218
+
219
+ Created by [Lamar Wilson](https://lamarwilson.com)
220
+
221
+ ## Support
222
+
223
+ - GitHub Issues: [Report bugs](https://github.com/bigmarh/nostr-blog-widget/issues)
@@ -0,0 +1,2 @@
1
+ "use strict";(this.webpackChunkNostrBlog=this.webpackChunkNostrBlog||[]).push([[537],{537(n,r,e){e.d(r,{Navigation:()=>s});var t=e(35),b=e(701),o=(0,t.vs)('<nav class=nbw-space-y-2><a href=#/ class="nbw-block nbw-px-4 nbw-py-2 nbw-rounded nbw-transition-colors hover:nbw-bg-gray-100 nbw-text-gray-900 nbw-no-underline">Home</a><div class="nbw-border-t nbw-border-gray-200 nbw-my-2">'),a=(0,t.vs)('<a class="nbw-block nbw-px-4 nbw-py-2 nbw-rounded nbw-transition-colors hover:nbw-bg-gray-100 nbw-text-gray-700 nbw-no-underline nbw-text-sm">');const s=n=>{return r=o(),(e=r.firstChild).nextSibling,e.$$click=r=>{r.preventDefault(),n.onHome()},(0,t.Yr)(r,(0,b.a0)(b.a,{get each(){return n.posts},children:r=>{return(e=a()).$$click=e=>{e.preventDefault(),n.onNavigate(r.id)},(0,t.Yr)(e,()=>r.title),(0,b.gb)(b=>{var o=`#/post/${r.id}`,a={"nbw-bg-gray-200 nbw-font-semibold":n.currentPostId===r.id};return o!==b.e&&(0,t.Bq)(e,"href",b.e=o),b.t=(0,t.pP)(e,a,b.t),b},{e:void 0,t:void 0}),e;var e}}),null),(0,b.gb)(r=>(0,t.pP)(e,{"nbw-bg-gray-200 nbw-font-semibold":!n.currentPostId},r)),r;var r,e};(0,t.z_)(["click"])}}]);
2
+ //# sourceMappingURL=537.nostr-blog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"537.nostr-blog.js","mappings":"8hBAUO,MAAMA,EAA0CC,IACrD,oDAMgBC,IACRA,EAAEC,iBACFF,EAAMG,WACP,mBAKF,IAAG,SAACC,GAAI,OAAEJ,EAAMK,KAAK,WAClBC,IAAI,sBAKQL,IACRA,EAAEC,iBACFF,EAAMO,WAAWD,EAAKE,MACvB,cAEAF,EAAKG,QAAK,kBARL,UAAUH,EAAKE,KAAI,EAEd,CAAE,oCAAqCR,EAAMU,gBAAkBJ,EAAKE,IAAI,yFAJjF,SAYL,6BAtBU,CAAE,qCAAsCR,EAAMU,eAAe,MALvE,IAAP,MA+BA,kB","sources":["webpack://NostrBlog/./src/components/Navigation.tsx"],"sourcesContent":["import { Component, For } from 'solid-js';\nimport { BlogPost } from '../types/config';\n\ninterface NavigationProps {\n posts: BlogPost[];\n currentPostId?: string;\n onNavigate: (postId: string) => void;\n onHome: () => void;\n}\n\nexport const Navigation: Component<NavigationProps> = (props) => {\n return (\n <nav class=\"nbw-space-y-2\">\n <a\n href=\"#/\"\n class=\"nbw-block nbw-px-4 nbw-py-2 nbw-rounded nbw-transition-colors hover:nbw-bg-gray-100 nbw-text-gray-900 nbw-no-underline\"\n classList={{ 'nbw-bg-gray-200 nbw-font-semibold': !props.currentPostId }}\n onClick={(e) => {\n e.preventDefault();\n props.onHome();\n }}\n >\n Home\n </a>\n <div class=\"nbw-border-t nbw-border-gray-200 nbw-my-2\"></div>\n <For each={props.posts}>\n {(post) => (\n <a\n href={`#/post/${post.id}`}\n class=\"nbw-block nbw-px-4 nbw-py-2 nbw-rounded nbw-transition-colors hover:nbw-bg-gray-100 nbw-text-gray-700 nbw-no-underline nbw-text-sm\"\n classList={{ 'nbw-bg-gray-200 nbw-font-semibold': props.currentPostId === post.id }}\n onClick={(e) => {\n e.preventDefault();\n props.onNavigate(post.id);\n }}\n >\n {post.title}\n </a>\n )}\n </For>\n </nav>\n );\n};\n"],"names":["Navigation","props","e","preventDefault","onHome","each","posts","post","onNavigate","id","title","currentPostId"],"ignoreList":[],"sourceRoot":""}