Concepts, value, and typical clone scenarios — less code.
Concepts, value, and typical clone scenarios — less code.
Preparing Ring Platform content
Preparing Ring Platform content
Preparing Ring Platform content
Filter this page with Founder / Developer in the docs sidebar. Founders learn why listings stay fresh; developers get modules, events, and extension points.
When someone creates, edits, or removes an opportunity or entity on a PostgreSQL-primary Ring clone, users expect the marketplace and directory to update immediately — without a nightly reindex job. Ring coordinates three lightweight steps on every mutation.
| Step | What users perceive | What happens under the hood |
|---|---|---|
| 1. Cache bust | List pages stop showing stale cards | revalidateTag clears role-scoped list caches |
| 2. Page refresh | Detail and hub URLs show new data on next navigation | revalidatePath invalidates App Router SSR |
| 3. Realtime ping | Open tabs update without manual reload | Tunnel publishes opportunity:* / entity:* events |
On Postgres-primary clones, the database row is the search index. There is no separate Elasticsearch table to rebuild — discovery queries read JSONB directly (Data model).
Your clone's directory (entities) and marketplace of needs (opportunities) are the core loop most rings monetize around. Stale listings erode trust faster than a missing feature.
A member posts a contract — approved listings appear on /opportunities and subscribers get Tunnel notifications.
A verified entity updates its showcase — profile pages and public directory refresh without ops intervention.
New opportunities trigger matcher pipelines; fresh cache tags ensure match cards reference current budget and deadline fields.
Prerequisite: channel subscribe SSOT and publishToChannel vs publishToUserTunnel.
Deep-dive: TunnelHub broker and feature publish/subscribe matrix.
Depends-on: JSONB collections synced by this pipeline.
Same-workflow: REST surface + post-mutation hooks for opportunities.
Filter this page with Founder / Developer in the docs sidebar. Founders learn why listings stay fresh; developers get modules, events, and extension points.
When someone creates, edits, or removes an opportunity or entity on a PostgreSQL-primary Ring clone, users expect the marketplace and directory to update immediately — without a nightly reindex job. Ring coordinates three lightweight steps on every mutation.
| Step | What users perceive | What happens under the hood |
|---|---|---|
| 1. Cache bust | List pages stop showing stale cards | revalidateTag clears role-scoped list caches |
| 2. Page refresh | Detail and hub URLs show new data on next navigation | revalidatePath invalidates App Router SSR |
| 3. Realtime ping | Open tabs update without manual reload | Tunnel publishes opportunity:* / entity:* events |
On Postgres-primary clones, the database row is the search index. There is no separate Elasticsearch table to rebuild — discovery queries read JSONB directly (Data model).
Your clone's directory (entities) and marketplace of needs (opportunities) are the core loop most rings monetize around. Stale listings erode trust faster than a missing feature.
A member posts a contract — approved listings appear on /opportunities and subscribers get Tunnel notifications.
A verified entity updates its showcase — profile pages and public directory refresh without ops intervention.
New opportunities trigger matcher pipelines; fresh cache tags ensure match cards reference current budget and deadline fields.
Prerequisite: channel subscribe SSOT and publishToChannel vs publishToUserTunnel.
Deep-dive: TunnelHub broker and feature publish/subscribe matrix.
Depends-on: JSONB collections synced by this pipeline.
Same-workflow: REST surface + post-mutation hooks for opportunities.
Filter this page with Founder / Developer in the docs sidebar. Founders learn why listings stay fresh; developers get modules, events, and extension points.
When someone creates, edits, or removes an opportunity or entity on a PostgreSQL-primary Ring clone, users expect the marketplace and directory to update immediately — without a nightly reindex job. Ring coordinates three lightweight steps on every mutation.
| Step | What users perceive | What happens under the hood |
|---|---|---|
| 1. Cache bust | List pages stop showing stale cards | revalidateTag clears role-scoped list caches |
| 2. Page refresh | Detail and hub URLs show new data on next navigation | revalidatePath invalidates App Router SSR |
| 3. Realtime ping | Open tabs update without manual reload | Tunnel publishes opportunity:* / entity:* events |
On Postgres-primary clones, the database row is the search index. There is no separate Elasticsearch table to rebuild — discovery queries read JSONB directly (Data model).
Your clone's directory (entities) and marketplace of needs (opportunities) are the core loop most rings monetize around. Stale listings erode trust faster than a missing feature.
A member posts a contract — approved listings appear on /opportunities and subscribers get Tunnel notifications.
A verified entity updates its showcase — profile pages and public directory refresh without ops intervention.
New opportunities trigger matcher pipelines; fresh cache tags ensure match cards reference current budget and deadline fields.
Prerequisite: channel subscribe SSOT and publishToChannel vs publishToUserTunnel.
Deep-dive: TunnelHub broker and feature publish/subscribe matrix.
Depends-on: JSONB collections synced by this pipeline.
Same-workflow: REST surface + post-mutation hooks for opportunities.
Admin approve/reject flows call the same sync — status changes behave like updates for subscribers watching the channel.
DB_BACKEND_MODE first.features/opportunities/lib/opportunity-mutation-sync.ts |
create-opportunity, update-opportunity, delete-opportunity, auto-approval-service |
| Entities | features/entities/lib/entity-mutation-sync.ts | create-entity, update-entity, delete-entity, moderation + KYC hooks |
Wire topic listeners with useTunnelChannel — production hooks parse syncDiscovery payloads via lib/discovery/parse-discovery-tunnel-message.ts ({ id, event } + message.event like entity:created).
| Channel | Hook | UI wiring |
|---|---|---|
opportunities | hooks/use-realtime-opportunities.ts | features/opportunities/components/opportunities.tsx |
entities | hooks/use-realtime-entities.ts | features/entities/components/entities.tsx — deletes splice locally; create/update soft-reloads the cursor feed |
See Realtime transport and Tunnel protocol.
Opportunities
/[locale]/opportunities/[locale]/opportunities/[id]/[locale]/opportunities/my/opportunities (on create / status change)Entities
/[locale]/entities/[locale]/entities/[id]/[locale]/entities/my/entities (on create / status change)| Path | Reason |
|---|---|
/[locale]/entities/add | One-shot form; redirect after create |
/[locale]/entities/status/... | Payment callbacks — unrelated to CRUD discovery |
/[locale]/confidential/entities | Tag invalidation sufficient; avoids extra path churn |
| Ringdom Maps nodes | Separate graph store — not wired to entity list caches |
Reads map DatabaseService rows through:
features/opportunities/lib/opportunity-db-mapper.tsfeatures/entities/lib/entity-db-mapper.tsLegacy Firestore converters under lib/converters/*-converter.ts apply only when DB_BACKEND_MODE=firebase-full.
Same-workflow: REST surface + post-mutation hooks for entities.
Admin approve/reject flows call the same sync — status changes behave like updates for subscribers watching the channel.
DB_BACKEND_MODE first.features/opportunities/lib/opportunity-mutation-sync.ts |
create-opportunity, update-opportunity, delete-opportunity, auto-approval-service |
| Entities | features/entities/lib/entity-mutation-sync.ts | create-entity, update-entity, delete-entity, moderation + KYC hooks |
Wire topic listeners with useTunnelChannel — production hooks parse syncDiscovery payloads via lib/discovery/parse-discovery-tunnel-message.ts ({ id, event } + message.event like entity:created).
| Channel | Hook | UI wiring |
|---|---|---|
opportunities | hooks/use-realtime-opportunities.ts | features/opportunities/components/opportunities.tsx |
entities | hooks/use-realtime-entities.ts | features/entities/components/entities.tsx — deletes splice locally; create/update soft-reloads the cursor feed |
See Realtime transport and Tunnel protocol.
Opportunities
/[locale]/opportunities/[locale]/opportunities/[id]/[locale]/opportunities/my/opportunities (on create / status change)Entities
/[locale]/entities/[locale]/entities/[id]/[locale]/entities/my/entities (on create / status change)| Path | Reason |
|---|---|
/[locale]/entities/add | One-shot form; redirect after create |
/[locale]/entities/status/... | Payment callbacks — unrelated to CRUD discovery |
/[locale]/confidential/entities | Tag invalidation sufficient; avoids extra path churn |
| Ringdom Maps nodes | Separate graph store — not wired to entity list caches |
Reads map DatabaseService rows through:
features/opportunities/lib/opportunity-db-mapper.tsfeatures/entities/lib/entity-db-mapper.tsLegacy Firestore converters under lib/converters/*-converter.ts apply only when DB_BACKEND_MODE=firebase-full.
Same-workflow: REST surface + post-mutation hooks for entities.
Admin approve/reject flows call the same sync — status changes behave like updates for subscribers watching the channel.
DB_BACKEND_MODE first.features/opportunities/lib/opportunity-mutation-sync.ts |
create-opportunity, update-opportunity, delete-opportunity, auto-approval-service |
| Entities | features/entities/lib/entity-mutation-sync.ts | create-entity, update-entity, delete-entity, moderation + KYC hooks |
Wire topic listeners with useTunnelChannel — production hooks parse syncDiscovery payloads via lib/discovery/parse-discovery-tunnel-message.ts ({ id, event } + message.event like entity:created).
| Channel | Hook | UI wiring |
|---|---|---|
opportunities | hooks/use-realtime-opportunities.ts | features/opportunities/components/opportunities.tsx |
entities | hooks/use-realtime-entities.ts | features/entities/components/entities.tsx — deletes splice locally; create/update soft-reloads the cursor feed |
See Realtime transport and Tunnel protocol.
Opportunities
/[locale]/opportunities/[locale]/opportunities/[id]/[locale]/opportunities/my/opportunities (on create / status change)Entities
/[locale]/entities/[locale]/entities/[id]/[locale]/entities/my/entities (on create / status change)| Path | Reason |
|---|---|
/[locale]/entities/add | One-shot form; redirect after create |
/[locale]/entities/status/... | Payment callbacks — unrelated to CRUD discovery |
/[locale]/confidential/entities | Tag invalidation sufficient; avoids extra path churn |
| Ringdom Maps nodes | Separate graph store — not wired to entity list caches |
Reads map DatabaseService rows through:
features/opportunities/lib/opportunity-db-mapper.tsfeatures/entities/lib/entity-db-mapper.tsLegacy Firestore converters under lib/converters/*-converter.ts apply only when DB_BACKEND_MODE=firebase-full.
Same-workflow: REST surface + post-mutation hooks for entities.