Privacy & Security

static.bio is built with privacy and security as first principles. This page documents our model, what data we store, and our security posture.

Privacy Model

No Cookies on Public Pages

Public profile pages set zero cookies. No Set-Cookie headers are sent in responses. This means:

  • No tracking cookies
  • No session cookies
  • No analytics cookies
  • No third-party cookies (we don't load third-party scripts anyway)

No Third-Party Scripts

Public pages load zero external resources:

  • No <script> tags pointing to external domains
  • No <link> tags pointing to external CSS or fonts
  • No iframes, tracking pixels, or beacons
  • Third-party images are allowed (users control their avatar URLs)

Analytics Are Opt-In

Analytics are disabled by default. When enabled (Lifetime plan only):

  • Links are rendered as /r/{linkId} instead of direct URLs
  • The redirect endpoint increments a counter (per-link click counts)
  • No cookies are set
  • No external analytics services are called
  • Data is stored in our database only

When analytics are disabled, links are rendered as direct <a href="https://destination">tags with no tracking.

Data Stored

Creator Data

For authenticated creators, we store:

  • Email address (for passwordless authentication)
  • Profile data: username, displayName, bio, avatarUrl, themeId
  • Links: label, url, enabled status, order
  • Plan: FREE or LIFETIME
  • Custom domains (Lifetime plan only)

Visitor Data

For visitors to public profiles:

  • If analytics disabled: We store nothing. No requests are logged, no data is collected.
  • If analytics enabled: We store aggregated click counts per link. No PII, no IP addresses, no user agents, no timestamps beyond aggregate counts.

Analytics Event Schema

When analytics are enabled, we use a minimal aggregated analytics model:

  • What is stored: A single integer counter (clicks) per link in the Link table. This counter increments atomically when a visitor clicks a link through the /r/{linkId} redirect endpoint.
  • What is NOT stored:
    • IP addresses
    • User-agent strings
    • Per-event timestamps (only the link's updatedAt timestamp is updated)
    • Geographic location
    • Referrer information
    • Session identifiers
    • Any other personally identifiable information (PII)
  • Storage model: Analytics are stored as a simple integer column (clicks INTEGER NOT NULL DEFAULT 0) on the Link table. There is no separate analytics or events table. No per-event records are created.
  • Best-effort counting: Under extreme traffic or abuse scenarios, analytics events may be dropped to preserve performance. Click counts are approximate and best-effort, not guaranteed to be 100% accurate.

Security Posture

Authentication Model

We use passwordless email authentication:

  • Auth.js (NextAuth) for session management
  • Magic links sent via email (no passwords to leak)
  • Server-side sessions (no JWT tokens in cookies)
  • CSRF protection via "use server" directive
  • Production security: Magic links are email-only and never rendered in HTML. In production, the DEV_MAGIC_LINK environment variable is unset or set tofalse, ensuring magic link tokens are never exposed in page HTML.

Security Headers

Public pages include security headers:

  • X-Frame-Options: DENY (prevents clickjacking)
  • X-Content-Type-Options: nosniff (prevents MIME sniffing)

XSS Mitigation

XSS is prevented through multiple layers:

  • No JavaScript: Even if HTML injection occurs, no scripts can execute (zero <script> tags)
  • Careful escaping: All user input (displayName, bio, link labels) is HTML-escaped before rendering
  • URL scheme allowlisting: Link URLs are restricted to http:,https:, and mailto: to prevent XSS via malicious URL schemes (e.g., javascript:, data:). URLs are normalized and validated before storage.

Authorization

Dashboard routes are protected:

  • Proxy-level authentication check (proxy.ts)
  • Unauthenticated users redirected to /auth/signin
  • All database queries filter by userId from authenticated session
  • Users can only access their own profile data

Future Commitments

  • Export/self-host options: We're building static export functionality so you can host your profile anywhere
  • No surprise trackers: We will never add third-party analytics, tracking pixels, or external scripts to public pages
  • Data portability: Export scripts will allow you to take your data and leave at any time