Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
8c72bf3
Migrate to React Router v8, pnpm workspace, Tailwind + shadcn
askides Aug 3, 2026
fb660db
Drop docs app and READMEs, replace prettier with oxfmt + oxlint
askides Aug 3, 2026
e58aebf
Drop TODO.md
askides Aug 3, 2026
b93ab10
Inline validation schemas into their consumers
askides Aug 3, 2026
89463d0
Replace Prisma with Drizzle, and fix the schema defects it was hiding
askides Aug 3, 2026
3a4ada0
Fix two regressions and a timezone bug found reviewing the Drizzle port
askides Aug 3, 2026
0dd149f
Add docker-compose for the dev Postgres
askides Aug 4, 2026
9ec5cf8
Denormalise events into one wide table
askides Aug 4, 2026
4c627d3
Rewrite the seed for the wide event shape
askides Aug 4, 2026
4633055
Derive visitor and session ids from a rotating HMAC
askides Aug 4, 2026
3c4e830
Resolve country from edge headers only
askides Aug 4, 2026
55b7410
Classify referrers into acquisition channels at ingest
askides Aug 4, 2026
d83812a
Rate limit the unauthenticated collect endpoints
askides Aug 4, 2026
53b780c
Parse the client from hints first, UA string second
askides Aug 4, 2026
b4ca45d
Echo the caller's origin instead of allowing *
askides Aug 4, 2026
2f04353
Rewrite the tracker in TypeScript, storage-free
askides Aug 4, 2026
4844d55
Rebuild ingest around sessionization and a duration token
askides Aug 4, 2026
ccfd511
Substitute the legacy zone names Postgres rejects
askides Aug 4, 2026
1c1951d
Rebuild the query layer on the wide events table
askides Aug 4, 2026
26b89c8
Measure preset windows in milliseconds, not calendar days
askides Aug 4, 2026
b3954a7
Add the shared display formatting
askides Aug 4, 2026
0aff106
Swap ApexCharts for Recharts, add sonner and day-picker
askides Aug 4, 2026
0aac165
Restyle on an aurora palette and add the missing primitives
askides Aug 4, 2026
cbc8a84
Replace the navbar with a sidebar shell
askides Aug 4, 2026
30f21d2
Redraw the timeseries on Recharts
askides Aug 4, 2026
12bac1d
Replace the breakdown table with tabbed panels
askides Aug 4, 2026
df54c48
Rebuild the dashboard around the range and zone pickers
askides Aug 4, 2026
3ad0056
Give the website list its numbers and a sheet to add sites
askides Aug 4, 2026
fcaba0f
Put signin and setup behind a shared auth frame
askides Aug 4, 2026
293bd0c
Name every dependency in optimizeDeps
askides Aug 4, 2026
feebb16
Pin both tzdata copies and assert them
askides Aug 4, 2026
0522942
Reorganise the app into feature modules over a shared layer
askides Aug 4, 2026
57db04b
Enforce the shared to modules direction
askides Aug 4, 2026
400b755
Move the tracker's endpoints to routes/api
askides Aug 4, 2026
98d9712
Lift the unique-violation check out of db.server
askides Aug 4, 2026
3990f01
Rename logout to signout
askides Aug 4, 2026
7e6a18c
Split PublicShell out of app-shell
askides Aug 4, 2026
d538952
Extract the shared panel parts from breakdown-panel
askides Aug 4, 2026
508d100
Move the beacon wire format into the ingest module
askides Aug 4, 2026
966dfca
ci: derive releases from conventional commits and publish to ghcr
askides Aug 5, 2026
be577bb
docs: add the readme and restore the license
askides Aug 5, 2026
529dc72
fix(signin): remove the autofocus from the email field
askides Aug 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 6 additions & 0 deletions .commitlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"extends": ["@commitlint/config-conventional"],
"rules": {
"subject-case": [2, "always", "lower-case"]
}
}
10 changes: 10 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
node_modules
**/node_modules
**/build
**/.next
**/.react-router
**/app/generated
.git
.github
*.md
**/.env
54 changes: 0 additions & 54 deletions .github/workflows/backend.yml

This file was deleted.

235 changes: 235 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

# Narrow by default; the two jobs that need more declare it themselves.
permissions:
contents: read

# There is no commit to hook here, and the commitlint job below is the real
# enforcement point anyway.
env:
HUSKY: 0

jobs:
lint:
name: Lint
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm

- run: pnpm install --frozen-lockfile
- run: pnpm lint
- run: pnpm format:check

# The commit-msg hook is one `--no-verify` away from being bypassed, and it
# never sees the message that actually lands: squash merges are enabled with
# `squash_merge_commit_title: COMMIT_OR_PR_TITLE`, so a multi-commit squash
# takes the *pull request title* as the subject on main. Both are checked.
commitlint:
name: Commitlint
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
# commitlint walks the base..head range, which shallow clones lack.
fetch-depth: 0
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm

- run: pnpm install --frozen-lockfile

- name: Commits
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: pnpm exec commitlint --verbose --from "$BASE_SHA" --to "$HEAD_SHA"

# Through the environment, never interpolated into the script: a pull
# request title is attacker-controlled text on a public repository.
- name: Pull request title
env:
PR_TITLE: ${{ github.event.pull_request.title }}
run: echo "$PR_TITLE" | pnpm exec commitlint --verbose

web:
name: Web
runs-on: ubuntu-latest
defaults:
run:
working-directory: apps/web

env:
DATABASE_URL: postgres://root:password@localhost:5432/aurora
SESSION_SECRET: impossibletoguess

services:
postgres:
# Pinned to the patch for the reason docker-compose.yml gives at length:
# Postgres reads zones from its image's own OS tzdata package, so a
# floating `postgres:16` picks up whichever release the latest rebuild
# carried. It resolves to 16.14 / tzdata 2026b today, one release ahead
# of the 2026a the Dockerfile asserts against `process.versions.tz` and
# docker-compose's healthcheck refuses to start without. The
# timezone-sensitive suites are the ones that run here, so this was the
# one place the two zone databases were never checked against each
# other. Move this with the pin in docker-compose.yml.
image: postgres:16.13
env:
POSTGRES_DB: aurora
POSTGRES_USER: root
POSTGRES_PASSWORD: password
options: >-
--health-cmd pg_isready --health-interval 10s --health-timeout 5s
--health-retries 5
ports:
- 5432:5432

steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm

- run: pnpm install --frozen-lockfile
working-directory: .

- run: pnpm db:migrate
- run: pnpm typecheck
- run: pnpm test
- run: pnpm build

# The deployment path, which nothing else exercises. `pnpm build` covers the
# app's own compilation, but the Dockerfile carries logic that only ever runs
# here: the base stage's tzdata assertion, the `--filter web... --filter
# tracker...` scoped installs, the `--prod` install, and the runner stage's
# hand-assembled node_modules copy. A dependency that only resolved because a
# dev dependency hoisted it, or a file the runner stage forgets to copy, is
# invisible to every step above and surfaces at deploy time.
#
# Pull requests only: on main the publish job below builds the same image for
# real, so running this too would build it twice.
docker:
name: Docker
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3

# Build only — the image is never pushed from a pull request. This is a
# gate, not a release step. Its own cache scope, because it builds one
# architecture where publish builds two.
- uses: docker/build-push-action@v6
with:
context: .
push: false
cache-from: type=gha,scope=gate
cache-to: type=gha,mode=max,scope=gate

# Opens (and maintains) a release pull request from the conventional commits
# on main; merging that pull request is what bumps the version, writes
# CHANGELOG.md, tags, and publishes the GitHub release. Gated on lint and web
# so a red main cannot produce a release.
release:
name: Release
if: github.event_name == 'push'
needs: [lint, web]
runs-on: ubuntu-latest

permissions:
contents: write
pull-requests: write
issues: write

outputs:
release_created: ${{ steps.release-please.outputs.release_created }}
tag_name: ${{ steps.release-please.outputs.tag_name }}

steps:
# No `release-type` input: omitting it is what makes the action read
# release-please-config.json and .release-please-manifest.json.
- uses: googleapis/release-please-action@v4
id: release-please
with:
token: ${{ secrets.GITHUB_TOKEN }}

# Publishing lives here, keyed off the job above's output, rather than in a
# workflow triggered `on: release`. A release created with GITHUB_TOKEN does
# not fire `release`, `create`, or tag `push` events — GitHub suppresses them
# so workflows cannot trigger themselves — so the obvious wiring would simply
# never run. Reading `release_created` in the same workflow avoids needing a
# personal access token or a GitHub App just to break that loop.
publish:
name: Publish
if: github.event_name == 'push'
needs: [release]
runs-on: ubuntu-latest

permissions:
contents: read
packages: write

steps:
- uses: actions/checkout@v4

# linux/arm64 is emulated, so its install and build stages are slow on a
# cold cache. If that becomes the bottleneck, the repository is public and
# therefore has free ubuntu-24.04-arm runners: split into a per-platform
# matrix that builds by digest and merge with `buildx imagetools create`.
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3

- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

# `edge` and `sha-` land on every push to main; the version tags only on
# the push that merged a release pull request. Every versioned entry is
# gated on `release_created` rather than on tag_name being empty, so no
# entry is ever handed a value to parse that isn't a tag: on an ordinary
# push a `type=semver` with no value falls back to github.ref, which is
# `refs/heads/main`.
- id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=raw,value=edge
type=sha,prefix=sha-,format=short
type=semver,pattern={{version}},value=${{ needs.release.outputs.tag_name }},enable=${{ needs.release.outputs.release_created == 'true' }}
type=semver,pattern={{major}}.{{minor}},value=${{ needs.release.outputs.tag_name }},enable=${{ needs.release.outputs.release_created == 'true' }}
type=semver,pattern={{major}},value=${{ needs.release.outputs.tag_name }},enable=${{ needs.release.outputs.release_created == 'true' }}
type=raw,value=latest,enable=${{ needs.release.outputs.release_created == 'true' }}

- uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
# Carries org.opencontainers.image.source, which is what links the
# package to this repository and inherits its visibility.
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha,scope=publish
cache-to: type=gha,mode=max,scope=publish
30 changes: 0 additions & 30 deletions .github/workflows/frontend.yml

This file was deleted.

20 changes: 10 additions & 10 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
node_modules/
.pnp
.pnp.js

# testing
/coverage
coverage/

# next.js
/.next/
/out/

# production
/build
# builds
build/
dist/
out/
.react-router/

# misc
.DS_Store
Expand All @@ -23,13 +22,14 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*

# local env files
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

# vercel
.vercel
.env
1 change: 1 addition & 0 deletions .husky/commit-msg
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pnpm exec commitlint --edit "$1"
Loading
Loading