Components
The elements of a distributed app
The Webnative SDK is built on a few foundational blocks, the Webnative File System (WNFS), IPLD, CIDs, and UCANs. How these pieces are bound to an identity, communicated to other devices and users, encrypted, and transferred, is customizable through components. By default, Webnative uses the Fission infrastructure, but you don't have to.
There are seven components:
- Crypto. How should private-public key pairs and symmetric keys be stored? How do I sign a message? Which key types should I support for the
did:key
method? What are my agent and sharing key pairs? - Depot. Gets IPLD data in and out of your program by creating and referencing CIDs. File system data is brought in and shipped out through this component.
- Manners. Various behavioral elements. If the
debug
configuration flag is enabled, how does the logging happen, file system hooks, etc. - Reference. Responsible for the sources of truth: the data root (root CID of WNFS), the DID root (your account DID, aka. root agent DID), DNS, and repositories of various items.
- Storage. Stores and retrieves ephemeral and session data.

This illustrates the relationships between the different components and the Fission infrastructure.
The webnative-walletauth plugin allows you to use your blockchain wallet to authenticate with webnative. It does not have an
auth
component because the identity already exists. But it does have crypto
and manners
components that make the following customizations:- The
crypto
component configures Webnative to work with the key pair used by an Ethereum wallet. - The
manners
component alters how Webnative transfers the root file system encryption key. Using file system hooks, the key is encrypted and put on the public side of the file system. The wallet can always decrypt this key, enabling file system access no matter what device connects.
In this example, we'll add a file system hook and emojis to the debug messages.
// example/manners/implementation.ts
import { Manners } from "webnative/components"
import { addSampleData } from "webnative/fs/data"
export async function implementation(
options: Manners.ImplementationOptions
): Manners.Implementation {
const base = WebnativeManners.implementation(options)
const dontDoAnything = () => {}
const hooks = {
// Add some sample data to new file systems
afterLoadNew: async (fs: FileSystem.API) => {
addSampleData(fs)
fs.publish()
},
}
return {
...base,
// Debug messages
log: opts.configuration.debug ? msg => console.log("ℹ️", msg) : dontDoAnything,
warn: opts.configuration.debug ? msg => console.warn("⚠️", msg) : dontDoAnything,
// File system hooks
fileSystem: { hooks }
}
}
To use a different component than Webnative's defaults, all you have to do is pass them into the
program
. Alternatively, if you have a whole composition (see the section below), you can skip a step and directly use the assemble
function. That's what the program
function uses underneath.// Using our custom manners component implementation from earlier
import * as CustomManners from "./example/manners/implementation.ts"
import * as wn from "webnative"
const configuration = { namespace: "example" }
const program = await wn.program({
...configuration,
manners: CustomManners.implementation({ configuration })
})
A composition is a full set of components.
// The default set of components is available as:
wn.compositions.fission()
// To illustrate how the fission composition works:
const crypto = await wn.defaultCryptoComponent(configuration)
const manners = wn.defaultMannersComponent(configuration)
const storage = wn.defaultStorageComponent(configuration)
const configWithComponents = { ...configuration, crypto, manners, storage }
const r = await wn.reference.fission(configWithComponents)
const d = await wn.depot.fissionIPFS(configWithComponents)
const c = await wn.capabilities.fissionLobby({ ...configWithComponents, depot: d })
const a = await wn.auth.fissionWebCrypto({ ...configWithComponents, reference: r })
const composition = {
auth: a,
capabilities: c,
depot: d,
reference: r,
crypto,
manners,
storage,
}
const program = await wn.assemble(
configuration,
composition
)
Last modified 5mo ago