Using Solid Pods to store and share consumer preferences across apps

Hello,

I’ve been building ConsAuth — an identity and preference-sharing layer built on top of Ory Hydra (OAuth2/OIDC) and Community Solid Server v7.

Wanted to share the current status and where it’s heading, get feedback. What we’re planning touches directly on Solid’s strengths in a way that feels worth discussing.

Expression of Demand ( consauth[dot]com/expression-of-demand ) is my attempt to extend the freedom of expression into the one domain where it has been quietly taken away — in a world that has reduced people to consumers, I want the act of consuming to be as expressive, intentional, and self-owned as any other form of speech.

@


What ConsAuth does

ConsAuth (consumer . consent . auth ) lets users log into apps with “Login with ConsAuth” — similar to “Login with Google” — but here apps receive structured preference and wish data that the user explicitly approved. Food preferences, music taste, travel style, values-based stances (like ethical sourcing), expressed as named scopes on the consent screen.

The preferences aren’t inferred from behavior. They’re declared by the user, directly or as part of the AI-assisted chat, scoped by category, and shared only when the user actively consents to each app that requests them.


Where Solid comes in

We chose Solid because we didn’t want ConsAuth to hold user data — we wanted users to own it. Every user who opts in gets a personal Pod at

pod[dot]consauth[dot]com backed by CSS v7. (on-demand pod provisioning)

When a user sets a preference, it syncs to their Pod as Turtle RDF using a vocabulary we publish at vocab.consauth.com — a lightweight Linked Data schema for consumer preferences. Public preferences are readable at
their Pod URL by any app the user authorises. Private ones aren’t.

A short example of what lands in a Pod:

@prefix ca:  <https://vocab.consauth.com/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

<https://pod.consauth.com/tolgay/consauth/preferences/values-boycott_brands>
  a ca:Preference ;
  ca:category "values" ;
  ca:key "boycott_brands" ;
  ca:value "Coca-Cola,amazon" ;
  ca:visibility ca:Public ;
  ca:setAt "2026-03-09T16:09:58Z"^^xsd:dateTime ;
  ca:updatedAt "2026-03-09T18:03:06Z"^^xsd:dateTime ;
  ca:isBinding false .

We also store product wishes (structured demand expressions — “Looking for a secondhand road bike under £300”) and boycott positions with reasons, all as RDF resources under the user’s Pod path.


One technical thing worth sharing: CSS v7 DPoP

For anyone integrating with CSS v7 from a backend service: it requires DPoP for all resource writes. We implemented this in Go — generating ECDSA keypairs per-request, hashing the request method + URL as the htu/htm claims. Happy to share the code if useful.

One gotcha: CSS validates WebIDs by dereferencing them internally, so the server must be accessible at the same URL it uses in --baseUrl. We run it on the same port it advertises (:4001) and have our API container spoof the Host header when talking to CSS internally.


Where we’re heading: demand signalling via LDN

The part I’m most interested in discussing with this community is what comes next.

Right now preferences live in a Pod and travel into apps via the OAuth2 token. That’s useful. But the Pod being a live, accessible data store opens up something more interesting: it can be an inbox for things that match what you’ve declared you want.

We’re exploring using Linked Data Notifications as the mechanism for this. The basic idea:

  • A user’s Pod exposes a public LDN inbox
  • They’ve declared (publicly or at community level) that they’re interested in, say, plant-based leather alternatives
    in a certain price range
  • A small producer browsing ConsAuth’s demand API discovers that 847 members of an Ethical Fashion community have
    expressed this demand — as an aggregate signal, no individual profiles exposed
  • The producer sends an LDN notification to the community inbox, or to individual inboxes of users who’ve opted in to
    producer notifications in that category
  • The user sees it in their Pod, not in an ad feed — on their terms, in their data store

The privacy property here is what makes it interesting: at the collective level, individuals are protected behind the aggregate (what we think of as a “zebra effect” — the herd is visible, the individual is not). At the individual
level, you can make preferences public on your Pod and be directly discoverable, or keep them private and only contribute to community-level signals.

This would mean Solid Pods can become active receivers of relevant market signals. Broadcasting and receiving. No intermediary platform. No algorithm deciding what reaches.


Questions / things we’d love feedback on

  1. LDN inbox design — has anyone implemented per-category LDN inboxes on CSS? We’re thinking about a namespace like
    pod.consauth .com/{user}/inbox/demand/ vs. a single inbox with typed notifications. Curious what patterns others have
    found workable.
  2. Vocabulary — our schema at vocab[dot]consauth[dot]com is hand-rolled and minimal. Is there existing work in the Solid ecosystem on preference or interest representation that we should be aligning with?
  3. Cross-pod discovery — if a user moves their Pod to a different provider (which is the whole point of Solid), how
    should ConsAuth’s demand aggregation layer stay in sync? We’re thinking about the Pod advertising a ConsAuth-specific
    type link in its profile document, but haven’t designed this yet.

Haven’t open-sourced the code yet. The vocabulary is live and resolvable. Happy to discuss any of this and collaborate.

— @