Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
d332371
feat: Session replays
Blaumaus Jun 3, 2026
cfbdc19
UI changes
Blaumaus Jun 3, 2026
16ff7be
Interactive player
Blaumaus Jun 3, 2026
34de327
fix: session replay viewport scaling
Blaumaus Jun 3, 2026
c16047d
Remove current time icon
Blaumaus Jun 3, 2026
9a24b47
Video player UI improvements
Blaumaus Jun 3, 2026
3854854
Use ui lib components
Blaumaus Jun 3, 2026
4d9d0ef
Player improvements
Blaumaus Jun 3, 2026
a07ca81
Use standard text colours
Blaumaus Jun 4, 2026
4cfaa19
Scerenshot export improvements
Blaumaus Jun 4, 2026
578eed0
Export as MP4 option
Blaumaus Jun 4, 2026
b0840c3
Split features you need into web & product analytics
Blaumaus Jun 4, 2026
5026267
Session replays tab
Blaumaus Jun 4, 2026
c2ecdb6
Session replay docs
Blaumaus Jun 4, 2026
c7e529e
Smooth timeline transition
Blaumaus Jun 4, 2026
35ae303
Pre-launch improvements
Blaumaus Jun 4, 2026
9fb9af4
privacy
Blaumaus Jun 4, 2026
aa5f3d0
Fix lints
Blaumaus Jun 4, 2026
cf9e9be
Stylistic changes
Blaumaus Jun 4, 2026
352426b
Migrate to Hetzner S3
Blaumaus Jun 4, 2026
68aeb0e
Fix review comments
Blaumaus Jun 4, 2026
a589296
Replay addons
Blaumaus Jun 4, 2026
e8df315
Update for consistency
Blaumaus Jun 4, 2026
c034627
Simplify
Blaumaus Jun 4, 2026
eb4fc02
fix review comments
Blaumaus Jun 4, 2026
5d572cc
fix lints
Blaumaus Jun 4, 2026
c532815
Merge branch 'main' into feature/session-replays
Blaumaus Jun 4, 2026
4a5bf11
fix session replay retention and chunk dedupe
Blaumaus Jun 5, 2026
8d5fbb6
Rename to replaylibrary
Blaumaus Jun 5, 2026
ebf078e
Security hardening
Blaumaus Jun 5, 2026
7554404
fix session replay retry idempotency
Blaumaus Jun 5, 2026
6c1eb52
Use selector for retention policy
Blaumaus Jun 5, 2026
9e4fcd0
Allow deleting session replays
Blaumaus Jun 5, 2026
e0f5ca4
Refactor
Blaumaus Jun 5, 2026
e72e836
fix session replay storage race conditions
Blaumaus Jun 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 24 additions & 4 deletions admin/src/billing/pricing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,15 @@ export const planEntitlements = {
websites: 50,
teamMembers: 10,
organisations: 3,
apiRateLimitPerHour: 600,
apiRateLimitPerHour: 300,
sessionReplaysIncluded: 0,
},
[PlanType.plus]: {
websites: 100,
teamMembers: 25,
organisations: 10,
apiRateLimitPerHour: 5000,
sessionReplaysIncluded: 50000,
apiRateLimitPerHour: 6000,
sessionReplaysIncluded: 'byEventTier',
},
[PlanType.enterprise]: {
websites: 'custom',
Expand All @@ -63,6 +63,21 @@ export const planEntitlements = {
},
} as const

const sessionReplayQuotas: Partial<Record<PlanCode, number>> = {
[PlanCode['100k']]: 5000,
[PlanCode['200k']]: 10000,
[PlanCode['500k']]: 25000,
[PlanCode['1m']]: 50000,
[PlanCode['2m']]: 100000,
[PlanCode['5m']]: 250000,
[PlanCode['10m']]: 500000,
[PlanCode['15m']]: 750000,
[PlanCode['20m']]: 1000000,
[PlanCode['30m']]: 1500000,
[PlanCode['40m']]: 2000000,
[PlanCode['50m']]: 2500000,
}

const numberValue = (source: Record<string, unknown> | null, key: string) =>
source && typeof source[key] === 'number' ? (source[key] as number) : null

Expand All @@ -88,6 +103,11 @@ export const getEffectiveLimits = (user: User) => {
user.entitlementOverrides,
'sessionReplaysIncluded',
)
const replayQuota =
replayOverride ??
(entitlements.sessionReplaysIncluded === 'byEventTier'
? sessionReplayQuotas[user.planCode] || 0
: entitlements.sessionReplaysIncluded)
const websites =
websiteOverride ??
(typeof entitlements.websites === 'number'
Expand All @@ -105,7 +125,7 @@ export const getEffectiveLimits = (user: User) => {
websitesIncluded:
typeof websites === 'number' ? websites + addonWebsites : websites,
purchasedWebsiteAddons: addonWebsites,
replayQuota: replayOverride ?? entitlements.sessionReplaysIncluded,
replayQuota,
apiRateLimitPerHour,
}
}
17 changes: 17 additions & 0 deletions backend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,23 @@ EMAIL_ACTION_ENCRYPTION_KEY=
# Swetrix Enterprise (Cloud)
SWETRIX_LICENSE_KEY=

# Hetzner S3 storage defaults. Session Replay uses these when the
# SESSION_REPLAY_S3_* variables below are not set.
# HETZNER_S3_ENDPOINT is the location endpoint, for example https://fsn1.your-objectstorage.com.
# Do not include the bucket path in HETZNER_S3_ENDPOINT.
HETZNER_S3_ENDPOINT=
HETZNER_S3_BUCKET=
HETZNER_S3_ACCESS_KEY_ID=
HETZNER_S3_SECRET_ACCESS_KEY=

# Hetzner S3 storage for Session Replays.
# SESSION_REPLAY_S3_ENDPOINT is the location endpoint, for example https://fsn1.your-objectstorage.com.
# Do not include the bucket path in SESSION_REPLAY_S3_ENDPOINT.
SESSION_REPLAY_S3_ENDPOINT=
SESSION_REPLAY_S3_BUCKET=
SESSION_REPLAY_S3_ACCESS_KEY_ID=
SESSION_REPLAY_S3_SECRET_ACCESS_KEY=

# OpenRouter API key for AI features
OPENROUTER_API_KEY=

Expand Down
13 changes: 8 additions & 5 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
#Stage 1: Build
FROM node:lts-alpine AS build
FROM mcr.microsoft.com/playwright:v1.60.0-noble AS build
WORKDIR /build
ENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
COPY package*.json ./
COPY scripts/patch-rrvideo.js ./scripts/patch-rrvideo.js
RUN npm ci --force
COPY . .
RUN npm run deploy:community
RUN node ./meta/dbip-free-sync.js
RUN npm prune --omit=dev --force

#Stage 2: Runtime
FROM node:lts-alpine AS run
FROM mcr.microsoft.com/playwright:v1.60.0-noble AS run
LABEL maintainer="swetrix.com <[email protected]>"

ENV TZ=UTC \
Expand All @@ -32,10 +34,11 @@ ENV OIDC_CLIENT_ID='' \
OIDC_DISCOVERY_URL='' \
OIDC_CLIENT_SECRET=''

# Install and configure timezone
RUN apk add --no-cache tzdata && \
# Install video tooling and configure timezone
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends ffmpeg tzdata && \
cp /usr/share/zoneinfo/$TZ /etc/localtime && \
apk del tzdata
rm -rf /var/lib/apt/lists/*

# Use non-root numeric user
USER 999
Expand Down
Loading
Loading