# Basic IPFS User Stories In order for IPFS to be successful not just with people who are already committed to a decentralization agenda but in a wider community that might simply want to try something and see if it can do useful work, there is a number of very basic user stories that need to work flawlessly and to be easy to find in the documentation. These basically involve people in common development exploration contexts attempting very simple operations: serve, get, verify, and *maybe* sync. ## On my command line I am reasonably proficient with a command line and wish to interact with IPFS using simple command line tools that are sufficiently similar to other commands in that environment. ### Serve I have a directory of content (that may have subdirectories) and I want it to be available on IPFS. The HTTP equivalent is: `http-server .`. There are other options that are just as simple, `http-server` is widely available (from npm, from brew, runnable with npx if it isn't installed, etc.). When you kill it, it stops serving the content. In IPFS, that's: `XXX` (break it up by serve directory and serve single file) ### Get Someone gave me an `ipfs:` or `ipns:` URL and I want to download it. I don't know what it is, I just want to get it, save it, poke at it, and do something with it if it's useful. The HTTP equivalent is `curl --ouput file.foo URL`. There are options other than `curl` and many ways in which this command can fail, but this will usually work. In IPFS, that's: `XXX`. ### Verify We can break this user story into two cases: 1. I am downloading from a URL and once downloaded I want to verify that I got the right thing. 2. I already have a file and I want to verify that it's the same as a remote resource. The HTTP implementation of these two requires that some other party has published a hash of the resource and made it available in redundant places (i.e. location that presumably won't be compromised if the resource has been compromised). Assuming you obtained a SHA-256 `de4db33f`, you can verify a download by running `shasum -a 256 downloaded.file` and checking that it matches the hash you have. If you already have a file and wish to check that it is the same as a remote one, your best bet is also to compare a locally-generated hash to one provided by another part. Otherwise, HTTP lacks a reliable way to verify that a local file is the same as a remote one without downloading it. The `Digest`/`Want-Digest` pair is deprecated and would require trusting the remote server anyway. In IPFS, that's: `XXX`. ### Modify/Patch We can think of two applicable substories: 1. I want to update a remote directory by adding or replacing a file in it. 2. I want to modify a remote JSON resource. The JSON resource is: ```json { "questions": { "life": 41 } } ``` And the update is intended to set the correct answer. For HTTP (assuming no access control), `PUT`ting a file remotely can be invoked with `curl --upload-file kitten.jpg https://berjon.com/cats/`. HTTP also has a [`PATCH`](https://www.rfc-editor.org/rfc/rfc5789) method, though it is rarely used. It can be paired with [JSON Patch](https://www.rfc-editor.org/rfc/rfc6902) like so: `curl -X PATCH --data '[{"op": "replace", "path": "/questions/life", "value": 42}]' https://berjon.com/deep-philosophy.json` In IPFS, that's: `XXX`. ## In my Node app I am writing a simple Node.js application and wish to interact with IPFS without needing to understand much if anything about it. I want a solution that I can grab off of npm and can paste code for from StackOverflow, I don't want to need to stop working on my app because I need to learn about a whole new thing. ### Serve We can break this story up between serving a single resource and serving a directory. In Node, serving up a single resource is: ```js import express from 'express'; const app = express(); app.get('/cat.txt', (req, res) => res.send('meow')); app.listen(1337, () => console.warn(`Listening at http://localhost:1337/…`)); ``` And serving a directory is: ```js import express from 'express'; const app = express(); app.use(express.static('./cats')); app.listen(1337, () => console.warn(`Listening at http://localhost:1337/…`)); ``` In IPFS, that's: `XXX`. ### Get In Node, fetching a URL (assuming you just want the binary data) is: ```js const res = await fetch(url); const data = await res.arrayBuffer(); ``` In IPFS, that's: `XXX`. ### Verify In Node, fetching and verifying a URL assumes that you also have the hash already: ```js import { createHash } from 'node:crypto'; export function trustButVerify (url, hash) { const res = await fetch(url); const data = await res.arrayBuffer(); const dataHash = createHash('sha256').update(data).digest('hex'); return dataHash === hash; } ``` In IPFS, that's: `XXX`. ### Modify/Patch In Node, `PUT`ting a file is: ```js import { readFile } from 'node:fs'; await fetch( 'https://berjon.com/cats/kittens.jpg', { method: 'put', headers: { 'content-type': 'image/jpeg' }, body: await readFile('./kittens.jpg'), } ); ``` And sending a `PATCH` is: ```js await fetch( 'https://berjon.com/deep-philosophy.json', { method: 'patch', headers: { 'content-type': 'application/json' }, body: JSON.stringify([{ op: "replace", path: "/questions/life", value: 42 }]), } ); ``` Of course, this assumes that the server will expose support for `PATCH`, which as usual is unlikely unless it was specifically coded to support it. In IPFS, that's: `XXX`. ## In my browser JS I am tinkering with a web page, which I'm testing on `localhost` and deploying on `https`, and wish to interact with IPFS without needing to understand much if anything about it. I want a solution that I can grab off of npm and can paste code for from StackOverflow, I don't want to need to stop working on my app because I need to learn about a whole new thing. ### Serve There isn't really an HTTP way to serve from the browser. One could considering `PUT`ting to a remote server, but that's cheating. In IPFS, that's: `XXX`. ### Get For HTTP, this is the same as in Node. In IPFS, that's: `XXX`. ### Verify Verifying that a URL matches a provided hash in the browser: ```js function trustButVerify (url, hash) { const res = await fetch(url); const data = await res.arrayBuffer(); const buf = await crypto.subtle.digest("SHA-256", data); const dataHash = Array.from(new Uint8Array(buf)) .map((b) => b.toString(16).padStart(2, "0")) .join("") ; return dataHash === hash; } ``` In IPFS, that's: `XXX`. ### Modify/Patch These work the same way they do in Node, except that `readFile()` has to be replaced with another way to get at the data (e.g. an uploaded `Blob`). In IPFS, that's: `XXX`. ## On my server I have a server running some kind of Linux and I want to put an IPFS thing on it. I'm admin, I can install things and change configurations, including opening ports, but I don't want to have to spend the day doing it — whatever I need to do, I need to have a clear and straightforward way to set it up. This just considers serving because that's the one that's different from accomplishing the same on the a personal device's command line. ### Serve For HTTP, that's typically done by running `nginx` or `Apache`. These are available pre-packaged. :::warning This is where we explain serve, provide, pin From DN: From my understanding, there’s a subtle difference between the two. - With a local node, pinning results in the CID kept locally, but not necessarily provided to the network - If your node is not running, are the CIDs still pinned? My guess would be yes. - Providing on the other hand is what makes the CID available to the network and it requires “work” to publish/advertrise the CIDs. - In https://docs.ipfs.tech/concepts/lifecycle/ we treat advertising/providing as a subset of Pinning. ::: In IPFS, that's: `XXX`.