{"id":47668055,"url":"https://github.com/tyssejc/junction","last_synced_at":"2026-04-02T12:05:19.355Z","repository":{"id":339044288,"uuid":"1157472663","full_name":"tyssejc/junction","owner":"tyssejc","description":"Next-generation, Git-native event collection and routing system. A replacement for Adobe Launch and Google Tag Manager built for the modern web.","archived":false,"fork":false,"pushed_at":"2026-04-01T13:01:47.000Z","size":451,"stargazers_count":9,"open_issues_count":7,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-01T14:06:01.305Z","etag":null,"topics":["amplitude","analytics","cloudflare-workers","consent","edge-computing","event-collector","google-analytics","isomorphic","meta-pixel","plausible","privacy","tag-manager","typescript"],"latest_commit_sha":null,"homepage":"https://demo.jctn.io","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tyssejc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-13T21:27:02.000Z","updated_at":"2026-04-01T13:01:52.000Z","dependencies_parsed_at":null,"dependency_job_id":"369d28b2-0acd-4c6b-adda-db91eb317f00","html_url":"https://github.com/tyssejc/junction","commit_stats":null,"previous_names":["tyssejc/junction"],"tags_count":25,"template":false,"template_full_name":null,"purl":"pkg:github/tyssejc/junction","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tyssejc%2Fjunction","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tyssejc%2Fjunction/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tyssejc%2Fjunction/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tyssejc%2Fjunction/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tyssejc","download_url":"https://codeload.github.com/tyssejc/junction/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tyssejc%2Fjunction/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31305973,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T09:48:21.550Z","status":"ssl_error","status_checked_at":"2026-04-02T09:48:19.196Z","response_time":89,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["amplitude","analytics","cloudflare-workers","consent","edge-computing","event-collector","google-analytics","isomorphic","meta-pixel","plausible","privacy","tag-manager","typescript"],"created_at":"2026-04-02T12:05:18.719Z","updated_at":"2026-04-02T12:05:19.349Z","avatar_url":"https://github.com/tyssejc.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Junction\n\nNext-generation, Git-native event collection and routing system. A replacement for Adobe Launch and Google Tag Manager built for the modern web.\n\n## Why Junction\n\nTag managers were designed for marketers adding snippets to websites. Junction is designed for engineers building data infrastructure. Events are the primitive — not tags, not rules. Configuration lives in TypeScript files, reviewed in pull requests, deployed through CI/CD.\n\n**Config as code.** Your tracking config is a TypeScript file in your repo. No web UI, no race conditions, no \"who changed that rule in production?\"\n\n**Consent-first.** Events queue until consent is resolved. Destinations only receive events they're allowed to see. DNT and GPC respected out of the box.\n\n**Schema validation.** Zod contracts enforce event shapes at runtime. Catch typos, missing fields, and type mismatches before they reach your analytics.\n\n**Isomorphic.** The same collector runs in browsers, Node.js, Deno, Cloudflare Workers, and Bun. Write once, deploy anywhere.\n\n## Packages\n\n| Package | Description |\n|---------|-------------|\n| [`@junctionjs/core`](packages/core) | Isomorphic collector, consent state machine, Zod validation |\n| [`@junctionjs/client`](packages/client) | Browser runtime — anonymous IDs, sessions, auto page views |\n| [`@junctionjs/astro`](packages/astro) | Astro v5+ integration — script injection, SSR middleware, View Transitions |\n| [`@junctionjs/gateway`](packages/gateway) | WinterCG edge gateway — Cloudflare Workers, Deno, Bun, Vercel Edge |\n| [`@junctionjs/destination-amplitude`](packages/destination-amplitude) | Amplitude (HTTP API, client + server) |\n| [`@junctionjs/destination-ga4`](packages/destination-ga4) | GA4 (gtag.js, Measurement Protocol, Consent Mode v2) |\n| [`@junctionjs/destination-meta`](packages/destination-meta) | Meta Pixel + Conversions API |\n| [`@junctionjs/destination-http`](packages/destination-http) | Generic HTTP destination — POST events to any endpoint |\n| [`@junctionjs/destination-plausible`](packages/destination-plausible) | Plausible Analytics — privacy-first, consent-exempt |\n| [`@junctionjs/debug`](packages/debug) | In-page debug panel — real-time event flow visibility |\n\n## Quick start\n\n```bash\nnpm install @junctionjs/core @junctionjs/client\n```\n\n```typescript\nimport { createClient } from \"@junctionjs/client\";\nimport { amplitude } from \"@junctionjs/destination-amplitude\";\n\nconst client = createClient({\n  name: \"my-site\",\n  environment: \"production\",\n  consent: {\n    defaultState: {},\n    queueTimeout: 30000,\n    respectDNT: true,\n    respectGPC: true,\n  },\n  destinations: [\n    {\n      destination: amplitude,\n      config: { apiKey: \"YOUR_KEY\", mode: \"client\" },\n      consent: [\"analytics\"],\n    },\n  ],\n});\n\n// Track events\nclient.track(\"product\", \"viewed\", { product_id: \"SKU-123\", price: 29.99, currency: \"USD\" });\n\n// Update consent\nclient.consent({ analytics: true, marketing: false });\n\n// Identify users\nclient.identify(\"user-42\", { email: \"user@example.com\" });\n```\n\n## Architecture\n\nSee [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) for the full design document covering data flow, consent semantics, destination plugin interface, and migration paths.\n\n## Development\n\n```bash\n# Install dependencies\nnpm install\n\n# Build all packages\nnpm run build\n\n# Run tests\nnpm test\n\n# Type check\nnpm run typecheck\n\n# Lint\nnpm run lint\n```\n\n## Writing a destination\n\nDestinations are plain objects with three required methods:\n\n```typescript\nimport type { Destination, JctEvent, ConsentState } from \"@junctionjs/core\";\n\nexport const myDestination: Destination\u003c{ apiKey: string }\u003e = {\n  name: \"my-destination\",\n  version: \"0.1.0\",\n  consent: [\"analytics\"],\n  runtime: \"both\",\n\n  init(config) {\n    // Load SDKs, validate config\n  },\n\n  transform(event: JctEvent) {\n    // Convert Junction event to your format. Return null to skip.\n    return { name: `${event.entity}_${event.action}`, data: event.properties };\n  },\n\n  async send(payload, config) {\n    // Send to your service\n    await fetch(\"https://api.example.com/events\", {\n      method: \"POST\",\n      headers: { \"Authorization\": `Bearer ${config.apiKey}` },\n      body: JSON.stringify(payload),\n    });\n  },\n};\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftyssejc%2Fjunction","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftyssejc%2Fjunction","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftyssejc%2Fjunction/lists"}