How to make Tiddlywiki an installable PWA (Progressive Web App)

I want to share a way I found to make Tiddlywiki installable as PWA, this allow for example to have Tiddlywiki as “app” on the smartphone. This is not very dissimilar from having a bookmark but it suit me better.

It only works for hosted wikis, both as single page or using the node backend, because for a PWA to be installable is necessary to have it served via https.

Demo: My TiddlyWiki — a non-linear personal web notebook , on Chrome the app should be installable after some interaction with the website (What does it take to be installable?).

Screenshot_20230609_210301

It is possible to inspect the properties (and installability) of the manifest from the Chrome Dev Tools - Application tab.

It’s based on a couple of tiddler plus a couple of icons, $:/manifest-link to add a link in the <head/> (using $:/tags/RawMarkupWikified/TopHead tag) and $:/manifest.json that generate the manifest.

$:/manifest-link
tags: $:/tags/RawMarkupWikified/TopHead
title: $:/manifest-link
type: text/vnd.tiddlywiki

<$wikify
  name=manifest
  text={{$:/manifest.json}}>

`<link
    rel="manifest"
    href="`<$macrocall
                $name="makedatauri"
                text=<<manifest>>
                type="application/json"
                $output="text/plain" 
           />`"
>`

</$wikify>
$:/manifest.json
tags: 
title: $:/manifest.json
type: text/vnd.tiddlywiki

`{
  "name": "`{{$:/SiteTitle}}`",
  "description": "`{{$:/SiteSubtitle}}`",
  "short_name": "`{{$:/SiteTitle}}`",
  "theme_color": "#4682B4",
  "background_color": "#4682B4",
  "display": "standalone",
  "orientation": "portrait",
  "scope": "/",
  "start_url": "`{{$:/info/url/full}}`",
  "icons": [
    {
      "src": "`<<datauri "icon-192x192.png">>`",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "`<<datauri "icon-512x512.png">>`",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}`

Alternatively is possible to get the manifest from the node back-end, my understanding is that because the manifest is rendered on its own (and not in the context of the wiki) is also necessary to load macros with \import.

alternative $:/manifest-link
`<link rel="manifest" crossorigin="use-credentials" href="/%24%3A%2Fmanifest.json">`
alternative $:/manifest.json

\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]

tags: 
title: $:/manifest.json
type: text/vnd.tiddlywiki

`{
  "name": "`{{$:/SiteTitle}}`",
  "description": "`{{$:/SiteSubtitle}}`",
  "short_name": "`{{$:/SiteTitle}}`",
  "theme_color": "#4682B4",
  "background_color": "#4682B4",
  "display": "standalone",
  "orientation": "portrait",
  "scope": "/",
  "start_url": "https://carlo-colombo.github.io/tiddlywiki-pwa",
  "icons": [
    {
      "src": "`<<datauri "icon-192x192.png">>`",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "`<<datauri "icon-512x512.png">>`",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}`

I suppose there are ways to improve/simplify, e.g. I tried to use the icon present by default (e.g. $:/core/icon) but I have not been able to generate a valid svg data uri comprehensible to chrome.

4 Likes

Great, seems your approach is easier to be pack as a plugin.

I have created GitHub - tiddly-gittly/service-worker: Use service worker to cache content, make it works even offline, and can be add to the desktop as an App. , but it require manually add a manifest.webmanifest to the /public folder, and use github action to deploy to gh-pages.

Hi Carlo
Welcome to the club!

Cool stuff. I did test it with Edge on Windows 11 and it works. It can be installed as an app.

This should definitely be part of the core. I’ll have a closer look at the code, to see how we can convert it into a PR for v5.3.0 …

I did read the docs about the icons. It seems they can be SVGs. Some experiments will be needed. So the manifest can look a bit cleaner.

Do you have a GitHub repo with the code. It’s no problem if not. I can have a look at the wiki itself. But I could contribute to your repo, instead of creating my own one.

I did a bit more testing with the GitHub Saver and the wiki installed as an Edge-app Windows 11 desktop
The wiki uses external tiddlywikicore-xxx.js so saving is fast.
Installed the app using FF on android phone. … Saving works there too \o/

The only thing that is important with that setting is, that every browser / app needs it’s own access token. But that’s easy enough to generate and copy paste.

Thanks for sharing @carlo-colombo, and welcome to the community.

I am interested in a PWA edition of TiddlyWiki, but I was imagining it working slightly differently from the usual configurations. It would live at a standard URL like https://app.tiddlywiki.com/ and would use the new file system APIs to access TiddlyWiki files directly in the users file system. In other words, it would be similar to something like https://squoosh.app/ or SVGOMG - SVGO's Missing GUI.

1 Like

Thanks all!!

Yes they are, but I have not been able to find the correct combination of filters and macro to have a data uri svg string in the json manifest in a way understandable to the browsers.

No I don’t, I just started experimenting with the tiddlers above, and I setup github pages for easier sharing, but is just the static index.html. I did not look how to contribuite it to core.

I don’t know how the github saver works, and is not clear to me from the docs. Does it saves tokens in the browser to be able to sync back?

My current setup is with the server edition deployed, so I can have easy access from multiple devices and interact through the API too (to create and read tiddlers), the installable app is mostly a shortcut because the android launcher that I am using does not support links. I suppose that with the standard URL app it would still be possible to sync it to a remote sever for sharing across devices.

1 Like

Yes. I’ll share some more info here. So you’ll be able to save back to the gh-pages. GitHub did change there auth-tokens recently. … There should be much more fine grained control. But I do have to read that doc first :wink:

The auth-token will be stored in the browser local storage. So no secrets will be sent back to github. Only the the single page wiki will be saved back.

Latest chromium based browsers do allow users to save the wiki, with a relatively “new” api back to the local filesystem. This mechanism is called file system access API.

So the “app” lives in the web on a server, but it does read the data from the users filesystem. For well designed apps, no data should be sent back to the server.

There are some projects already, that allow users to use that mechanism with TW, but the workflow is still a bit “bumpy”.

Sadly (for me) FireFox does not support that api yet :confused:

2 Likes

I use this method, but get-manifest.js must become a shadow file to read manifest.json and pwa to work normally. Can the startup sequence of routes be controlled?

/*\
title: $:/plugins/oeyoews/neotw-pwa/routes/get-manifest.js
type: application/javascript
module-type: route

GET /manifest.json

\*/
(function () {
  /*jslint node: true, browser: true */
  /*global $tw: false */
  "use strict";

  exports.method = "GET";

  // exports.after = "story";

  exports.path = /^\/manifest.json$/;

  exports.handler = function (request, response, state) {
    var buffer = state.wiki.getTiddlerText("$:/manifest.json", ""); // 修改文件名
    state.sendResponse(200, { "Content-Type": "application/json" }, buffer);
  };
})();

Folks,

This is a very important development can we look at taking this mainstream so designers can deliver their own PWA impementations?

I use tw-reciever on a host as well as tiddlyhost as internet facing servers can we use these?

The ability for someone to install a PWA and not save back to the server but own their own data is a very useful way to distribute solutions and editions.

  • Can this be made to work?

Technically tw 5.3.x has new features such as HTTP Requests in WikiText which may support this endevor.

I could imagin a plugin, plus configuration creating a PWA