Decentralized Web App: it's a Web5 Progressive Web App.
It's a perfect match with Web5 DWNs since a PWA can work offline and DWN has a synced local storage.
Aside from that, the advanced PWA capabilities such as modifying fetch requests allow us to extract the most such as displaying images with DRLs in the traditional src
attribute.
Requirements:
- node v20.x (
nvm use 20
) - pnpm v9 (
npm i -g pnpm
) - docker (to run a local DWN server)
pnpm i
docker compose up -d
pnpm dev
- Unit tests are located alongside the code in the
src
folder, suffixed with.test.tsx
, ran byvitest
andreact-testing-library
for components - E2E tests are located in the
e2e
folder, ran byplaywright
pnpm test # runs both unit and e2e tests
pnpm test:unit # runs only the unit tests
pnpm test:e2e # runs only the e2e tests
pnpm build
Deploy the dist
folder to the server. It's just a static PWA! Please make sure all the settings are optimized for production, including your application descriptions, icons, service workers, polyfills and configurations (ie. check vite-pwa eslint recommendations below).
- It's just a Traditional React Application with a PWA on top using
vite-pwa
src/pages
- contains the page componentssrc/App.tsx
- contains the main App componentsrc/main.tsx
- contains the main entry pointsrc/sw.ts
- contains the service worker setup, including the new web5activatePolyfills
which will setup DRLs (and DWN store offline management in the future)
- Built with tailwind css and @shadcn/ui which will allow us to expand to other frameworks as well (vue, svelte, solid, etc.)
src/components/ui
has the shadcn default components
src/web5
folder has web5 specific functionalities that you will most likely not needed to updated on your DWA- except for
protocols.ts
which you should add your custom protocols and/or port other known protocols to leverage typings
- except for
The app has a standard responsive layout with a sidebar, with basic routing setup with three pages:
- Home Page: it invites the user to connect to Web5 and once it's connect it presents a basic Todo List CRUD powered by DWNs
- Settings Page: shows off protocols and the usage of DRL in an
img
tag. - About Page: it shows a basic info page that does not require any Web5 connection.
Just a basic tasks CRUD that allows the user to add, edit, delete and mark task as done. Pretty standard example across many frameworks.
Try it yourself! Connect and then add your first tasks, edit, remove them etc.
The difference is that here we are using Web5 DWNs as the data store.
It uses Web5 through the useWeb5
hook and, to simplify the component code, we wrapped the CRUD operations using the repository
pattern, pretty much a data access layer, in the `todo-dwn-repository.ts file.
In this page we are using direct access to the DWN protocols in the component itself, just to have more inline code to read.
The goal here is to understand how to persist data using protocols (read more in our docs here) and read them using DRLs in the browser natively.
First, we need to install the protocols schemas, the code for that can be found in the protocols.ts
file and is executed only once, when connected, if the protocol is not installed yet.
Then in this page, we read the display name and the image using DRLs, which is a browser customization in the fetch API to read protocols when the url is prefixed with https://dweb
.
First the page will be blank and you will see 404 network errors. Thats because we tried to fetch from the DWN protocol without any data. Try to change the display name and upload an image in the form. Then refresh the page.
Now you will see that we load the display name and the avatar image from the following urls:
https://dweb/${did}/read/protocols/${encodeURIComponent(protocolUri)}/name
https://dweb/${did}/read/protocols/${encodeURIComponent(protocolUri)}/avatar
The beauty of DWAs is that, once the Web5 SDK polyfills are active, we can read the data from the DWNs without any extra code, just by using the native browser fetch API!
Even further, the urls works out of the box in any browser context, including img tags within the src
attribute. The following code just works:
<img src="https://dweb/${did}/read/protocols/${encodeURIComponent(protocolUri)}/avatar" />
Check the <ProfileSettings />
component, to see how the avatar image is being handled (ignoring the conditional noise to handle the image file upload input).
This repo was created with vite-pwa, check the default instructions below.
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
- Configure the top-level
parserOptions
property like this:
export default {
// other rules...
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
project: ["./tsconfig.json", "./tsconfig.node.json"],
tsconfigRootDir: __dirname,
},
};
- Replace
plugin:@typescript-eslint/recommended
toplugin:@typescript-eslint/recommended-type-checked
orplugin:@typescript-eslint/strict-type-checked
- Optionally add
plugin:@typescript-eslint/stylistic-type-checked
- Install eslint-plugin-react and add
plugin:react/recommended
&plugin:react/jsx-runtime
to theextends
list
Resource | Description |
---|---|
CODEOWNERS | Outlines the project lead(s) |
CODE_OF_CONDUCT.md | Expected behavior for project contributors, promoting a welcoming environment |
CONTRIBUTING.md | Developer guide to build, test, run, access CI, chat, discuss, file issues |
GOVERNANCE.md | Project governance |
LICENSE | Apache License, Version 2.0 |