Skip to content

Commit ba2f6e0

Browse files
author
Philipp Heckel
committed
Anchors in web UI
1 parent ffe0c72 commit ba2f6e0

File tree

3 files changed

+74
-26
lines changed

3 files changed

+74
-26
lines changed

server/index.gohtml

+47-26
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
Endless possibilities 😀. Be sure to check out the <a href="https://github.com/binwiederhier/ntfy/tree/main/examples">example on GitHub</a>!
5959
</p>
6060

61-
<h2>Publishing messages</h2>
61+
<h2 id="publish" class="anchor">Publishing messages</h2>
6262
<p>
6363
Publishing messages can be done via PUT or POST using. Topics are created on the fly by subscribing or publishing to them.
6464
Because there is no sign-up, <b>the topic is essentially a password</b>, so pick something that's not easily guessable.
@@ -79,14 +79,14 @@
7979
})
8080
</code>
8181

82-
<h2>Subscribe to a topic</h2>
82+
<h2 id="subscribe" class="anchor">Subscribe to a topic</h2>
8383
<p>
8484
You can create and subscribe to a topic either in this web UI, or in your own app by subscribing to an
8585
<a href="https://developer.mozilla.org/en-US/docs/Web/API/EventSource">EventSource</a>, a JSON feed, or raw feed.
8686
</p>
8787

8888
<div id="subscribeBox">
89-
<h3>Subscribe in this Web UI</h3>
89+
<h3 id="subscribe-web" class="anchor">Subscribe in this Web UI</h3>
9090
<p id="error"></p>
9191
<p>
9292
Subscribe to topics here and receive messages as <b>desktop notification</b>. Topics are not password-protected,
@@ -104,13 +104,13 @@
104104
<audio id="notifySound" src="static/sound/mixkit-message-pop-alert-2354.mp3"></audio>
105105
</div>
106106

107-
<h3>Subscribe via Android App</h3>
107+
<h3 id="android-app" class="anchor">Subscribe via Android App</h3>
108108
<p>
109109
You can use the <a href="https://play.google.com/store/apps/details?id=io.heckel.ntfy">Ntfy Android App</a>
110110
to receive notifications directly on your phone. Just like the server, this app is also <a href="https://github.com/binwiederhier/ntfy-android">open source</a>.
111111
</p>
112112

113-
<h3>Subscribe via your app, or via the CLI</h3>
113+
<h3 id="subscribe-api" class="anchor">Subscribe via your app, or via the CLI</h3>
114114
<p class="smallMarginBottom">
115115
Using <a href="https://developer.mozilla.org/en-US/docs/Web/API/EventSource">EventSource</a> in JS, you can consume
116116
notifications like this (see <a href="https://github.com/binwiederhier/ntfy/tree/main/examples">full example</a>):
@@ -160,58 +160,79 @@
160160
done < <(stdbuf -i0 -o0 curl -s ntfy.sh/mytopic/raw)
161161
</code>
162162

163-
<h3>Message buffering and polling</h3>
163+
<h2 id="other-features" class="anchor">Other features</h2>
164+
<h3 id="fetching-cached-messages" class="anchor">Fetching cached messages</h3>
164165
<p class="smallMarginBottom">
165-
Messages are buffered in memory for a few hours to account for network interruptions of subscribers.
166-
You can read back what you missed by using the <tt>since=...</tt> query parameter. It takes either a
167-
duration (e.g. <tt>10m</tt> or <tt>30s</tt>) or a Unix timestamp (e.g. <tt>1635528757</tt>):
166+
Messages are cached on disk for {{.CacheDuration}} to account for network interruptions of subscribers.
167+
You can read back what you missed by using the <tt>since=</tt> query parameter. It takes either a
168+
duration (e.g. <tt>10m</tt> or <tt>30s</tt>), a Unix timestamp (e.g. <tt>1635528757</tt>) or <tt>all</tt> (all
169+
cached messages).
168170
</p>
169171
<code>
170-
$ curl -s "ntfy.sh/mytopic/json?since=10m"<br/>
171-
# Same output as above, but includes messages from up to 10 minutes ago
172+
curl -s "ntfy.sh/mytopic/json?since=10m"
172173
</code>
174+
175+
<h3 id="polling" class="anchor">Fetching cached messages</h3>
173176
<p class="smallMarginBottom">
174177
You can also just poll for messages if you don't like the long-standing connection using the <tt>poll=1</tt>
175-
query parameter. The connection will end after all available messages have been read. This parameter has to be
176-
combined with <tt>since=</tt>.
178+
query parameter. The connection will end after all available messages have been read. This parameter can be
179+
combined with <tt>since=</tt> (defaults to <tt>since=all</tt>).
177180
</p>
178181
<code>
179-
$ curl -s "ntfy.sh/mytopic/json?poll=1&since=10m"<br/>
180-
# Returns messages from up to 10 minutes ago and ends the connection
182+
curl -s "ntfy.sh/mytopic/json?poll=1"
181183
</code>
182184

183-
<h2>FAQ</h2>
185+
<h3 id="multiple-topics" class="anchor">Subscribing to multiple topics</h3>
186+
<p class="smallMarginBottom">
187+
It's possible to subscribe to multiple topics in one HTTP call by providing a
188+
comma-separated list of topics in the URL. This allows you to reduce the number of connections you have to maintain:
189+
</p>
190+
<code>
191+
$ curl -s ntfy.sh/mytopic1,mytopic2/json<br/>
192+
{"id":"0OkXIryH3H","time":1637182619,"event":"open","topic":"mytopic1,mytopic2,mytopic3"}<br/>
193+
{"id":"dzJJm7BCWs","time":1637182634,"event":"message","topic":"mytopic1","message":"for topic 1"}<br/>
194+
{"id":"Cm02DsxUHb","time":1637182643,"event":"message","topic":"mytopic2","message":"for topic 2"}
195+
</code>
196+
197+
<h2 id="faq" class="anchor">FAQ</h2>
184198
<p>
185-
<b>Isn't this like ...?</b><br/>
199+
<b id="isnt-this-like" class="anchor">Isn't this like ...?</b><br/>
186200
Who knows. I didn't do a lot of research before making this. It was fun making it.
187201
</p>
188202

189203
<p>
190-
<b>Can I use this in my app? Will it stay free?</b><br/>
204+
<b id="is-it-free" class="anchor">Can I use this in my app? Will it stay free?</b><br/>
191205
Yes. As long as you don't abuse it, it'll be available and free of charge. I do not plan on monetizing
192206
the service.
193207
</p>
194208

195209
<p>
196-
<b>What are the uptime guarantees?</b><br/>
210+
<b id="uptime-guarantees" class="anchor">What are the uptime guarantees?</b><br/>
197211
Best effort.
198212
</p>
199213

200214
<p>
201-
<b>Will you know what topics exist, can you spy on me?</b><br/>
215+
<b id="multiple-subscribers" class="anchor">What happens if there are multiple subscribers to the same topic?</b><br/>
216+
As per usual with pub-sub, all subscribers receive notifications if they are
217+
subscribed to a topic.
218+
</p>
219+
220+
<p>
221+
<b id="can-you-spy-on-me" class="anchor">Will you know what topics exist, can you spy on me?</b><br/>
202222
If you don't trust me or your messages are sensitive, run your own server. It's <a href="https://github.com/binwiederhier/ntfy">open source</a>.
203-
That said, the logs do not contain any topic names or other details about you. Check the code if you don't believe me.
223+
That said, the logs do not contain any topic names or other details about you.
224+
Messages are cached for {{.CacheDuration}} to facilitate service restarts, message polling and to overcome
225+
client network disruptions.
204226
</p>
205227

206228
<p>
207-
<b>Why is Firebase used?</b><br/>
229+
<b id="why-firebase" class="anchor">Why is Firebase used?</b><br/>
208230
In addition to caching messages locally and delivering them to long-polling subscribers, all messages are also
209231
published to Firebase Cloud Messaging (FCM) (if <tt>FirebaseKeyFile</tt> is set, which it is on ntfy.sh). This
210-
is to facilitate instant notifications on Android. I tried really, really hard to avoid using FCM, but newer
211-
versions of Android made it impossible to implement <a href="https://developer.android.com/guide/background">background services</a>.
232+
is to facilitate instant notifications on Android.
212233
</p>
213234

214-
<h2>Privacy policy</h2>
235+
<h2 id="#privacy" class="anchor">Privacy policy</h2>
215236
<p>
216237
Neither the server nor the app record any personal information, or share any of the messages and topics with
217238
any outside service. All data is exclusively used to make the service function properly. The one exception
@@ -220,7 +241,7 @@
220241
</p>
221242
<p>
222243
The web server does not log or otherwise store request paths, remote IP addresses or even topics or messages,
223-
aside from a short on-disk cache (up to a day) to support service restarts.
244+
aside from a short on-disk cache (for {{.CacheDuration}}) to support service restarts.
224245
</p>
225246

226247
<center id="ironicCenterTagDontFreakOut"><i>Made with ❤️ by <a href="https://heckel.io">Philipp C. Heckel</a></i></center>

server/static/css/app.css

+18
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,24 @@ code {
9595
color: #666;
9696
}
9797

98+
/* Anchors */
99+
100+
.anchor .anchorLink {
101+
color: #ccc;
102+
text-decoration: none;
103+
padding: 0 5px;
104+
visibility: hidden;
105+
}
106+
107+
.anchor:hover .anchorLink {
108+
visibility: visible;
109+
}
110+
111+
.anchor .anchorLink:hover {
112+
color: #3a9784;
113+
visibility: visible;
114+
}
115+
98116
/* Screenshots */
99117

100118
#screenshots {

server/static/js/app.js

+9
Original file line numberDiff line numberDiff line change
@@ -337,3 +337,12 @@ if (match) {
337337
currentTopicUnsubscribeOnClose = true;
338338
}
339339
}
340+
341+
document.querySelectorAll('.anchor').forEach((el) => {
342+
if (el.hasAttribute('id')) {
343+
const id = el.getAttribute('id');
344+
const anchor = document.createElement('a');
345+
anchor.innerHTML = `<a href="#${id}" class="anchorLink">#</a>`;
346+
el.appendChild(anchor);
347+
}
348+
});

0 commit comments

Comments
 (0)