All projects

77-Day Dominion Challenge

Web applicationBeta

Daily tracking, journaling, and private groups.

Beta

Beta release for daily challenge tracking, private groups, journaling, and rewards. Enrollment and paid features follow the current beta availability.

Visit 77 Dominion

Overview.

77 Dominion is a challenge and accountability application built around a 77-day rhythm of spiritual and physical disciplines. Members track seven Daily Standards, submit a daily Check-In, and see their progress through points, streaks, badges, and rewards.

The app supports individual challenges and private groups. Group invitations require an explicit confirmation, while a separate private journal keeps personal reflections out of the shared group experience. The backend owns challenge state and earned progress so changing a browser value cannot create a reward or join a private group.

Screens & workflows.

Application screens and development prototypes. Select a capture for a closer look.

Complete a day of the challenge

  1. Open the dashboard to see the current challenge day and today's seven Daily Standards.
  2. Read the guidance for a standard and mark it complete as you go.
  3. Review the day's checklist and explicitly submit the Check-In.
  4. See the resulting progress, earned points, streaks, and badge state.

Join a private accountability group

  1. Open an invitation link, scan its QR code, or enter the invitation code.
  2. Review the group preview without joining automatically.
  3. Sign in and explicitly confirm that you want to join.
  4. Follow the group's activity and member progress, with access limited to the private group.

Track personal reflection and progress

  1. Open the Private Journal from the member navigation.
  2. Choose an allowed date and save a text reflection.
  3. Return to saved entries separately from the group's activity feed.
  4. Use the dashboard and reward views to review challenge progress without sharing the journal.

Start and continue a challenge

  1. Choose an available solo or group challenge and confirm the start configuration.
  2. Follow the current challenge instance through its daily check-ins.
  3. Review unlocked rewards as trusted points accumulate.
  4. After completion, start an available challenge again as a new instance while retaining lifetime points and permanent rewards.

Inside the build.

Explore the components, their boundaries, and the decisions behind them.

The frontend is a Vite multi-page application built with HTML, CSS, and browser-native JavaScript. Shared browser modules call a common API boundary, backed by Supabase Auth, Postgres row-level policies and transactional RPCs. Deno Edge Functions handle privileged integrations, uploads, and public share rendering independently from the static bundle.

Static multi-page experience

Keep each member journey addressable as its own page while sharing behavior and visual tokens.

  • A single entrypoint map declares every active HTML page for the build and entrypoint tests.
  • Page modules cover dashboard, Daily Standards, groups, journal, rewards, profile, authentication, and billing views.
  • Shared modules own navigation, appearance, challenge progression, validation, and accessibility behavior; there is no client framework mount or catch-all application route.

Design decisions & tradeoffs.

Use page modules instead of a client framework

Each customer-facing view is a real HTML entry, and a shared module layer supplies common behavior. The build and its tests use the same explicit entrypoint map.

The tradeoffCross-page state must be handled deliberately, but navigation and delivery stay straightforward without a large client application shell.

Separate editable progress from an awarded Check-In

Members can mark Daily Standards before submitting the day. The trusted backend applies the point contract and creates immutable award events, with duplicate protection.

The tradeoffThe domain needs transactional rules and retry handling, but browser edits or repeated requests cannot manufacture earned progress.

Preview invitations before creating membership

Links, codes, and QR representations resolve to a privacy-safe preview. Only explicit authenticated confirmation can commit membership, attribution, and any associated reward.

The tradeoffThe flow has an extra confirmation step, but opening a link or passing through sign-in cannot silently add someone to a private group.

Preserve rewards across repeated challenges

Challenge instances own their daily state, while the immutable lifetime ledger drives permanent reward ownership. Levels are a display rhythm rather than the authority for rewards.

The tradeoffInstance and lifetime state require separate models, but restarting a challenge does not erase previously earned points or entitlements.

Technical stack.

Frontend

  • HTML
  • CSS
  • JavaScript ES modules
  • Vite

A static multi-page application with dedicated page modules and shared visual and interaction primitives.

Identity and data

  • Supabase Auth
  • PostgreSQL
  • PostgREST
  • SQL RPCs
  • Row-level security

Member identity, scoped reads, transactional challenge state, immutable points, reward entitlements, and private groups.

Trusted backend

  • Deno
  • TypeScript
  • Supabase Edge Functions
  • Supabase Storage

Profile-photo processing, lifecycle cleanup, reward downloads, public share snapshots, and provider-facing operations.

Delivery

  • Cloudflare Pages
  • Wrangler
  • GitHub workflows
  • pnpm

Static asset deployment, explicit mock/live build gates, and independent backend migration/function release paths.

Quality

  • Node test runner
  • Playwright
  • axe-core
  • pgTAP
  • Deno tests

Browser fixtures and screenshot baselines, accessible interactions, real database policies, migration behavior, and concurrency checks.

Controlled integrations

  • Stripe
  • Slack OAuth
  • Discord OAuth
  • qrcode

Billing and external channel adapters are implemented behind release controls. Invitation QR codes are generated locally without sending invitation secrets to a hosted QR service.