Open-source project
dubinc/dub avatar
dubinc/dub

Dub (dubinc/dub): the open core split behind a self hostable link tracker

The modern link attribution platform. Loved by world-class marketing teams like Framer, Perplexity, Superhuman, Twilio, Buffer and more.

24,853 stars3,313 forksTypeScriptNOASSERTION

At a glance

What is it?
Dub tracks short link clicks, conversions, and affiliate programs from a TypeScript monorepo, but the open source part is the core 99%: the ee directory is commercial, and the analytics layer is Tinybird rather than your own server. What a self hosted instance gives you, and what it does not.
Who is it for?
Pick Dub if you want a full attribution stack you can read and modify under AGPLv3, and go in knowing that self hosting means provisioning PlanetScale, Upstash, Tinybird, Stripe, and Resend yourself, and that the enterprise tier is not in the open tree. Skip it if SAML single sign-on, an audit trail, or a hosted team workspace is the deciding requirement, since those sit on the commercial side of the split.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Most of the code is AGPL, and the ee directory is not

Dub Technologies describes itself as a commercial open source company that uses the open core model. The core, which the project puts at 99%, is licensed under AGPLv3. The last 1% lives in an ee Enterprise Edition directory and is covered by a commercial license instead. Enterprise features in that tree are built by the core engineering team of Dub Technologies, Inc., who are hired full time, which means outside contributors can read that directory but cannot change its licensing terms. SAML and SSO sit on the commercial side of the split, with BoxyHQ named as the provider in the stack. The practical effect for anyone running their own instance is that short links, conversion tracking, and affiliate programs are available to them, while the enterprise tier is not, and no pull request can move a feature across that license boundary.

Click events go to Tinybird even when you run it yourself

The self hosting pitch is greater control over your data and design, but the stack named in this repository routes the interesting parts elsewhere. Tinybird handles analytics, PlanetScale is the database, and Upstash is the redis layer. Conversion tracking events, the data that separates an attribution tool from a shortener, are written to Tinybird, a hosted service, so a self hosted instance still sends click data off your own hardware unless you stand up substitutes and repoint the environment. Stripe carries payments and Resend carries email, which adds two more dependencies on outside accounts. A reader evaluating this code should treat it as an application you operate on top of other vendors rather than a single install, and should expect the list of accounts to provision to live in the self hosting guide instead of the repository.

Running the seed command from the repo root only prints a reminder

The root package.json binds the script name to one instruction: echo 'Run this script in apps/web'. The seed entry point only resolves inside the web app, so running it at the repository root produces a single line of output, no database rows, and no error message explaining the miss. From apps/web, two forms are supported.

bash
cd apps/web
pnpm run script dev/seed

and the truncating form.

bash
cd apps/web
pnpm run script dev/seed --truncate

The second form deletes all existing data before it inserts, and it asks for confirmation before deleting anything. Because that deletion sits behind an interactive prompt rather than a required flag, an unattended or interrupted run stops at the question instead of wiping a database that holds real click history.

A missing table means the Prisma schema never reached your database

The first documented failure reads The table <table-name> does not exist in the current database, and the fix given is `pnpm prisma:push`, which pushes the state of the Prisma schema file to the database without using migrations files. That wording carries a consequence for anyone moving between environments: push leaves no migration history, so there is no recorded trail of how a given database reached its current shape. The second documented failure is a local build that does not complete. The remedy is to delete all node_modules, .next, and .turbo directories in the apps and packages directories, reinstall with `pnpm install`, then rebuild with `pnpm build`. Both steps assume pnpm, since the root ships pnpm-workspace.yaml and pnpm-lock.yaml and nothing here installs with npm.

Node and pnpm are held to exact patch versions

The recommended versions table names node v23.11.0 and pnpm 9.15.9, and the root package.json repeats the pnpm pin in its packageManager field as [email protected]. That field turns the package manager choice into an enforced constraint rather than a suggestion, while node stays a recommendation, so a node mismatch tends to surface as the build failure described above instead of as an install error. Contributors have to watch two different failure surfaces for one toolchain. Because both numbers are exact, the repository gives no way to tell whether v23.11.0 tracks a fix in a neighbouring release or a team preference, and with no GitHub releases published there is no version history in which to look for the reason.

Publishing is a manual npm publish per workspace package

Six scripts in the root package.json push workspace packages to the npm registry: publish-cli, publish-embed-core, publish-embed-react, publish-tw, publish-ui, and publish-utils. Each one builds a single package through turbo, changes into its directory, and runs npm publish, so publish-cli targets @dub/cli under packages/cli, the embed scripts target @dub/embed-core under packages/embeds/core and @dub/embed-react under packages/embeds/react, and the last three target @dub/tailwind-config, @dub/ui, and @dub/utils. None of these scripts bumps a version, writes a changelog, or creates a tag, and the repository publishes no GitHub releases. For anyone depending on the CLI or the React embed, the version available is whatever the last person to run a publish script left sitting on npm.

Build, lint, clean, and test all delegate to turbo

The root scripts configure almost nothing themselves. build runs turbo build, dev runs turbo dev, lint runs turbo lint, clean runs turbo clean, and test runs turbo run test, while build:packages narrows the same graph to the workspace packages by handing pnpm -r --filter a pattern that selects only the packages directory. The top level layout matches that model, with apps and packages directories sitting beside package.json, turbo.json, prettier.config.js, and pnpm-workspace.yaml. What this costs a contributor is failure isolation: because the graph runs as one pipeline, a package that does not compile holds up a build for the web app even when the web app itself is sound. The seed scripts inherit the same assumption, which is why they are written as cd apps/web before the script name.

The prettier scripts cover ts, tsx, and md and nothing else

Two scripts handle formatting. format hands prettier a --write flag over a single glob, and prettier-check hands it a --check flag over the same glob, and that glob is limited to ts, tsx, and md files. Read the extension list literally and the coverage stops there, so package.json, turbo.json, pnpm-workspace.yaml, prettier.config.js, and the YAML files under .github are formatted by hand and never verified by either command. Contributors can get a clean prettier-check result that says nothing about those files. For a reviewer that means configuration drift is caught by reading diffs, and for the build graph it means the turbo pipeline and the workspace definition can move apart without any check failing.

Editorial conclusion

Pick Dub if you want a full attribution stack you can read and modify under AGPLv3, and go in knowing that self hosting means provisioning PlanetScale, Upstash, Tinybird, Stripe, and Resend yourself, and that the enterprise tier is not in the open tree. Skip it if SAML single sign-on, an audit trail, or a hosted team workspace is the deciding requirement, since those sit on the commercial side of the split. Before either, read LICENSE.md against the ee directory, confirm your node v23.11.0 and pnpm 9.15.9 pins, and read the self hosting guide for the list of services you are signing up for.

Frequently asked questions

Is dub co legit?

The project states that its platform powers 100M+ clicks and 2M+ links monthly and names Twilio, Buffer, Framer, Perplexity, Vercel, and Laravel as users. Those are first party claims in the README, not outside verification, and the last push on the repository is dated 2026-10-01 with no GitHub releases behind it.

What is a dub account?

On the hosted service at dub.co, an account is the login tied to short links, conversion tracking, and affiliate programs. In the codebase, sign in runs through NextAuth.js, SAML and SSO are handled through BoxyHQ, and billing runs through Stripe.

Is dub co open-source?

Partly. Dub Technologies calls the project open core: the core 99% sits under AGPLv3, and the remaining 1% is in an ee Enterprise Edition directory under a commercial license. The root package.json declares AGPL-3.0-or-later and marks the workspace package private.

What is the dub sh website?

Nothing in the dubinc/dub repository points at a dub.sh domain. Every link in the project, including the self hosting guide at https://dub.co/docs/self-hosting/guide, sits on dub.co, so what dub.sh serves is not answered anywhere in this codebase.

Official sources

  1. dubinc/dub on GitHub
  2. Issues
  3. Project website
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/dubinc-dub.svg)](https://hysenlabs.com/projects/dubinc-dub)