Files
trakqr/docs/spec.md
2026-01-27 13:47:56 -05:00

284 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# QR-First URL Shortener SaaS (Designer + Short Links + Tracking)
Note: These specs are a draft and need review.
## 0) Product Definition
One-liner: Create branded short links and highly customizable QR codes, then track scans/clicks with actionable analytics.
Primary users:
- Solo creators / small businesses
- Marketing teams in SMB/PME
- Agencies managing multiple clients
Core value: Beautiful QR designs + brandable short domains + trustworthy tracking in one place.
## 1) MVP Scope (what ships first)
### 1.1 User Capabilities (MVP)
Auth & Account
- Sign up / sign in (email + password; optional SSO later)
- Email verification
- Password reset
- Basic account settings
Projects / Workspaces
- Default workspace per user
- Create “Projects” to organize links/QRs (e.g., “Restaurant menus”, “Flyers Q1”)
Short Link Creation
- Create short link: https://d.om/abc123 or custom slug …/menu
- Destination URL validation
- Optional UTM builder (preset templates)
- Enable/disable link
- Expiration date (optional)
- Password protection (optional) — may be “Pro” if you want
QR Code Designer
- Generate QR from a short link (default) or direct URL
- Styling:
- Colors (foreground/background)
- Error correction level (L/M/Q/H)
- Quiet zone padding
- Shape presets (modules/eyes) (start with a few presets)
- Center logo upload (PNG/SVG) with size + margin controls
- Export:
- PNG and SVG
- Size presets (e.g., 256/512/1024/2048)
- Print-ready options (e.g., “high contrast” toggle)
Tracking & Analytics (MVP)
- Track events: click (short link) and scan (QR)
- Dashboard:
- Total events, uniques, last 24h / 7d / 30d
- Time series
- Top referrers (for clicks)
- Geo (country) and device (desktop/mobile) high-level
- Per-link analytics and per-QR analytics
Basic Admin
- Subscription status
- Usage quotas (links/QRs/events)
## 2) Non-Goals for MVP (explicitly out)
- Team roles/permissions (RBAC) beyond “owner”
- A/B routing, smart rules, rotation, geo routing
- Deep campaign automation
- Enterprise SSO, SCIM
- Offline QR scan tracking (impossible without network in most cases)
## 3) Plans & Monetization (recommended)
Free
- 1 workspace
- 25 short links
- 25 QR designs
- 10k events/month
- 1 custom QR logo upload (or allow unlimited but watermark exports)
Pro (individual/SMB)
- Custom domains (13)
- Higher limits
- No watermark
- UTM templates
- Expiring links / password links (if Pro)
Business
- Multiple workspaces
- Team seats (later)
- Higher retention and export presets
## 4) Core Entities (Data Model)
### 4.1 Entities
User
- id, email, password_hash, verified_at, created_at
Workspace
- id, owner_user_id, name, plan, created_at
Project
- id, workspace_id, name, created_at
Domain
- id, workspace_id, hostname, status (pending/verified/active), verification_token, created_at
ShortLink
- id
- workspace_id, project_id (nullable)
- domain_id (nullable; else default platform domain)
- slug
- destination_url
- title (nullable)
- status (active/disabled)
- expires_at (nullable)
- password_hash (nullable)
- created_at, updated_at
QRCodeDesign
- id
- workspace_id, project_id (nullable)
- shortlink_id (nullable; recommended default)
- style_json (colors, shapes, ecc level, etc.)
- logo_asset_id (nullable)
- created_at, updated_at
Event
- id (or bigint)
- workspace_id
- shortlink_id
- qrcode_id (nullable but strongly recommended to tag scans)
- type: click | scan
- ts
- ip_hash (privacy-safe)
- user_agent
- referrer
- country_code (nullable)
- device_type (nullable)
- dedupe_key (nullable)
- raw_json (optional for debug, or drop)
Asset
- id, workspace_id, type (logo), storage_key, mime, size, created_at
### 4.2 Key Design Choice
How do we distinguish “scan” vs “click”?
When exporting a QR, embed a URL like:
https://d.om/s/abc123?qr=<qrcode_id>
The redirect endpoint records scan when it detects qr=<id>, then redirects to destination, which will also produce a click unless you decide “scan implies click” and record only one.
Recommendation: record one event per redirect request:
- If qr present → type=scan
- Else → type=click
## 5) System Behavior (Routes & Flows)
### 5.1 Public Redirect
GET /{slug}
Resolve domain + slug → short link
Validate:
- exists
- active
- not expired
- if password-protected → show password page
Log event (scan/click)
Redirect 301/302 (configurable later; MVP use 302)
### 5.2 QR Export
QR code is generated from:
Redirect URL including qrcode id: https://{domain}/{slug}?qr={qrcode_id}
## 6) Functional Requirements (MVP checklist)
Link Management
- Create, edit, disable, delete (soft delete preferred)
- Slug uniqueness per domain
- Auto-slug generator (base62)
- Destination URL allowlist/denylist (prevent abuse)
QR Designer
- Live preview
- Save design
- Export SVG/PNG
- Logo upload with validation (size/mime)
Analytics
- Views for:
- Workspace overview
- Project overview
- Per short link
- Per QR design
- Time filters: 24h / 7d / 30d / custom range
- Unique definition:
- Unique per day per link based on ip_hash + UA hash (privacy-safe and approximate)
## 7) Non-Functional Requirements
Performance
- Redirect endpoint P95 < 100ms (excluding DNS/TLS)
- Event write must not block redirect (use async queue if possible)
Availability
- Redirect is the critical path; should stay up even if dashboard is down
- Graceful degradation: if analytics store is down, still redirect
Security
- Rate limit public endpoints
- Abuse prevention: phishing/malware reporting flow (later), basic filters now
- Domain verification to prevent takeover
- Strict CSP on app pages
Privacy & Compliance (Canada / Quebec friendly baseline)
- Avoid storing raw IP; store hashed IP with rotating salt (e.g., monthly)
- Provide retention configuration per plan (e.g., 30/180/365 days)
## 8) Architecture (pragmatic MVP)
Components
- Web App: dashboard + designer (Vue/React)
- API: CRUD for links/qr/projects/domains, analytics queries
- Redirect Edge: fastest path for /{slug} (can be same API initially)
Storage
- PostgreSQL for core entities
- Analytics:
- MVP: PostgreSQL events table partitioned by month
- Later: ClickHouse/BigQuery for scale
Background Jobs
- Domain verification checks
- Event enrichment (geo/device parsing)
- Cleanup & retention tasks
## 9) API Surface (minimal)
- POST /auth/register|login|forgot|reset
- GET/POST /workspaces
- GET/POST /projects
- GET/POST /links
- GET/POST /qrcodes
- POST /domains + verification status
- GET /analytics/overview
- GET /analytics/link/{id}
- GET /analytics/qrcode/{id}
## 10) UI Pages (MVP)
- Login / Register / Reset
- Workspace switcher
- Projects list
- Links list + create/edit
- QR designer (create/edit) with preview
- Analytics dashboard (overview + per link + per QR)
- Domains page (add/verify)
## 11) Pricing/Quotas Enforcement
Enforce at API level:
- max links, max QR codes, max events/month, max custom domains
Stripe integration later; MVP can be “manual Pro” toggle or Stripe from day 1 if you want.
## 12) Implementation Notes (key decisions)
- Use one redirect URL as canonical; QR adds ?qr= for attribution.
- Event logging should be non-blocking:
- MVP: write to DB async (background queue) or “fire-and-forget” with retry
- Plan for domain verification:
- Require DNS TXT record or CNAME to verify ownership
- Short link collision:
- Slug uniqueness per domain enforced in DB