Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 0 additions & 12 deletions .eslintrc.js

This file was deleted.

18 changes: 10 additions & 8 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:

1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
Expand All @@ -24,15 +24,17 @@ A clear and concise description of what you expected to happen.
If applicable, add screenshots to help explain your problem.

**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]

- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]

**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]

- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]

**Additional context**
Add any other context about the problem here.
1 change: 0 additions & 1 deletion .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
Expand Down
38 changes: 38 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: CI

on:
pull_request:
push:
branches:
- main

jobs:
build-and-test:
name: Build and test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Check
run: pnpm exec vp check

- name: Test
run: pnpm test

- name: Build
run: pnpm build
13 changes: 0 additions & 13 deletions .github/workflows/dependabot-automerge.yml

This file was deleted.

58 changes: 29 additions & 29 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,48 +1,48 @@
name: Release

on:
pull_request:
branches:
- master
push:
branches:
- master
- main

jobs:
release:
name: release
runs-on: ubuntu-latest
permissions:
contents: write
issues: write
pull-requests: write
packages: write
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Semantic Release
uses: cycjimmy/semantic-release-action@v2
id: semantic
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
branch: master
extra_plugins: |
@semantic-release/git
@semantic-release/changelog
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
version: 9

- name: Setup Node.js with GitHub Package Registry
uses: actions/setup-node@v1
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 12
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
node-version: 22
cache: pnpm
registry-url: 'https://npm.pkg.github.com'
scope: 'academydistrict20'
scope: '@altitudems'

- name: Publish To GitHub Package Registry
if: steps.semantic.outputs.new_release_published == 'true'
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.GH_TOKEN }}
- name: Push updates to branch for major version
if: steps.semantic.outputs.new_release_published == 'true'
run: "git push https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git HEAD:refs/heads/v${{steps.semantic.outputs.new_release_major_version}}"
- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Build
run: pnpm build

- name: Semantic Release
working-directory: packages/analytics
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: pnpm release
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
coverage
node_modules
.eslintcache
.eslintcache
dist
*.tsbuildinfo
.DS_Store
*.log
.pnpm-store
7 changes: 0 additions & 7 deletions .prettierrc.js

This file was deleted.

19 changes: 11 additions & 8 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
{
"editor.defaultFormatter": "oxc.oxc-vscode",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
"source.fixAll.oxc": "explicit"
},
"editor.formatOnSave": false,
"[typescript]": {
"editor.formatOnSave": false
"editor.defaultFormatter": "oxc.oxc-vscode"
},
"conventionalCommits.scopes": [
"commit-hooks",
"release",
"client"
]
"[javascript]": {
"editor.defaultFormatter": "oxc.oxc-vscode"
},
"[json]": {
"editor.defaultFormatter": "oxc.oxc-vscode"
},
"conventionalCommits.scopes": ["commit-hooks", "release", "client", "monorepo"]
}
19 changes: 19 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!--VITE PLUS START-->

# Vite+

- `vp check` — format, lint, types
- `vp fmt` — format
- `pnpm test` / `pnpm build` — packages
- `pnpm dev` — API + demo

<!--VITE PLUS END-->

# Layout

```
packages/analytics # browser SDK
packages/analytics-server # store interface + ingest
apps/api # Hono example
apps/demo # marketing + app + Lit dashboard (same origin)
```
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# analyitics

First-party analytics you own — browser SDK, pluggable ingest, zero vendors.

```bash
pnpm install
pnpm dev
```

| | |
| --------- | ------------------------------------ |
| Marketing | http://localhost:5173 |
| App | http://localhost:5173/app.html |
| Dashboard | http://localhost:5173/dashboard.html |
| API | http://localhost:8787 |

Open the dashboard first — it boots with seeded history and an SSE live feed.

```ts
// browser
import { createAnalytics } from '@altitudems/analytics'
const analytics = createAnalytics({ endpoint: '/ingest', app: 'app' })
analytics.capture('feature_used')

// server
import { registerIngest, type AnalyticsStore } from '@altitudems/analytics-server'
registerIngest(app, { store: myStore, writeKey: '…' })
```

Built with **Vite+** (`vp check`, `vp test`, `vp pack`).
48 changes: 48 additions & 0 deletions apps/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Examples

## Full demo (same-origin funnel)

```bash
pnpm install
pnpm dev
```

| Surface | URL |
| --------- | ------------------------------------ |
| Marketing | http://localhost:5173 |
| App | http://localhost:5173/app.html |
| Dashboard | http://localhost:5173/dashboard.html |
| API | http://localhost:8787 |

Vite proxies `/ingest`, `/stats`, `/events`, and `/stream` (SSE) to the API — so marketing, app, and dashboard share **one origin**.

### Happy path

1. Open http://localhost:5173/dashboard.html — tiles and feed are already full (seeded history)
2. Watch the feed tick via **SSE** as synthetic live traffic lands
3. Open http://localhost:5173/?utm_source=twitter&utm_medium=social&utm_campaign=launch
4. Click **Start free** → lands in the app with the same visitor id
5. **Sign in as Alex** → identify stitches the funnel
6. Your real events stream into the same dashboard instantly

The Lit dashboard (`harbor-dashboard`, `stat-tile`, `rank-list`, `event-stream`) connects to `/stream` (SSE). It falls back to polling `/stats` + `/events` if SSE drops.

Set `HARBOR_LIVE_TRAFFIC=0` to disable the synthetic traffic generator.

## Wire your own backend

```ts
import { Hono } from 'hono'
import { registerIngest, type AnalyticsStore } from '@altitudems/analytics-server'

const store: AnalyticsStore = {
async insert(events, meta) {
// persist to Postgres / ClickHouse / …
},
}

const app = new Hono()
registerIngest(app, { store, writeKey: process.env.ANALYTICS_WRITE_KEY })
```

`MemoryStore` is for demos only.
21 changes: 21 additions & 0 deletions apps/api/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "@altitudems/example-api",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "tsx watch src/index.ts",
"start": "tsx src/index.ts",
"build": "echo \"api is run with tsx\""
},
"dependencies": {
"@altitudems/analytics-server": "workspace:*",
"@hono/node-server": "^2.0.10",
"hono": "^4.12.30"
},
"devDependencies": {
"@types/node": "^22.15.32",
"tsx": "^4.20.3",
"typescript": "~5.9.3"
}
}
Loading
Loading