Docs docs docs
@ -4,9 +4,9 @@ I love free software and I'm doing this because it's fun and to give back. I hav
|
|||||||
never monetize or sell your information. This service will always stay free and open.
|
never monetize or sell your information. This service will always stay free and open.
|
||||||
|
|
||||||
Neither the server nor the app record any personal information, or share any of the messages and topics with
|
Neither the server nor the app record any personal information, or share any of the messages and topics with
|
||||||
any outside service. All data is exclusively used to make the service function properly. The one exception
|
any outside service. All data is exclusively used to make the service function properly. The only external service
|
||||||
is the Firebase Cloud Messaging (FCM) service, which is required to provide instant Android notifications (see
|
I use is Firebase Cloud Messaging (FCM) service, which is required to provide instant Android notifications (see
|
||||||
[FAQ](faq.md) for details).
|
[FAQ](faq.md) for details). To avoid FCM altogether, download the F-Droid version.
|
||||||
|
|
||||||
The web server does not log or otherwise store request paths, remote IP addresses or even topics or messages,
|
The web server does not log or otherwise store request paths, remote IP addresses or even topics or messages,
|
||||||
aside from a short on-disk cache to support service restarts.
|
aside from a short on-disk cache to support service restarts.
|
||||||
|
79
docs/static/css/extra.css
vendored
@ -1,3 +1,7 @@
|
|||||||
|
.md-header__button.md-logo :is(img, svg) {
|
||||||
|
width: unset !important;
|
||||||
|
}
|
||||||
|
|
||||||
article {
|
article {
|
||||||
padding-bottom: 50px;
|
padding-bottom: 50px;
|
||||||
}
|
}
|
||||||
@ -16,3 +20,78 @@ figure img {
|
|||||||
.remove-md-box td {
|
.remove-md-box td {
|
||||||
padding: 0 10px
|
padding: 0 10px
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Lightbox; thanks to https://yossiabramov.com/blog/vanilla-js-lightbox */
|
||||||
|
|
||||||
|
.screenshots {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.screenshots img {
|
||||||
|
height: 230px;
|
||||||
|
margin: 3px;
|
||||||
|
border-radius: 5px;
|
||||||
|
filter: drop-shadow(2px 2px 2px #ddd);
|
||||||
|
}
|
||||||
|
|
||||||
|
.screenshots .nowrap {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lightbox {
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
position: fixed;
|
||||||
|
left:0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: -1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition: all 0.15s ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lightbox.show {
|
||||||
|
background-color: rgba(0,0,0, 0.75);
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lightbox img {
|
||||||
|
max-width: 90%;
|
||||||
|
max-height: 90%;
|
||||||
|
filter: drop-shadow(5px 5px 10px #222);
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lightbox .close-lightbox {
|
||||||
|
cursor: pointer;
|
||||||
|
position: absolute;
|
||||||
|
top: 30px;
|
||||||
|
right: 30px;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lightbox .close-lightbox::after,
|
||||||
|
.lightbox .close-lightbox::before {
|
||||||
|
content: '';
|
||||||
|
width: 3px;
|
||||||
|
height: 20px;
|
||||||
|
background-color: #ddd;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 5px;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.lightbox .close-lightbox::before {
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.lightbox .close-lightbox:hover::after,
|
||||||
|
.lightbox .close-lightbox:hover::before {
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
BIN
docs/static/img/android-notification-settings.png
vendored
Normal file
After Width: | Height: | Size: 111 KiB |
BIN
docs/static/img/android-screenshot-add-instant.jpg
vendored
Normal file
After Width: | Height: | Size: 297 KiB |
BIN
docs/static/img/android-screenshot-add-other.jpg
vendored
Normal file
After Width: | Height: | Size: 300 KiB |
BIN
docs/static/img/android-screenshot-add.jpg
vendored
Normal file
After Width: | Height: | Size: 236 KiB |
BIN
docs/static/img/android-screenshot-detail.jpg
vendored
Normal file
After Width: | Height: | Size: 255 KiB |
BIN
docs/static/img/android-screenshot-main.jpg
vendored
Normal file
After Width: | Height: | Size: 149 KiB |
BIN
docs/static/img/android-screenshot-pause.jpg
vendored
Normal file
After Width: | Height: | Size: 212 KiB |
BIN
docs/static/img/android-video-overview.mp4
vendored
Normal file
Before Width: | Height: | Size: 253 KiB After Width: | Height: | Size: 253 KiB |
BIN
docs/static/img/screenshot-phone-add.jpg
vendored
Normal file
After Width: | Height: | Size: 227 KiB |
BIN
docs/static/img/screenshot-phone-detail.jpg
vendored
Normal file
After Width: | Height: | Size: 225 KiB |
BIN
docs/static/img/screenshot-phone-main.jpg
vendored
Normal file
After Width: | Height: | Size: 128 KiB |
BIN
docs/static/img/screenshot-phone-notification.jpg
vendored
Normal file
After Width: | Height: | Size: 224 KiB |
BIN
docs/static/img/screenshot-web.png
vendored
Before Width: | Height: | Size: 41 KiB |
BIN
docs/static/img/web-detail.png
vendored
Normal file
After Width: | Height: | Size: 116 KiB |
BIN
docs/static/img/web-notification.png
vendored
Normal file
After Width: | Height: | Size: 297 KiB |
BIN
docs/static/img/web-subscribe.png
vendored
Normal file
After Width: | Height: | Size: 31 KiB |
68
docs/static/js/extra.js
vendored
@ -29,3 +29,71 @@ for (const tab of tabs) {
|
|||||||
tab.checked = true
|
tab.checked = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lightbox for screenshot
|
||||||
|
|
||||||
|
const lightbox = document.createElement('div');
|
||||||
|
lightbox.classList.add('lightbox');
|
||||||
|
document.body.appendChild(lightbox);
|
||||||
|
|
||||||
|
const showScreenshotOverlay = (e, el, group, index) => {
|
||||||
|
lightbox.classList.add('show');
|
||||||
|
document.addEventListener('keydown', nextScreenshotKeyboardListener);
|
||||||
|
return showScreenshot(e, group, index);
|
||||||
|
};
|
||||||
|
|
||||||
|
const showScreenshot = (e, group, index) => {
|
||||||
|
const actualIndex = resolveScreenshotIndex(group, index);
|
||||||
|
lightbox.innerHTML = '<div class="close-lightbox"></div>' + screenshots[group][actualIndex].innerHTML;
|
||||||
|
lightbox.querySelector('img').onclick = (e) => { return showScreenshot(e, group, actualIndex+1); };
|
||||||
|
currentScreenshotGroup = group;
|
||||||
|
currentScreenshotIndex = actualIndex;
|
||||||
|
e.stopPropagation();
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const nextScreenshot = (e) => {
|
||||||
|
return showScreenshot(e, currentScreenshotGroup, currentScreenshotIndex+1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const previousScreenshot = (e) => {
|
||||||
|
return showScreenshot(e, currentScreenshotGroup, currentScreenshotIndex-1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const resolveScreenshotIndex = (group, index) => {
|
||||||
|
if (index < 0) {
|
||||||
|
return screenshots[group].length - 1;
|
||||||
|
} else if (index > screenshots[group].length - 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
};
|
||||||
|
|
||||||
|
const hideScreenshotOverlay = (e) => {
|
||||||
|
lightbox.classList.remove('show');
|
||||||
|
document.removeEventListener('keydown', nextScreenshotKeyboardListener);
|
||||||
|
};
|
||||||
|
|
||||||
|
const nextScreenshotKeyboardListener = (e) => {
|
||||||
|
switch (e.keyCode) {
|
||||||
|
case 37:
|
||||||
|
previousScreenshot(e);
|
||||||
|
break;
|
||||||
|
case 39:
|
||||||
|
nextScreenshot(e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let currentScreenshotGroup = '';
|
||||||
|
let currentScreenshotIndex = 0;
|
||||||
|
let screenshots = {};
|
||||||
|
Array.from(document.getElementsByClassName('screenshots')).forEach((sg) => {
|
||||||
|
const group = sg.id;
|
||||||
|
screenshots[group] = [...sg.querySelectorAll('a')];
|
||||||
|
screenshots[group].forEach((el, index) => {
|
||||||
|
el.onclick = (e) => { return showScreenshotOverlay(e, el, group, index); };
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
lightbox.onclick = hideScreenshotOverlay;
|
||||||
|
@ -4,12 +4,51 @@ notifications directly on your phone. Just like the server, this app is also [op
|
|||||||
Since I don't have an iPhone or a Mac, I didn't make an iOS app yet. I'd be awesome if [someone else could help out](https://github.com/binwiederhier/ntfy/issues/4).
|
Since I don't have an iPhone or a Mac, I didn't make an iOS app yet. I'd be awesome if [someone else could help out](https://github.com/binwiederhier/ntfy/issues/4).
|
||||||
|
|
||||||
## Android
|
## Android
|
||||||
|
<a href="https://play.google.com/store/apps/details?id=io.heckel.ntfy"><img src="../../static/img/badge-googleplay.png"></a>
|
||||||
|
<a href="https://f-droid.org/en/packages/io.heckel.ntfy/"><img src="../../static/img/badge-fdroid.png"></a>
|
||||||
|
|
||||||
You can get the Android app from both [Google Play](https://play.google.com/store/apps/details?id=io.heckel.ntfy) and
|
You can get the Android app from both [Google Play](https://play.google.com/store/apps/details?id=io.heckel.ntfy) and
|
||||||
from [F-Droid](https://f-droid.org/en/packages/io.heckel.ntfy/). Both are largely identical, with the one exception that
|
from [F-Droid](https://f-droid.org/en/packages/io.heckel.ntfy/). Both are largely identical, with the one exception that
|
||||||
the F-Droid flavor does not use Firebase.
|
the F-Droid flavor does not use Firebase.
|
||||||
|
|
||||||
<a href="https://play.google.com/store/apps/details?id=io.heckel.ntfy"><img src="../../static/img/badge-googleplay.png"></a>
|
### Overview
|
||||||
<a href="https://f-droid.org/en/packages/io.heckel.ntfy/"><img src="../../static/img/badge-fdroid.png"></a>
|
A picture is worth a thousand words. Here are a few screenshots showing what the app looks like. It's all pretty
|
||||||
|
straight forward. You can add topics and as soon as you add them, you can [publish messages](../publish.md) to them.
|
||||||
|
|
||||||
|
<div id="android-screenshots" class="screenshots">
|
||||||
|
<a href="../../static/img/android-screenshot-main.jpg"><img src="../../static/img/android-screenshot-main.jpg"/></a>
|
||||||
|
<a href="../../static/img/android-screenshot-detail.jpg"><img src="../../static/img/android-screenshot-detail.jpg"/></a>
|
||||||
|
<a href="../../static/img/android-screenshot-add.jpg"><img src="../../static/img/android-screenshot-add.jpg"/></a>
|
||||||
|
<a href="../../static/img/android-screenshot-add-instant.jpg"><img src="../../static/img/android-screenshot-add-instant.jpg"/></a>
|
||||||
|
<a href="../../static/img/android-screenshot-add-other.jpg"><img src="../../static/img/android-screenshot-add-other.jpg"/></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
If those screenshots are still not enough, here's a video:
|
||||||
|
|
||||||
|
<figure>
|
||||||
|
<video controls muted autoplay loop width="650" src="../../static/img/overview.mp4"></video>
|
||||||
|
<figcaption>Sending push notifications to your Android phone</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
### Message priority
|
||||||
|
When you [publish messages](../publish.md#message-priority) to a topic, you can define a priority. This priority defines
|
||||||
|
how urgently Android will notify you about the notification, and whether they make a sound and/or vibrate.
|
||||||
|
|
||||||
|
By default, messages with default priority or higher (>= 3) will vibrate and make a sound. Messages with high or urgent
|
||||||
|
priority (>= 4) will also show as pop-over, like so:
|
||||||
|
|
||||||
|
<figure markdown>
|
||||||
|
![priority notification](../static/img/priority-notification.png){ width=500 }
|
||||||
|
<figcaption>High and urgent notifications show as pop-over</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
You can change these settings in Android by long-pressing on the app, and tapping "Notifications". You can then configure
|
||||||
|
the settings (and custom sounds or vibration) for each of the priorities:
|
||||||
|
|
||||||
|
<figure markdown>
|
||||||
|
![notification settings](../static/img/android-notification-settings.png){ width=500 }
|
||||||
|
<figcaption>Per-priority sound/vibration settings</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
### Instant delivery
|
### Instant delivery
|
||||||
Instant delivery is allows you to receive messages on your phone instantly, **even when your phone is in doze mode**, i.e.
|
Instant delivery is allows you to receive messages on your phone instantly, **even when your phone is in doze mode**, i.e.
|
||||||
|
@ -3,9 +3,12 @@ You can use the Web UI to subscribe to topics as well. If you do, and you keep t
|
|||||||
pop up as desktop notifications**. Simply type in the topic name and click the *Subscribe* button. The browser will
|
pop up as desktop notifications**. Simply type in the topic name and click the *Subscribe* button. The browser will
|
||||||
keep a connection open and listen for incoming notifications.
|
keep a connection open and listen for incoming notifications.
|
||||||
|
|
||||||
<figure markdown>
|
To learn how to send messages, check out the [publishing page](../publish.md).
|
||||||
![web subscribe](../static/img/screenshot-web.png){ width=300 }
|
|
||||||
<figcaption>Subscribe via Web UI</figcaption>
|
<div id="web-screenshots" class="screenshots">
|
||||||
</figure>
|
<a href="../../static/img/web-subscribe.png"><img src="../../static/img/web-subscribe.png"/></a>
|
||||||
|
<a href="../../static/img/web-notification.png"><img src="../../static/img/web-notification.png"/></a>
|
||||||
|
<a href="../../static/img/web-detail.png"><img src="../../static/img/web-detail.png"/></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
Once subscribed, you can [publish messages](../publish.md) via `curl` or from without any of your scripts.
|
|
||||||
|
@ -33,7 +33,7 @@ theme:
|
|||||||
- search.highlight
|
- search.highlight
|
||||||
- search.share
|
- search.share
|
||||||
- navigation.sections
|
- navigation.sections
|
||||||
- navigation.instant
|
# - navigation.instant
|
||||||
- toc.integrate
|
- toc.integrate
|
||||||
- content.tabs.link
|
- content.tabs.link
|
||||||
extra:
|
extra:
|
||||||
@ -67,6 +67,8 @@ markdown_extensions:
|
|||||||
|
|
||||||
plugins:
|
plugins:
|
||||||
- search
|
- search
|
||||||
|
- minify:
|
||||||
|
minify_html: true
|
||||||
|
|
||||||
nav:
|
nav:
|
||||||
- "Getting started": index.md
|
- "Getting started": index.md
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
<meta property="og:type" content="website" />
|
<meta property="og:type" content="website" />
|
||||||
<meta property="og:locale" content="en_US" />
|
<meta property="og:locale" content="en_US" />
|
||||||
<meta property="og:site_name" content="ntfy.sh" />
|
<meta property="og:site_name" content="ntfy.sh" />
|
||||||
<meta property="og:title" content="ntfy.sh | send push notifications to your phone via simple PUT/POST requests" />
|
<meta property="og:title" content="ntfy.sh | send push notifications to your phone or desktop via PUT/POST" />
|
||||||
<meta property="og:description" content="ntfy is a simple HTTP-based pub-sub notification service. It allows you to send desktop notifications via scripts from any computer, entirely without signup or cost. Made with ❤ by Philipp C. Heckel, Apache License 2.0, source at https://heckel.io/ntfy." />
|
<meta property="og:description" content="ntfy is a simple HTTP-based pub-sub notification service. It allows you to send desktop notifications via scripts from any computer, entirely without signup or cost. Made with ❤ by Philipp C. Heckel, Apache License 2.0, source at https://heckel.io/ntfy." />
|
||||||
<meta property="og:image" content="/static/img/ntfy.png" />
|
<meta property="og:image" content="/static/img/ntfy.png" />
|
||||||
<meta property="og:url" content="https://ntfy.sh" />
|
<meta property="og:url" content="https://ntfy.sh" />
|
||||||
@ -104,7 +104,7 @@
|
|||||||
<p id="error"></p>
|
<p id="error"></p>
|
||||||
<p>
|
<p>
|
||||||
Subscribe to topics here and receive messages as <b>desktop notification</b>. Topics are not password-protected,
|
Subscribe to topics here and receive messages as <b>desktop notification</b>. Topics are not password-protected,
|
||||||
so choose a name that's not easy to guess. Once subscribed, you can publish messages via PUT/POST.
|
so choose a name that's not easy to guess.
|
||||||
</p>
|
</p>
|
||||||
<form id="subscribeForm">
|
<form id="subscribeForm">
|
||||||
<p>
|
<p>
|
||||||
|
Before Width: | Height: | Size: 253 KiB After Width: | Height: | Size: 297 KiB |
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 116 KiB |