Product architecture

How Living Echoes fits together

A single memorial record is authored by families, curated by center staff, distributed to lobby kiosks, and safeguarded by administrators. Each surface talks to the same domain services through a role-aware policy layer.

Roles & surfaces

Family portal
Author biographies, upload media, invite family, manage subscription
Center dashboard
Manage memorials, moderate submissions, schedule ceremonies
Lobby kiosk
Touch-first browse of approved profiles with auto-return
Admin console
Centers, users, packages, billing, moderation, analytics

Layered composition

Presentation
Web app (Family, Center, Admin), Kiosk touch app, public docs pages
Application services
MemorialService · MediaService · BillingService · CeremonyService · KioskService
Domain rules engine
Role policies · Media approval · Subscription lifecycle · Kiosk eligibility · Audit hooks
Data & storage
Relational profile store · Object storage for media · Search index · Backup snapshots
Platform
Auth · Role-based access · Observability · Automated cloud backups

Data flow — Family uploads a photo

Family uploads
Selected in Family portal media page
Object storage
Signed upload, virus scan, thumbnails
Rules engine
Package quota, file type, kiosk eligibility
Center moderates
Approve, reject with note, or hold
Kiosk & public
Approved media appears within seconds

Rules engine — a peek inside

rule "media.approval":
  when
    upload.kind in (photo, video, audio)
    subscription.status == active
    upload.size_mb <= package.mediaLimitGb * 1024 - used_mb
  then
    if package.tier >= "Legacy" and upload.auto_ok:
      status := approved
    else:
      status := pending
      notify(center_staff, "New media awaiting review")

rule "kiosk.eligibility":
  when
    memorial.status == approved
    subscription.status in (active, trialing)
    memorial.center in kiosk.assigned_centers
  then
    include_in_lineup := true

rule "subscription.lifecycle":
  on invoice.failed:
    subscription.status := past_due
    grace := 14 days
  on grace.expired:
    subscription.status := canceled
    memorial.public := false
    kiosk.remove(memorial)

Subsystems at a glance

Media
Upload, transcode, thumbnails, captions, moderation queue
Billing
Packages, subscriptions, invoices, dunning, upgrades
Kiosk
Lineup, idle-timeout, touch search, offline resilience
Access control
Role policies, per-center scoping, family invites, audit
Search & index
Names, tags, dates, centers; faceted for kiosk browsing
Backups
Nightly snapshots, media replication, annual archival export

Built to grow

400 → 100k profiles
Partitioned by center; sharded media buckets
1 → many centers
Center-scoped RBAC and kiosk assignment
Regional replicas
Read-through caching for kiosk & public pages
Ready to explore the platform surfaces?