diff --git a/docs/config.md b/docs/config.md index 56db10c..4f9afc0 100644 --- a/docs/config.md +++ b/docs/config.md @@ -21,7 +21,7 @@ If desired, ntfy can temporarily keep notifications in an in-memory or an on-dis of time is important to allow [phones](subscribe/phone.md) and other devices with brittle Internet connections to be able to retrieve notifications that they may have missed. -By default, ntfy keeps messages in memory for 12 hours, which means that **cached messages do not survive an application +By default, ntfy keeps messages **in-memory for 12 hours**, which means that **cached messages do not survive an application restart**. You can override this behavior using the following config settings: * `cache-file`: if set, ntfy will store messages in a SQLite based cache (default is empty, which means in-memory cache). @@ -29,7 +29,7 @@ restart**. You can override this behavior using the following config settings: * `cache-duration`: defines the duration for which messages are stored in the cache (default is `12h`) Subscribers can retrieve cached messaging using the [`poll=1` parameter](subscribe/api.md#polling), as well as the -[`since=` parameter](subscribe/api.md#since). +[`since=` parameter](subscribe/api.md#fetching-cached-messages). ## Behind a proxy (TLS, etc.) @@ -42,27 +42,27 @@ flag. This will instruct the [rate limiting](#rate-limiting) logic to use the `X identifier for a visitor, as opposed to the remote IP address. If the `behind-proxy` flag is not set, all visitors will be counted as one, because from the perspective of the ntfy server, they all share the proxy's IP address. -**TLS/SSL:** ntfy supports HTTPS/TLS by setting the `listen-https` config option. However, if you are behind a proxy, it is -recommended that TLS/SSL termination is done by the proxy itself. +**TLS/SSL:** ntfy supports HTTPS/TLS by setting the `listen-https` [config option](#config-options). However, if you +are behind a proxy, it is recommended that TLS/SSL termination is done by the proxy itself. ## Firebase (FCM) !!! info - Using Firebase is **optional** and only works if you modify and build your own Android .apk. + Using Firebase is **optional** and only works if you modify and [build your own Android .apk](develop.md#android-app). For a self-hosted instance, it's easier to just not bother with FCM. [Firebase Cloud Messaging (FCM)](https://firebase.google.com/docs/cloud-messaging) is the Google approved way to send push messages to Android devices. FCM is the only method that an Android app can receive messages without having to run a [foreground service](https://developer.android.com/guide/components/foreground-services). -For the main host [ntfy.sh](https://ntfy.sh), the [ntfy Android App](subscribe/phone.md) uses Firebase to send messages +For the main host [ntfy.sh](https://ntfy.sh), the [ntfy Android app](subscribe/phone.md) uses Firebase to send messages to the device. For other hosts, instant delivery is used and FCM is not involved. To configure FCM for your self-hosted instance of the ntfy server, follow these steps: 1. Sign up for a [Firebase account](https://console.firebase.google.com/) -2. Create an app and download the key file (e.g. `myapp-firebase-adminsdk-ahnce-....json`) +2. Create a Firebase app and download the key file (e.g. `myapp-firebase-adminsdk-...json`) 3. Place the key file in `/etc/ntfy`, set the `firebase-key-file` in `config.yml` accordingly and restart the ntfy server -4. Build your own Android .apk following [these instructions]() +4. Build your own Android .apk following [these instructions](develop.md#android-app) Example: ``` @@ -100,7 +100,7 @@ During normal usage, you shouldn't encounter this limit at all, and even if you reconnect after a connection drop), it shouldn't have any effect. ## Config options -Each config options can be set in the config file `/etc/ntfy/config.yml` (e.g. `listen-http: :80`) or as a +Each config option can be set in the config file `/etc/ntfy/config.yml` (e.g. `listen-http: :80`) or as a CLI option (e.g. `--listen-http :80`. Here's a list of all available options. Alternatively, you can set an environment variable before running the `ntfy` command (e.g. `export NTFY_LISTEN_HTTP=:80`). @@ -110,8 +110,8 @@ variable before running the `ntfy` command (e.g. `export NTFY_LISTEN_HTTP=:80`). | `listen-https` | `NTFY_LISTEN_HTTPS` | `[host]:port` | - | Listen address for the HTTPS web server. If set, you also need to set `key-file` and `cert-file`. | | `key-file` | `NTFY_KEY_FILE` | *filename* | - | HTTPS/TLS private key file, only used if `listen-https` is set. | | `cert-file` | `NTFY_CERT_FILE` | *filename* | - | HTTPS/TLS certificate file, only used if `listen-https` is set. | -| `firebase-key-file` | `NTFY_FIREBASE_KEY_FILE` | *filename* | - | If set, also publish messages to a Firebase Cloud Messaging (FCM) topic for your app. This is optional and only required to save battery when using the Android app. | -| `cache-file` | `NTFY_CACHE_FILE` | *filename* | - | If set, messages are cached in a local SQLite database instead of only in-memory. This allows for service restarts without losing messages in support of the since= parameter. | +| `firebase-key-file` | `NTFY_FIREBASE_KEY_FILE` | *filename* | - | If set, also publish messages to a Firebase Cloud Messaging (FCM) topic for your app. This is optional and only required to save battery when using the Android app. See [Firebase (FCM](#firebase-fcm). | +| `cache-file` | `NTFY_CACHE_FILE` | *filename* | - | If set, messages are cached in a local SQLite database instead of only in-memory. This allows for service restarts without losing messages in support of the since= parameter. See [message cache](#message-cache). | | `cache-duration` | `NTFY_CACHE_DURATION` | *duration* | 12h | Duration for which messages will be buffered before they are deleted. This is required to support the `since=...` and `poll=1` parameter. | | `keepalive-interval` | `NTFY_KEEPALIVE_INTERVAL` | *duration* | 30s | Interval in which keepalive messages are sent to the client. This is to prevent intermediaries closing the connection for inactivity. Note that the Android app has a hardcoded timeout at 77s, so it should be less than that. | | `manager-interval` | `$NTFY_MANAGER_INTERVAL` | *duration* | 1m | Interval in which the manager prunes old messages, deletes topics and prints the stats. | diff --git a/docs/examples.md b/docs/examples.md index b49d6ca..1359331 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -18,7 +18,7 @@ rsync -a root@laptop /backups/laptop \ ## Server-sent messages in your web app Just as you can [subscribe to topics in the Web UI](subscribe/web.md), you can use ntfy in your own -web application. Check out the live example or just look the source of this page. +web application. Check out the live example or just look the source of this page. ## Notify on SSH login Years ago my home server was broken into. That shook me hard, so every time someone logs into any machine that I diff --git a/docs/faq.md b/docs/faq.md index 947fcce..351ad5e 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -22,23 +22,24 @@ client network disruptions. ## Can I self-host it? Yes. The server (including this Web UI) can be self-hosted, and the Android app supports adding topics from -your own server as well. There are install instructions -on GitHub. +your own server as well. Check out the [install instructions](install.md). ## Why is Firebase used? In addition to caching messages locally and delivering them to long-polling subscribers, all messages are also published to Firebase Cloud Messaging (FCM) (if `FirebaseKeyFile` is set, which it is on ntfy.sh). This -is to facilitate instant notifications on Android. -

+is to facilitate notifications on Android. + +If you do not care for Firebase, I suggest you install the [F-Droid version](https://f-droid.org/en/packages/io.heckel.ntfy/) +of the app and [self-host your own ntfy server](install.md). ## How much battery does the Android app use? -If you use the ntfy.sh server and you don't use the instant delivery feature, the Android app uses no -additional battery, since Firebase Cloud Messaging (FCM) is used. If you use your own server, or you use -instant delivery, the app has to maintain a constant connection to the server, which consumes about 4% of -battery in 17h of use (on my phone). I use it and it makes no difference to me. +If you use the ntfy.sh server and you don't use the [instant delivery](subscribe/phone.md#instant-delivery) feature, +the Android app uses no additional battery, since Firebase Cloud Messaging (FCM) is used. If you use your own server, +or you use *instant delivery*, the app has to maintain a constant connection to the server, which consumes about 4% of +battery in 17h of use (on my phone). I use it, and it makes no difference to me. ## What is instant delivery? -Instant delivery is a feature in the Android app. If turned on, the app maintains a constant connection to the +[Instant delivery](subscribe/phone.md#instant-delivery) is a feature in the Android app. If turned on, the app maintains a constant connection to the server and listens for incoming notifications. This consumes additional battery, but delivers notifications instantly. diff --git a/docs/index.md b/docs/index.md index c6a42cc..9e9a3d2 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,8 +1,79 @@ # Getting started +ntfy lets you **send push notifications to your phone or desktop via scripts from any computer**, using simple HTTP PUT +or POST requests. I use it to notify myself when scripts fail, or long-running commands complete. -**ntfy** (pronounce: *notify*) is a simple HTTP-based [pub-sub](https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern) -notification service. It allows you to **send push notifications to your phone or desktop via scripts from any computer**, -entirely **without signup, cost or setup**. It's [open source](https://github.com/binwiederhier/ntfy) if you want to run your own. +## Step 1: Get the app + + + + +To [receive notifications on your phone](subscribe/phone.md), install the app, either via Google Play or F-Droid. +Once installed, open it and subscribe to a topic of your choosing. Topics don't have to explicitly be created, so just +pick a name and use it later when you [publish a message](publish.md). Note that **topic names are public, so it's wise +to choose something that cannot be guessed easily.** + +For this guide, we'll just use `mytopic` as our topic name: + +
+ ![adding a topic](static/img/getting-started-add.png){ width=500 } +
Creating/adding your first topic
+
+ +That's it. After you tap "Subscribe", the app is listening for new messages on that topic. + +## Step 2: Send a message +Now let's [send a message](publish.md) to our topic. It's easy in every language, since we're just using HTTP PUT or POST. The message +is in the request body. Here's an example showing how to publish a simple message using a POST request: + +=== "Command line (curl)" + ``` + curl -d "Backup successful 😀" ntfy.sh/mytopic + ``` + +=== "HTTP" + ``` http + POST /mytopic HTTP/1.1 + Host: ntfy.sh + + Backup successful 😀 + ``` + +=== "JavaScript" + ``` javascript + fetch('https://ntfy.sh/mytopic', { + method: 'POST', // PUT works too + body: 'Backup successful 😀' + }) + ``` + +=== "Go" + ``` go + http.Post("https://ntfy.sh/mytopic", "text/plain", + strings.NewReader("Backup successful 😀")) + ``` + +=== "PHP" + ``` php-inline + file_get_contents('https://ntfy.sh/mytopic', false, stream_context_create([ + 'http' => [ + 'method' => 'POST', // PUT also works + 'header' => 'Content-Type: text/plain', + 'content' => 'Backup successful 😀' + ] + ])); + ``` + +This will create a notification that looks like this: + +
+ ![basic notification](static/img/basic-notification.png){ width=500 } +
Android notification
+
+ +That's it. You're all set. Go play and read the rest of the docs. I highly recommend reading at least the page on +[publishing messages](publish.md), as well as the detailed page on the [Android app](subscribe/phone.md). + +Here's another video showing the entire process:
diff --git a/docs/install.md b/docs/install.md index ca2137d..66c6e1c 100644 --- a/docs/install.md +++ b/docs/install.md @@ -1,7 +1,10 @@ # Install your own ntfy server -The following steps are only required if you want to **self-host your own ntfy server**. If you just want to -[send messages using ntfy.sh](publish.md), you don't need to install anything. Just use `curl` -or your favorite HTTP client. +**Self-hosting your own ntfy server** is pretty straight forward. Just install the binary, package or Docker image, then +configure it and run it. Just like any other software. No fuzz. + +!!! info + The following steps are only required if you want to **self-host your own ntfy server**. If you just want to + [send messages using ntfy.sh](publish.md), you don't need to install anything. ## General steps The ntfy server comes as a statically linked binary and is shipped as tarball, deb/rpm packages and as a Docker image. @@ -129,7 +132,7 @@ The [ntfy image](https://hub.docker.com/r/binwiederhier/ntfy) is available for a straight forward to use. The server exposes its web UI and the API on port 80, so you need to expose that in Docker. To use the persistent -message cache, you also need to map a volume to `/var/cache/ntfy`. To change other settings, you should map `/etc/ntfy`, +[message cache](config.md#message-cache), you also need to map a volume to `/var/cache/ntfy`. To change other settings, you should map `/etc/ntfy`, so you can edit `/etc/ntfy/config.yml`. Basic usage (no cache or additional config): diff --git a/docs/privacy.md b/docs/privacy.md index b5f0aa5..5a36a1c 100644 --- a/docs/privacy.md +++ b/docs/privacy.md @@ -1,7 +1,7 @@ # Privacy policy -I love free software, and I'm doing this because it's fun. I have no bad intentions, and I will -never monetize or sell your information. This service will always stay free and open. +I love free software, and I'm doing this because it's fun. I have no bad intentions, and **I will +never monetize or sell your information, and this service and software 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 any outside service. All data is exclusively used to make the service function properly. The only external service diff --git a/docs/static/css/extra.css b/docs/static/css/extra.css index ac44b52..797c1aa 100644 --- a/docs/static/css/extra.css +++ b/docs/static/css/extra.css @@ -6,9 +6,14 @@ article { padding-bottom: 50px; } -figure img { +figure iframe, figure img, figure video { + filter: drop-shadow(3px 3px 3px #ccc); border-radius: 7px; - filter: drop-shadow(3px 3px 5px #ccc); +} + +figure video { + width: 100%; + max-height: 450px; } .remove-md-box { diff --git a/docs/static/img/getting-started-add.png b/docs/static/img/getting-started-add.png new file mode 100644 index 0000000..28309c4 Binary files /dev/null and b/docs/static/img/getting-started-add.png differ diff --git a/docs/static/img/web-pin.png b/docs/static/img/web-pin.png new file mode 100644 index 0000000..3312a50 Binary files /dev/null and b/docs/static/img/web-pin.png differ diff --git a/docs/subscribe/api.md b/docs/subscribe/api.md index 06b97d8..b4449cf 100644 --- a/docs/subscribe/api.md +++ b/docs/subscribe/api.md @@ -168,12 +168,12 @@ format of the message. It's very straight forward: | Field | Required | Type | Example | Description | |---|---|---|---|---| | `id` | ✔️ | *string* | `hwQ2YpKdmg` | Randomly chosen message identifier | -| `time` | ✔️ | *int* | 1635528741 | Message date time, as Unix time stamp | +| `time` | ✔️ | *int* | `1635528741` | Message date time, as Unix time stamp | | `event` | ✔️ | `open`, `keepalive` or `message` | `message` | Message type, typically you'd be only interested in `message` | | `topic` | ✔️ | *string* | `topic1,topic2` | Comma-separated list of topics the message is associated with; only one for all `message` events, but may be a list in `open` events | | `message` | - | *string* | `Some message` | Message body; always present in `message` events | | `title` | - | *string* | `Some title` | Message [title](../publish.md#message-title); if not set defaults to `ntfy.sh/` | -| `tags` | - | *string array* | `["tag1","tag2"]` | List of [tags](../publish.md#tags--emojis--) that may or not map to emojis | +| `tags` | - | *string array* | `["tag1","tag2"]` | List of [tags](../publish.md#tags-emojis) that may or not map to emojis | | `priority` | - | *1, 2, 3, 4, or 5* | `4` | Message [priority](../publish.md#message-priority) with 1=min, 3=default and 5=max | Here's an example for each message type: diff --git a/docs/subscribe/phone.md b/docs/subscribe/phone.md index bfa5971..c97a8f5 100644 --- a/docs/subscribe/phone.md +++ b/docs/subscribe/phone.md @@ -51,7 +51,7 @@ the settings (and custom sounds or vibration) for each of the priorities:
### 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 allows you to receive messages on your phone instantly, **even when your phone is in doze mode**, i.e. when the screen turns off, and you leave it on the desk for a while. This is achieved with a foreground service, which you'll see as a permanent notification that looks like this: diff --git a/docs/subscribe/web.md b/docs/subscribe/web.md index 70313a6..3af6fcc 100644 --- a/docs/subscribe/web.md +++ b/docs/subscribe/web.md @@ -11,4 +11,10 @@ To learn how to send messages, check out the [publishing page](../publish.md). +To keep receiving desktop notifications from ntfy, you need to keep the website open. What I do, and what I highly recommend, +is to pin the tab so that it's always open, but sort of out of the way: +
+ ![pinned](../static/img/web-pin.png){ width=500 } +
Pin web app to move it out of the way
+
diff --git a/server/index.gohtml b/server/index.gohtml index 8d2c022..22700b8 100644 --- a/server/index.gohtml +++ b/server/index.gohtml @@ -4,7 +4,7 @@ - ntfy.sh | PUT/POST push notifications to your phone + ntfy.sh | Send push notifications to your phone via PUT/POST @@ -24,7 +24,7 @@ - + @@ -38,12 +38,13 @@ @@ -63,14 +64,10 @@ -

- There are many ways to use it: Notify yourself when a build finishes, when an rsync is done or a backup fails, - or know when somebody logs into your server. There are many more examples, endless possibilities 😀. -

Publishing messages

- Publishing messages can be done via PUT or POST. Topics are created on the fly by subscribing or publishing to them. + Publishing messages can be done via PUT or POST. Topics are created on the fly by subscribing or publishing to them. Because there is no sign-up, the topic is essentially a password, so pick something that's not easily guessable.

@@ -81,8 +78,8 @@

There are more features related to publishing messages: You can set a - notification priority, a title, - and tag messages. + notification priority, a title, + and tag messages. Here's an example using all of them:

@@ -93,6 +90,13 @@   -d "Remote access to $(hostname) detected. Act right away." \
  ntfy.sh/mytopic
+

+ Here's what that looks like in the Android app: +

+
+ +
Urgent notification with pop-over
+

Subscribe to a topic

@@ -110,9 +114,11 @@

- +

+ Here's a video showing the app in action: +

- +
Sending push notifications to your Android phone
@@ -143,7 +149,7 @@ as well as a plain text stream.

- Here's an example for JSON. Note that the connection stays open, so you can retrieve messages as they come in: + Here's an example for JSON. The connection stays open, so you can retrieve messages as they come in:

$ curl -s ntfy.sh/mytopic/json
@@ -152,24 +158,30 @@ {"id":"DGUDShMCsc","time":1635528787,"event":"keepalive","topic":"mytopic"}
...
-

- + Here's a short video demonstrating it in action:

+
+ +
Subscribing to the JSON stream with curl
+
-

More, more, more!

+

Check out the docs!

- ntfy has so many more features and you can learn about all of them in the documentation + ntfy has so many more features and you can learn about all of them in the documentation (I tried my very best to make it the best docs ever 😉, not sure if I succeeded, hehe).

+
+ +
Check out the documentation
+
- - -

Forever free, forever 100% free software

+

100% open source & forever free

I love free software, and I'm doing this because it's fun. I have no bad intentions, and I will - never monetize or sell your information. This service will always stay free and open. You can - read more in the FAQs and in the privacy policy. + never monetize or sell your information. This service will always stay + free and open. + You can read more in the FAQs and in the privacy policy.

Made with ❤️ by Philipp C. Heckel
diff --git a/server/static/css/app.css b/server/static/css/app.css index bd383fe..07dcc75 100644 --- a/server/static/css/app.css +++ b/server/static/css/app.css @@ -1,9 +1,10 @@ /* general styling */ html, body { - font-family: 'Lato', sans-serif; - color: #333; + font-family: 'Roboto', sans-serif; + font-weight: 400; font-size: 1.1em; + color: #444; margin: 0; padding: 0; } @@ -29,31 +30,41 @@ h1 { font-size: 2.5em; word-wrap: break-word; /* For very long topics */ padding-right: 40px; /* For the X on the detail page */ + font-weight: 300; + color: #666; } h2 { margin-top: 30px; margin-bottom: 5px; font-size: 1.8em; + font-weight: 300; + color: #333; } h3 { margin-top: 25px; margin-bottom: 5px; font-size: 1.3em; + font-weight: 300; + color: #333; } p { margin-top: 10px; margin-bottom: 20px; - font-size: 1.1em; - line-height: 140%; + line-height: 160%; + font-weight: 400; } p.smallMarginBottom { margin-bottom: 10px; } +b { + font-weight: 500; +} + tt { background: #eee; padding: 2px 7px; @@ -72,16 +83,36 @@ code { white-space: nowrap; } -/* Lato font (OFL), https://fonts.google.com/specimen/Lato#about, - embedded with the help of https://google-webfonts-helper.herokuapp.com/fonts/lato?subsets=latin */ +/* Roboto font, embedded with the help of https://google-webfonts-helper.herokuapp.com/fonts/roboto?subsets=latin */ +/* roboto-300 - latin */ @font-face { - font-family: 'Lato'; + font-family: 'Roboto'; + font-style: normal; + font-weight: 300; + src: local(''), + url('../font/roboto-v29-latin-300.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('../font/roboto-v29-latin-300.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* roboto-regular - latin */ +@font-face { + font-family: 'Roboto'; font-style: normal; font-weight: 400; src: local(''), - url('../font/lato-v17-latin-ext_latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ - url('../font/lato-v17-latin-ext_latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ + url('../font/roboto-v29-latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('../font/roboto-v29-latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* roboto-500 - latin */ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 500; + src: local(''), + url('../font/roboto-v29-latin-500.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('../font/roboto-v29-latin-500.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ } /* Main page */ @@ -119,6 +150,29 @@ code { visibility: visible; } +/* Figures */ + +figure { + text-align: center; +} + +figure img, figure video { + filter: drop-shadow(3px 3px 3px #ccc); + border-radius: 7px; + max-width: 100%; +} + +figure video { + width: 100%; + max-height: 450px; +} + +figcaption { + text-align: center; + font-style: italic; + padding-top: 10px; +} + /* Screenshots */ #screenshots { @@ -218,21 +272,20 @@ code { float: left; color: white; font-size: 2.6em; - font-weight: bold; + font-weight: 300; margin: 35px 0 0 20px; } #header ol { list-style-type: none; - float:right; + float: right; margin-top: 80px; } #header ol li { display: inline-block; margin: 0 10px; - font-weight: bold; - + font-weight: 400; } #header ol li a, nav ol li a:visited { @@ -273,6 +326,14 @@ li { font-size: 0.9em; } + +/* Hide top menu SMALL SCREEN */ +@media only screen and (max-width: 780px) { + #header ol { + display: none; + } +} + /* Subscribe box SMALL SCREEN */ @media only screen and (max-width: 1599px) { #subscribeBox #subscribeForm { diff --git a/server/static/font/lato-v17-latin-ext_latin-regular.woff b/server/static/font/lato-v17-latin-ext_latin-regular.woff deleted file mode 100644 index c6d3d1d..0000000 Binary files a/server/static/font/lato-v17-latin-ext_latin-regular.woff and /dev/null differ diff --git a/server/static/font/lato-v17-latin-ext_latin-regular.woff2 b/server/static/font/lato-v17-latin-ext_latin-regular.woff2 deleted file mode 100644 index 4153a82..0000000 Binary files a/server/static/font/lato-v17-latin-ext_latin-regular.woff2 and /dev/null differ diff --git a/server/static/font/roboto-v29-latin-300.woff b/server/static/font/roboto-v29-latin-300.woff new file mode 100644 index 0000000..5565042 Binary files /dev/null and b/server/static/font/roboto-v29-latin-300.woff differ diff --git a/server/static/font/roboto-v29-latin-300.woff2 b/server/static/font/roboto-v29-latin-300.woff2 new file mode 100644 index 0000000..46445bf Binary files /dev/null and b/server/static/font/roboto-v29-latin-300.woff2 differ diff --git a/server/static/font/roboto-v29-latin-500.woff b/server/static/font/roboto-v29-latin-500.woff new file mode 100644 index 0000000..c9eb5ca Binary files /dev/null and b/server/static/font/roboto-v29-latin-500.woff differ diff --git a/server/static/font/roboto-v29-latin-500.woff2 b/server/static/font/roboto-v29-latin-500.woff2 new file mode 100644 index 0000000..ce795fa Binary files /dev/null and b/server/static/font/roboto-v29-latin-500.woff2 differ diff --git a/server/static/font/roboto-v29-latin-regular.woff b/server/static/font/roboto-v29-latin-regular.woff new file mode 100644 index 0000000..86b3863 Binary files /dev/null and b/server/static/font/roboto-v29-latin-regular.woff differ diff --git a/server/static/font/roboto-v29-latin-regular.woff2 b/server/static/font/roboto-v29-latin-regular.woff2 new file mode 100644 index 0000000..ebe1795 Binary files /dev/null and b/server/static/font/roboto-v29-latin-regular.woff2 differ diff --git a/server/static/img/android-video-subscribe-api.mp4 b/server/static/img/android-video-subscribe-api.mp4 new file mode 100644 index 0000000..d73e5c6 Binary files /dev/null and b/server/static/img/android-video-subscribe-api.mp4 differ diff --git a/server/static/img/basic-notification.png b/server/static/img/basic-notification.png new file mode 100644 index 0000000..3a8a245 Binary files /dev/null and b/server/static/img/basic-notification.png differ diff --git a/server/static/img/priority-notification.png b/server/static/img/priority-notification.png new file mode 100644 index 0000000..31d1515 Binary files /dev/null and b/server/static/img/priority-notification.png differ