Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time


patchless is a standard for modular ui apps. It's primarily intended for secure scuttlebutt, but not actually directly coupled to ssb.


clone this repo, npm install, and then run electro index.js (you won't see much ;) then edit index.js, comment out different modules and see that it still works.

you'll also need to be running ssb-names plugin on your sbot.


This repo will not become a fully fledged, shiny, ssb app. It will be a rough developer toolkit. I aim for this to be the easiest way to create a customized patchapp, or insert a new feature into any application derived from patchless!

There will be very little code in this repo, mainly it will become documentation for patchless interfaces.


  • write up interfaces as precisely as possible.
  • design compose interface?
  • message extras interfaces?
  • support multiple identities early, to make sure they get in on the ground floor.



nav: {
  gives: {
    screen (): returns root layout html element,
      supporting hypertabs focus|blur events on change,
      and hyperloadmore hasmore|readymore events on scroll.
    goto (path): move the view to another app
  needs: {
    app: {
      view (path): from app, loads a feed or document view
      menu (): from app, returns path that view(path) will render a view.
        the layout should present this to the user in some way so that they can navigate to it.

nav manages navigation between screens. patchnav-basic system might use forward/back navigation patchnav-tabs system uses tabs. You can switch between these two and everything else still works. The role of the nav module is quite similar to a window manager.

The nav needs a list of top level views (feeds) which can be navigated to or displayed by default. to navigate to a document view, follow a link from a top level feed.

The layout also manages navigation to links. There are two ways that links are handled, either there is a <a href=...> which is clicked (here the layout catches the click when it bubbles up to window.onclick) or a click handler on an element calls goto(href, opts) (opts can be provided to open externally, as a new tab, or as the layouts default mode, and wether to focus to the opened element)

the nav interface is also responsible for managing scrolling. currently, patchless uses hyperloadmore for scrolling. This gives the choice of either infinite scrolling, or "load more" buttons. Also, this moves the complicated part into the layout, and apps just need to handle 'hasmore' and 'readymore' events, this makes it easy to switch layouts with the same apps.

gives: nav.screen, nav.goto needs: app.view (first), (map)


app: {
  gives: {
    view (path): returns html element.
      if this view is a feed/index it should interact with hasmore|readymore events.
    menu (): returns the paths this app needs statically.

A view is a part of an application that is open at one time.

The view takes a string which is the identify for this view, and returns an html element (which may dynamically update)

A string is used so that it's easy to keep a map of the currently open views, and also so that a link to a view can be represented as a href. If to express an location as an object, it can be encoded as a query string.

there are 3 ways I can think of that a view might be used.

app.view: feed

A feed is a view which is a continious list of objects, for example new messages, private messages, search results, open events, user feed. It might be the result of a user action or it might be built into the app (say, just a single view like /public)

A feed is likely to have an infinite scroll bar.

A feed that does not need arguments should also give a menuItem so that the layout can provide navigation to the view.

app.view: document / thread

A thread is the simplest example of a document view. This shows messages related to a single message. for example, a message thread. The messages that make up the document are interpreted as a "single object". A thread renders this as just a list of messages, and a gathering renders this as updates to the same object but it's similar from a data design perspective.

A document usually does not have an infinite scroll bar. a document also does not give a menuItem, instead the user navigates to it via the feed.

gives: view (id) => element

app.view: state

The third sort of screen is just about local application state that is not represented as messages or feeds. for example, local peers, gossip state, etc.


Then there are other miscelanious components that make up an application.

These must have a well documented api. so that each api can be switched to different implementations.


gives: avatar.image (id) => img_element (id) => string


compose and confirm? identity (for switch identies?)




No description, website, or topics provided.







No releases published


No packages published