# Web Tiles Explainer
> User agents act as intermediaries between a service and the end user; rather than
> downloading an executable program from a service that has arbitrary access into the users'
> system, the user agent only allows limited access to display content and run code in a
> sandboxed environment. End users are diverse and the ability of a few user agents to
> represent individual interests properly is imperfect, but this arrangement is an
> improvement over the alternative — the need to trust a website completely with all
> information on your system to browse it.\
> [*RFC 8890: The Internet is for End Users*](https://www.rfc-editor.org/rfc/rfc8890#section-4.2-3),
> Mark Nottingham
Trust has been the defining constraint on the web's evolution towards more powerful, more
applicative capabilities. In a web context, the user must be able to safely load any
arbitrary URL, to safely click on any arbitrary link. The way in which this is achieved is
that the runtime places strict limits on what a web page can do, which in turn necessarily
limits powerful capabilities. App stores shift the trust around: apps get more powerful
capabilities but there is a review and enforcement bottleneck at the store level which is
load bearing for trust. This can open up more powerful capabilities but at the cost of
producing a chokepoint for rent extraction and self-serving policies. The system cannot
work without trust (user would face excessive harm and abandon it) and that trust must be
anchored somewhere.
Offloading trust to the user is not a promising option either. Fifteen years of W3C workshops
on permissions and consent on the web (and many other similar efforts) have succeeded in
only one thing: establishing that permissions and consent are not a promising avenue
through which to extend the web. More generally, installation ceremonies do not provide
the means for people to reason about different security models and, in some cases,
introduce undesirable differences between a page/app running locally or online.
To make matters worse, the web's trust model is anchored in [the same-origin security policy](https://www.w3.org/Security/wiki/Same_Origin_Policy). While this provides a
relatively natural boundary for user agents to reason about, it makes it difficult to
*compose* web services safely, which is to say to have two or more web pages cooperate to work for the user. Pages are not composable because novel threats emerge when
two origins are allowed to communicate with one another. This puts stringent limits on the
web's ability to allow people to combine two services together, which in turn limits the
web's usefulness.
Tiles provide a new approach to the problem of trust. A tile is a set of content-addressed
web resources that, once loaded, cannot communicate further with the network. This
additional safety makes it possible to grant tiles some powers with the trust that they
cannot exfiltrate data (or at least not without deliberate user interaction). Tiles can
additionally compose on the client side, to build a user-orchestrated application web
(rather than monolithic web apps).
- Tiles are **local-first and location agnostic**. Because a tile cannot exfiltrate content,
its content, once loaded, has to be sufficient to operate without touching the network.
And thanks to the fact that a tile is content-addressed, saving or "installing" a tile
simply means ensuring that it remains cached locally. *Publishing* a tile can happen
offline.
- Tiles are **multi-device** from the get-go. You can move a tile from your laptop to your
mobile phone to your TV safely and effortlessly.
- Tiles are designed to be **composable**. Having two or more tiles communicating together
should not produce a threat profile different from that of any of those tiles in isolation.
(Depending on where we land *exactly* in terms of security models, it is possible that
the threat profile may worsen some but it should be only in ways that the user agent can
reason about.) This is thanks in part to the fact that tiles cannot hit the network, and
all their other interactions are user-mediated.
- While the technology isn't ready yet, the fact that tiles build on content addressing
gives them a good hook to rely on some forms of
[**private retrieval**](https://research.protocol.ai/blog/2023/private-retrieval-grant-2023-roundup/)
that benefit from this.
- By essentially removing servers from the equation and moving the intelligence to the
agent, tiles **shift power to the user**.
Anyone who has built anything on the web should worry about the client-side nature of
tiles however: servers are useful for quite a few things, or at least that's the common
practice. In order to make up for that loss, we complement tiles with a number of key
APIs and with a specific client-side composition mechanism that makes it easy for tiles
to work with one another to create sophisticated, user-centric experiences. This can be
achieved with relatively minimal changes to how web pages are built and in a way that
supports better user experiences.
Trying to build web apps by copying native apps is like trying to build web pages by
emulating PDF. Sure, you do need some capabilities like arbitrary fonts and colours, but
it's a mistake to inherit the straightjacket and the antiquated design decisions. The
applicative capabilities that go with tiles are:
- **Wishes and local composability**: wishes are an iteration on intents/activities that
enables any tile to call upon other tiles (based on user preference) to handle specific
requests and conversely to provide services of its own to other tiles in an interoperable,
decoupled way. Modern primitives like UCANs align well with wishes when authorization is
desirable.
- **Gated access to specific protocols**: while tiles cannot `fetch` from protocols, they
can interact with them (e.g. post to ATProto or ActivityPub) in browser-gated ways.
- **Sophisticated local storage and provision**: tiles can write to a sophisticated local
storage system that can then be selectively shared (by the user) with other parties.
Submitting a form, for instance, is (at the conceptual level, the UX need not change)
editing an object in that storage and then sharing that object with the intended party.
There is growing interest in tile or tile-like approaches as noted at IPFS Thing 2023
where Capyloon, Peergos, and Protocol Labs all presented variations on this idea.
*This document is a batch of early notes and should not be considered to be stable or
definitive.*
## What's a Tile
A tile is a DAG-CBOR of metadata and content, available over IPFS. The metadata is
similar to that found in [Web Application Manifests](https://www.w3.org/TR/appmanifest/)
and the content is all of the web resources needed to run this tile. We don't use
the exact appmanifest format because tiles aren't a direct port of the notion of native
app to the web, and there is mismatch — but reuse applies where possible.
The purpose of the metadata is to provide functionality equivalent to embedding cards
(title, description, image, etc.) because tiles are expected not only to be rendered and
run in full, but also to be listed for instance in search results or social feeds. This
provides a hook into pages-as-objects that the web has struggled to hack together
consistently and that is particularly useful in a content-addressed world. It is also
a place to sign and assert authorship (and possibly other similar properties like peer
review), to declare usage rights or child-appropriate flags, to capture declarative wishes,
icons, and more.
Tiles load over the `tile://` scheme and the authority is a CID, e.g.
`tile://bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi/`. The CID is that
of the tile's metadata document which, in JSON, looks like:
```json
{
"name": "Fx Magic",
"description": "Fx Magic is a great image editor with plenty of great effects!",
"icons": [
{
"src": "fx.svg"
}
],
"resources": {
"/": {
"src": "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
"mediaType": "text/html"
},
"/fx.svg": {
"src": "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
"mediaType": "image/svg"
},
"/pretty.css": {
"src": "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
"mediaType": "text/css"
},
"/app.js": {
"src": "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
"mediaType": "application/javascript"
}
},
"wishes": [
{
"name": "Fx magic it!",
"can": "edit",
"what": ["image/*"]
}
]
}
```
Both `name` and `description` should be self-explanatory. They are used in contexts
in which the tile is listed but not rendered, for instance in feeds, search results,
social media timelines. All `icons` must be listed in `resources` if they are to
be resolved and used. The `resources` entry maps URL path components (in full) to
CIDs and media types required to load and render them. These essentially mint URLs
under the tile's authority, e.g. `tile://bafy…/pretty.css` and are resolved as such
at runtime. The `/` resource is shown by default.
:::info
IPFS supports directories for instance in UnixFS but that requires significantly more
work to consume and produce, and has impedance mismatch with web requirements. This
approach of having a single map of all resources keyed by path is more web-like.
:::
The `wishes` entry lists wishes that this tile can grant; in this case it is able to
edit images.
The loading context imposes a CSP equivalent to:
```
Content-Security-Policy: default-src 'self'
style-src 'self' 'unsafe-inline'
script-src 'self' 'unsafe-inline' 'wasm-unsafe-eval';
img-src 'self' blob:;
media-src 'self' blob:;
```
:::warning
**issues**
- We probably want to specify an interoperable set of CID options (v1, which multicodec
types) that are supported across the board.
- That CSP isn't exactly the one in cosmopolis, e.g. it doesn't have `data:`.
- We should look at WACZ: https://specs.webrecorder.net/wacz-ipfs/latest/#wacz-and-zip-file-chunking
:::
## Composing Tiles: Wishes/Intents/Activities
Users want to accomplish tasks more than they want to use any given app. The app-centric
model is limiting and the web can do better. Web apps have so far been modelled on native
apps: a blueprint for silos. Instead, we focus on dynamically linking tasks together to
create a seamless flow of interactions.
The existing technology matching this approach is
[Web Intents](https://www.w3.org/TR/web-intents/). Web Intents were developed (and abandoned) by
the W3C's Device APIs Working Group as a way to enable precisely the kind of composition
described here between Web pages. They were inspired by Android Intents. A number of alternative
designs were proposed at the time, one of which being Mozilla's
[WebActivities](https://wiki.mozilla.org/WebActivities) which is still in use in B2G.
The system used in tiles is tentatively named "wishes" so as not to conflict with an
existing design, but it's possible that we will end up adopting an existing one. (Capyloon
simply uses Web Activities for instance.)
A wish is a verb applied to a type of thing. A tile's metadata describes which wishes it
can grant.
```json
wishes: [
// this can pick images and return them
{
"can": "pick",
"what": ["image/*"],
"name": "Select an image from our cat memes collection"
},
// this can create a social post which the user can post
{
"can": "post",
"what": "com.atproto.repo.create",
"name": "Post a cat meme"
}
]
```
Whereas hyperlinks are nouns — they *name* things — wishes are verbs. In this sense, they are
comparable to HTTP's verbs (methods) but offer richer semantics that sit closer to user
applications and that can be fulfilled by the user agent.
When a verb is invoked, the agent typically needs to ask the user what they want to invoked it
on or with (e.g. which source pick images from, what to edit with). The tile making a wish has
a simple API:
```javascript
button.onclick = async () => {
const blob = await window.makeWish('pick', { what: ['image/*'] });
if (!blob) return message('Cancelled picking image.');
image.src = URL.createObjectURL(blob);
};
```
A wish can also be passed data that it can act on. This doesn't require trusting the party
that made that wish since that data has to remain on the client.
```javascript
const res = await fetch(`pic.jpg`); // from inside the tile itself
const blob = await res.blob();
const editedBlob = await window.makeWish('edit', { what: ['image/*'], data: blob });
```
A tile can handle a wish by listening to the `wish` event on its `window` and by
interacting with `currentWish`. (The API will almost certainly change some.)
To make this less abstract, we can walk through a couple of examples. We start with a very
basic tile that wants to obtain an image — it doesn't care about the source, that's up to the
user:
![Basic UI to pick an image, with a "Pick Pic" button](https://hackmd.io/_uploads/SykY-qnK2.png)
Clicking "Pick Pic" causes that tile to wish to `pick` and `image/*`. The user has a set
of image sources of their own depending on which tiles they have "installed":
![Same basic UI with also a list of potential sources for images](https://hackmd.io/_uploads/S1O-zc2Yn.png)
If the user selects "Pick random colour", this loads a tile the sole function of which is
to return an image made of a random colour. Not fascinating, perhaps, but we're not here
to judge: the web provides.
![A random shade of burgundy which can be picked or regenerated](https://hackmd.io/_uploads/BJhFf93K2.png)
Accepting that lovely shade of burgundy returns an image to the wishing tile:
![The original basic UI with an embedded block of burgundy](https://hackmd.io/_uploads/SJ9aGq2Yn.png)
Wishes can nest arbitrarily — the user ought to just flow from action to action. If instead
of going for the random colour we had chosen the "Pack of pics!" (just a tile containing a
curated list of pictures), we'd have seen:
![A list of nine pictures, each of which can be picked or edited](https://hackmd.io/_uploads/S1X_79nth.jpg)
Those images can be picked, in which case they would be returned to the wishing tile, but
each can also be edited first. Clicking "edit" with make a wish to edit that image:
![Pick an editor: Fx Magic](https://hackmd.io/_uploads/rkECQq2K2.jpg)
This user only has one image editor (the system also requires a way to discover wishes if
you don't have one): Fx Magic. Picking that, we get an advanced image manipulation system
provided by a completely different party — we use it to invert the blowfish:
![Image editing UI with a few filters and an inverted paper blowfish](https://hackmd.io/_uploads/BkVUNcnF3.jpg)
Accepting the edit returns the result to the pack of pic which in turn returns it to the
original calling tile:
![Initial basic UI with the edited blowfish](https://hackmd.io/_uploads/Syv3N93F2.jpg)
This is of course a trivial example, but we have made multiple unrelated parties compose
and collaborate safely, without any prior knowledge of one another (only the user and agent
connect them), in a way that presents no risk to the user of having their data shared with
arbitrary parties.
More involved interactions can be required when the wish is not about a simple request/response
action. For instance, we can think of a wish the purpose of which is to produce recommendations
for the user. The way it works when installed and active is that it receives lists of items of
the kind that it knows how to produce recommendations for, it filters out anything that it knows
should not be in the list (e.g. I've said I never want to read that author again), it ranks the
rest according to whatever applicable criteria (eg. using its own ML model or simply
chronologically), and returns that ranking to whatever tile is rendering the list. A wish can be
a very thin wrapper around a piece of WASM, for this kind of purpose. Eventually, the difference
between a tile and an extension becomes limited.
## Built-in Protocols
This section is just a sketch, more detailed work is needed but it can happen progressively.
The fact that a tile cannot touch the network means that a number of protocols must
be supported directly by the user agent. While this constrains the system, it also
creates a point of enforcement for open standards (if the agent itself is governed
well). These protocols must generally be activated by the user and not trivially
exposed to tiles lest they acquire the ability to exfiltrate data.
To begin with, **search must be a protocol**. This does not depart from earlier hypertext
systems (e.g. WAIS). People can configure multiple search sources, which can be queried
together, can have contextual uses, knobs, differentiated ranking options, etc. and the
user agent calls them via a protocol, collates the responses, and renders them. This
approach has great potential to improve user agency in search (and defend against capture
of the search market). It has consequences in terms of funding (and of the potential
funding of browsers themselves) that should be explored separately.
In a similar vein, **social must be a protocol**. Two things distinguish a social network
from another: one's identity and the graph of connections with others, and the format of
posts. Having multiple identities ought to be managed by the browser and the attached
social graphs should be part of the protocol (e.g. in the ATProto PDS that you use). The
format of posts is an unnecessary constraint: if the content of social feeds is itself
made of tiles, then since those tiles are safe when they load and run, the content of
a social feed can be essentially arbitrary. Better: using wishes, a tile can effectively
be a tile factory. So if I invent a new social publishing format, I can make a tile that
handles wishes to post by producing tiles matching that format.
Tiles also need **local storage with permissioned sharing**. Interacting with a form
should conceptually be using that form to edit the object it describes and then
sharing that with the intended party. (This means the form can be saved locally and
reused, too.) One option here is WNFS+UCAN. Another may be Solid, even though every
time I've looked there I've found the RDF to be beyond my reading level.
Rather than having every site that connects people together reinvent end-to-end chat
poorly, **it should be easy to put two endpoints in a Signal chat together**.
The list goes on: protocols for ads, for shopping cart management, for purchase, etc.
The idea is not that we need *all* of that for tiles to be useful; however we can use
tiles as a stepping stone to a world in which the core functions of the are handled
by protocols that give people real agency (and stop reinventing wheels poorly).
There is a careful balance so that we don't end up bundling every API in the world
into the agent, but we should be relatively expansive in terms of making tiles a
batteries-included system. A *lot* of web development is a repetitive invocation of
a small number of primitives; we can make both users' and developers' lives easier
by adding core primitives here.
## Feeds and Tile Modes
Tiles support multiple rendering modes: card and active. The reason for this is to
make it possible to embed an arbitrary number of tiles in a feed and show them
without triggering the run of a potentially unbounded number of separate rendering
processes.
The card rendering mode does not load the content or cause the runtime to run
anything. It simply exposes the content as a card that summarises it, as is often
done in search results or social media.
A lot of useful content on the web is lists: search results, social timelines,
curated RSS feeds. Instead of having each of these contexts reinvent which metadata
matters and come up with incompatible ways of producing and rendering it, the
built-in card view of a tile means that we can get a uniform behaviour across
all kinds of feeds. This makes it possible to treat tiles as objects consistently
across the UI. You can "repost" a tile to your social timeline directly from a
search result listing because a card can always have that affordance. You can
save a tile from a social timeline to a feed that you produce in your local
library, that may or may not be followable by others. You can just drag a tile
to the browser folder in which you keep the references you use for an ongoing
project. It's all uniform, browser-directed UI. (Tiles do assume that we reinvent
browser UIs beyond tabs.)
## Privacy Considerations
An important promise is that tiles can be more powerful by default
because they are safer by default: they cannot exfiltrate data, at
least not easily. This means that a tile can only load the resources
under its root, but once that is done it cannot touch the network
again. This is a very stringent constraint. The idea is to start
stringent and then see what can be opened.
### Considering the threat
We know from experience that privacy attackers are highly motivated.
Notably: they can dedicate significant resources to tracking
behaviour, they can be very inventive, they do not need perfect
data and are comfortable with probabilistic matching.
The threats of opening up arbitrary HTTP access are well-known
(see: the web). It's tempting to think that content-addressed
loading solves that. It does help, but it is not sufficient on its
own, at least not in its current state. We look at a few threats
to show how an attacker might proceed given IPFS-only loading.
#### Behavioural tracking
Here the goal is to produce an event stream about a person's
behaviour, presumably in order to profile that person and target
them with advertising.
An attacker could create CIDs for events of interest (which would
typically be a relatively restricted set) and cause those to be
loaded as a stream, observing the DHT as the requests are made and
identifying the person using timing and IP address. This would not
be perfect as the events would get cached, but it would be possible
to introduce enough variance to avoid that. There is a balance
between exposing an excessive number of CIDs and how much caching
may defeat you, but there is little doubt that an attacker would
figure out the most effective approach.
Note that in theory a tile's resources list could be created such that it
contains similarly crafted CIDs for events of interest. An
implementation that loads resources dynamically such that it fetches
only the blocks which are needed will be susceptible to this kind
of attack.
#### Geolocation tracking
If you make a GPS navigation app, the user can be tracked (coarsely,
but effectively enough) by paying attention to which map segments
the app loads (assuming the list of resources is the full geo tiling).
Since map segments are presumably known in advance (eg. from OpenStreetMap),
double-hashing doesn't help. This is a special case of BT.
#### Large Files (audio & video)
Another special case is tiles containing large data, notably audio and
video. You cannot expect the UA to load everything and so range requests
need to be included. But range requests can be used to signal bits back
to whoever is serving the content, a process which can be driven by
programmatically seeking around an audio or video resource.
This could be prevented by severely throttling just how much seeking can
happen.
### Escape hatch
It's important to remember that *not everything needs to be a
tile*. Ideally, a user agent would mix tiles and non-tile web
content, the difference being that tiles would have access to
more features and to composition. But we should recall that traditional
HTTP web pages are available and users' experience need not be
negatively impacted if they can navigate to both. The difficult
resides in ensuring that the UI clearly distinguishes the two
and makes it clear what functionality is available where.
A key issue is linking and navigation tracking prevention here.
If a tile links to an HTTP page, opening it in a separate UI
helps but the browser needs to strip nav tracking too.
### Mitigations
Some mitigations can be considered for a number of cases.
Generally, privacy need not be perfect, we primarily need to make
sure that tracking attacks are too costly or too unreliable.
One option would be that the initial top level resources can be loaded
directly (as being harder to track) and additional IPFS loads can be
triggered inside the tile but have to go through slower but more private
mechanisms such as Tor+IPFS.
Similarly, we could direct additional loads to trusted services,
for instance Saturn nodes on the edges that could offer guarantees
of privacy. We could consider additional mitigations such as
rendering such nodes observable and subject to slashing if they
participate in tracking.
We could also limit additional data loading to some publicly curated
datasets that we can guarantee sufficient distribution for. This
could include maps, weather data, or dependencies for JS, CSS,
icons, and fonts.
## Differences from Previous Proposals
Finding primitives and systems to support a more application-oriented (rather than
document-oriented) web has been a persistent problem of the past decades. Some additions
have proven useful (e.g. workers) while many others have floundered. Without attempting to
compare tiles with all previous approaches (there have been many), it is useful to
describe what sets tiles apart. Three things are worth teasing apart here: first, the
primitive itself, which is a relatively simple and constrained; second, some consequences
in terms of what becomes possible based on that primitive; and third some broader
(but brief) philosophical considerations about the overall approach in which this
primitive fits and which it furthers.
First, the key primitive underlying tiles is a strong sandboxing model that limits the
extraction of data much more severely than any prior proposals, once tiles are loaded
they cannot communicate back to the network, not even to their own origin. (In fact,
the notion of origin becomes at least partly moot.) We don't claim 100%
extraction-proof sandboxing because tiles can have links to non-tile web pages and
data can be extracted that way. (Those links have to be user-activated, but that only
affords so much protection even if
[nav-tracking protection](https://privacycg.github.io/nav-tracking-mitigations/) can help.)
However, for a great number of uses the sandboxing is effective. This makes tiles
composable in that the security and privacy properties of multiple tiles communicating
with one another are the same as those of any given individual tile.
Second, these properties have positive consequences. The sign of a good web primitive is
that it may not do much on its own but when composed with others things start happening.
The sandboxing means that we can consider exposing some more powerful capabilities out
of the box (notably in the class that creates privacy risk). It also means that we can
enable tiles to communicate with one another more. Given that they are composable without
additional risk, the properties of a system like Web Intents/Web Activities/Wishes match
tiles very well and open the door to strong client-side UI/task composability.
Finally, this primitive has desirable philosophical implications. By moving composition
from the server to the client, with loose joints that empower people to easily choose
how they wish to compose services, this system significantly increases user agency and
shifts power from servers to people. The user agent can also monitor interactions between
tiles and intervene when necessary (or at the very least render those interactions
available for auditing). Additionally, monolithic bundled apps have been a deeply
ingrained user-hostile pattern for a very long time. This approach may finally allow
us to move to a new model that aligns with people's expectations better.
One thing that is worth noting is that, because tiles are content addressed, we can get
a stronger and more predicatable sandboxing as well as a path towards privacy mitigations
in content loading since content need not be obtained from its origin. We also get
a more permanent web, and "installing" a tile is as simple as just keeping it around
locally — something that is very hard (impossible in the general case) over HTTP. You can
just pin your tiles, back them up, etc.
Arguably the biggest lift with tiles is in user interface: they probably do not work in
a classic tabbed browser UI and we probably shouldn't try to make that happen. While it
is key for the web to rely on the notion of user agents, there is nothing to say that the
current UI paradigm is right.
## Appendix: The Name
We are not in love with the name "tiles". It sort of works because they compose with one another on the client, horizontally, and so in a sense they *tesselate*.
Other options include:
- offgrids
- mycelia
- sensory deprivation
- tessel
Mood board:
* private
* can't phone home
* powerful + isolated
* composable
* networked with one another, horizontally
We further have the issue that the composability layer has been called both "intents"
and "activities", and it's tricky to pick between them, especially since both map to
existing APIs which we are certain to at least extend and probably change. (Even if
Web Intents aren't alive any more, on Android browsers can still invoke intents via
the `intent:` scheme.) The name we propose to use instead is "wish". You *wish* to
pick a picture or contact, you *wish* to share some content, you *wish* to edit a
video, etc. We can backronym it on demand, eg. *Web Intent System for Hyperapps*.
One option for tiles that would pair well with "wish" would be "mish". Basically,
web+mushrooms $\rightarrow$ mesh $\rightarrow$ mish (to get something different).
Modular Isolates {Soldered,Strapped,Strung,Sewn,Set up,Spread,Speaking,goSsinpping} Horizontally.
## Appendix: Notes from IPFS Thing, 2023-04-19
* not able to phone home is key property
* can't have composability if can phone home
* tracking/exfiltration is core threat model
* need to link to pages on the regular web, but how to not exfiltrate data
* block navigation entirely in proof of concept
* require user activation?
* use-case for activation: blog that links to individual post
* eg: ship arbitrary content to social media
* post cool app in tile, click on "install" to install the app
* social is tiles generating other tiles
* how to unpublish?
* you're fucked
* tombstoning, revocation, etc
* does need to be content addressed at start?
* sxg!
* start a new CA?
* no.
* ok ip tiles vs web tiles
* ip tiles -> content addressed
* maybe can sign w/ wallet
* (killer app format for dapps?)
* CBOR42 CAR
* metadata
* name
* icons
* cards
* CID (filesystem - winfs)
* index.html
* (MUST HAVE MIME TYPES)
* search
* tile
* tile
* tile
* tile rendering modes
* metadata mode
* active mode
* when fetching tiles for a list
* just get metadata blocks
* index just metadata blocks
* cannot just be links
* back to http problems
* tiles that create tiles
* intent handler
* click install
* instagram is a way of creating social that generates tile format
* browser tab model locks into certain models
* security model
* limited composability
* must break out of tabs
* use a tile to describe how to work w/ other tiles
* can't have tiles that load tiles
* tracking vector
* but tile that controls other tiles?
* what if tile supported configurable layouts
* intents system that marries tiles together via opaque blob-like urls
* that gives you composability
* for things like 3 pane ui where 1 tile configures 3 tiles (each pane) in a way that they work together
* common api (i have 3 things which support the X api)
* tile templates
* locally installed/pinned 'applications'
* ok fine yeah this is smalltalk
* goal is composability on the web
* power + composability is the leapfrog recipe
* challenge: don't have an installed tile that supports an intent, how do you find one?
* ipni: indexing network data by data type
* pubsub
* subscribe to a data model
* implementation in capyloon, peergos, electron
* no need to standard/spec yet
* developer workflow
* dev mode
* "unpacked"
* f5/refresh dev cycle
* ipfs add . | pubsub topic | cids -> hot reload
* things to get from browsers sooner rather than later:
* fix the RTC hole in CSP