Pod Mapping with Solid: Setup and Authentication
podmap.me is a Web-based implementation of Mia Mingus and the Bay Area Transformative Justice Collective's Pod Mapping Worksheet. Pod data is incredibly sensitive and personal - in the wrong hands, detailed information about the relationships we have with the most important people in our lives can be used to exact enormous harm. It is unacceptable, therefore, to let this data escape a podmap.me user's locus of control, and unethical to build a Web service that asks a user to do this.
Until now we've solved this problem by storing all data in the browser's local storage. This is certainly an improvement in some ways over the paper worksheet, but local browser storage is still too ephemeral and opaque to be useful for long-term storage of this data, tying the user to whatever device they happen to have used to complete the worksheet. It would be much better to store this data in a place fully controlled by the user that is also accessible by the various devices and apps they use: a place like their personal online datastore.
This series of articles will be a journal of the process of updating
podmap.me to store data in the personal online
datastores of its users. We'll be starting from the "Local Storage"
release of
podmap.me. You can follow along on the
solid
branch of the
Git repository.
Setup
podmap.me is built with
Next.js and React so
swrlit
is a perfect choice for
data and state management:
npm install swrlit
swrlit
exports an AuthenticationProvider
that will store and
manage authentication state for our app. We'll add it to _app.jsx
to
ensure it's available on every page:
import { AuthenticationProvider } from 'swrlit'
function MyApp({ Component, pageProps }) {
return (
<AuthenticationProvider>
<Component {...pageProps} />
</AuthenticationProvider>
)
}
You can see the full commit here.
Authentication
We can't start storing data until we can log in, so the first thing we'll do is to implement authentication. To keep things simple we'll add a simple log in form to the navigation bar:
import { useState } from 'react'
import Link from 'next/link'
import { useAuthentication } from 'swrlit'
export default function Nav() {
const [handle, setHandle] = useState("")
const [badHandle, setBadHandle] = useState(false)
const { loginHandle } = useAuthentication()
async function logIn(){
setBadHandle(false)
try {
await loginHandle(handle);
} catch (e) {
console.log("error:", e)
setBadHandle(true)
}
}
function onChange(e){
setHandle(e.target.value)
setBadHandle(false)
}
return (
<nav>
<ul>
<li>
<input type="text"
placeholder="what's your handle?"
value={handle} onChange={onChange} />
{badHandle && (
<p className="text-xs text-red-500 absolute">
hm, I don't recognize that handle
</p>
)}
</li>
<li>
<button onClick={logIn}>log in</button>
</li>
</ul>
</nav>
)
}
You can see the finished version, with styling and convenience functions, here.
swrlit
's loginHandle
function uses a couple heuristics to
construct the "identity provider" URL, so when I enter
tvachon.inrupt.net
in the "what's your handle?" input I'll be
redirected to the Solid Pod hosting service at inrupt.net
to enter
my credentials before being redirected back to podmap.me:
Now that we're back, we have two problems - the login form is still showing, and we have no way to log out. Fortunately this couldn't be easier to fix:
import { useAuthentication, useLoggedIn } from 'swrlit'
export default function Nav() {
const { loginHandle, logout } = useAuthentication()
const loggedIn = useLoggedIn()
...
return (
...
{loggedIn ? (
<li>
<button onClick={logout}>log out</button>
</li>
) : (
<>
<li>
<input type="text"
placeholder="what's your handle?"
value={handle} onChange={onChange} />
{badHandle && (
<p className="text-xs text-red-500 absolute">
hm, I don't recognize that handle
</p>
)}
</li>
<li>
<button onClick={logIn}>log in</button>
</li>
</>
)}
...
)
}
You can see the full commit here.
Next time
In the next article in this series we'll show you how to start creating, saving and updating data in our personal online datastore using swrlit
.
If you find this tutorial useful, please consider donating to the Bay Area Transformative Justice Collective, whose work inspired podmap.me.