SnappSnapp
  • Getting Started
  • Installation
  • Configuration
  • Styling
  • Introduction
  • Custom URLs
  • Authentication
  • Multi-Domain Architecture
  • Team Management
  • Third-Party Integrations
  • Metrics & Analytics
  • API Reference
  • English
  • Italiano
  • Getting Started
  • Installation
  • Configuration
  • Styling
  • Introduction
  • Custom URLs
  • Authentication
  • Multi-Domain Architecture
  • Team Management
  • Third-Party Integrations
  • Metrics & Analytics
  • API Reference
  • English
  • Italiano
  • Features

    • Introduction
    • Custom URLs
    • Authentication
    • Multi-Domain Architecture
    • Team Management
    • Third-Party Integrations
    • Metrics & Analytics
    • API Reference

Overview

Snapp supports multiple public domains within a single deployment.

This is not implemented through virtual instances, duplicated databases, or separate applications. Instead, Snapp relies on Better-Auth organizations as the structural boundary between domains.

Each exposed domain maps to:

  • one organization
  • one authentication context
  • one default access scope
  • one set of limits and behavioral options

All domains share the same runtime and database, while authority and control remain scoped.


Core principle

A domain maps to an organization.

This rule drives the entire model.

Every host defined in settings.yaml:

hosts:
  - origin: https://example.org
  - origin: https://another-domain.dev

corresponds to:

  • an organization with id = slugify(origin)
  • an isolated access scope
  • a dedicated Better-Auth client instance
  • a distinct permission graph

There is no implicit discovery or inferred mapping.


Initialization flow

On startup, Snapp performs a structured bootstrap sequence.

1. Admin bootstrap

For each admin defined in configuration:

admin:
  - email: admin@example.org
    username: admin

Snapp:

  • creates the user if missing
  • assigns the admin role
  • prints the generated password once
  • does not remove existing admins

This keeps administrative access recoverable.


2. Organization bootstrap

For each configured host:

hosts:
  - origin: https://example.org

Snapp ensures:

  • an organization exists with id = slugify(origin)
  • the original origin is stored in metadata
  • the organization remains stable across restarts

Missing organizations are created during initialization.


3. Membership enforcement

All admin users are added to every organization as owner.

This prevents:

  • orphan organizations
  • inaccessible domains
  • domains without a privileged user

4. Role materialization

Roles are stored per organization:

  • owner
  • admin
  • member

Each role contains a serialized permission graph.

When role definitions change, Snapp:

  • invalidates the in-memory auth cache
  • reloads permissions on demand
  • avoids relying on stale ACLs

Request-time domain resolution

For each incoming request, Snapp determines the active host:

  1. Reads event.url.origin
  2. Normalizes protocol (development vs production)
  3. Matches against settings.hosts
  4. Falls back to the first configured host if required

The resolved host defines:

  • the active organization
  • the Better-Auth client in use
  • the applicable limits and feature flags

Requests are not processed without a resolved host.


Authentication isolation

Each host has its own Better-Auth instance.

Instances are cached by:

slugify(host.origin)

This provides isolation for:

  • sessions
  • cookies
  • OAuth callbacks
  • rate limits
  • signup rules

When host options change, the related cache entry is invalidated.


Active organization enforcement

On authenticated requests:

  • if no active organization is set
  • Snapp assigns the organization associated with the current host

If the user is not a member of that organization:

  • access is denied
  • pending invitations are checked
  • invitation flows are enforced
  • no silent fallback is applied

Users cannot operate within a domain they do not belong to.


Shortcode resolution

Shortcodes are not strictly limited to a single organization.

Resolution follows a defined sequence.

1. Organization-scoped exact match

active = true
organizationId = current organization
shortcode = requested

This is the primary lookup path.


2. Organization-scoped case-insensitive fallback

If enabled:

disable:
  lowerCaseFallback: false

The lookup remains scoped to the current organization.


3. Global fallback (cross-organization)

If no organization-level match is found:

active = true
shortcode = requested
ORDER BY createdAt ASC
LIMIT 1

This lookup is global and used as a last step.


Rationale for global fallback

Global fallback supports:

  • shortcodes created before multi-domain support
  • canonical links that must resolve across domains
  • predictable resolution instead of silent 404s
  • reuse of existing links without duplication

Only the redirect behavior is shared.

Ownership and control remain unchanged.


What remains isolated

Even when global fallback is used:

  • ownership does not change
  • permissions are not bypassed
  • secrets are enforced
  • updates are not allowed
  • analytics remain tied to the original URL
  • organizations stay isolated

The host resolves the link without assuming control over it.


Security enforcement

Before redirecting, Snapp enforces:

  • expiration checks
  • active state validation
  • VirusTotal validation
  • watchlist rules
  • secret verification (if configured)

Redirection occurs only if all checks succeed.


Data model summary

ConceptScope
UsersGlobal
OrganizationsPer host
SessionsPer host
PermissionsPer organization
URLsOwned by one organization
Shortcode resolutionOrg → global fallback
RedirectStateless

Mental model

Snapp can be viewed as:

  • one runtime
  • multiple domains
  • a shared database
  • explicit authority boundaries
  • controlled cross-domain resolution

Domains remain isolated for control, while links can remain interoperable for resolution.


Configuration implications

Adding a domain:

  • creates an organization
  • assigns admin membership
  • initializes roles
  • enables access immediately

Removing a domain:

  • deletes the organization
  • invalidates auth caches
  • leaves URLs intact but unreachable from that host

Summary

  • Multi-domain support is built-in
  • Organizations define boundaries
  • Authentication is host-scoped
  • Permissions are explicit
  • Shortcode fallback follows a defined order
  • No implicit data leakage occurs

The model is deterministic, observable, and reversible.

Prev
Authentication
Next
Team Management