https://github.com/michaldziuba03/purly
SaaS platform for managing your brand links. Shorten links, generate QR codes, track traffic and more 🔗 📊
https://github.com/michaldziuba03/purly
bitly bull nodejs postgresql queue redis s3 saas shorten-urls shortener stripe tinyurl typescript url-shortener
Last synced: 3 months ago
JSON representation
SaaS platform for managing your brand links. Shorten links, generate QR codes, track traffic and more 🔗 📊
- Host: GitHub
- URL: https://github.com/michaldziuba03/purly
- Owner: michaldziuba03
- License: mit
- Created: 2021-09-29T18:17:36.000Z (about 4 years ago)
- Default Branch: main
- Last Pushed: 2025-07-24T23:35:35.000Z (3 months ago)
- Last Synced: 2025-07-25T01:49:55.627Z (3 months ago)
- Topics: bitly, bull, nodejs, postgresql, queue, redis, s3, saas, shorten-urls, shortener, stripe, tinyurl, typescript, url-shortener
- Language: TypeScript
- Homepage:
- Size: 2.33 MB
- Stars: 7
- Watchers: 1
- Forks: 3
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Codeowners: .github/CODEOWNERS
- Security: SECURITY.md
Awesome Lists containing this project
README
# purly ✂
SaaS platform for managing your brand links. Under active development. Primary goal of this project is to create sample that **does more** than just simple CRUD.
> Frontend is still in very early stage of development. It lacks proper error handling and will receive major upgrade when core features will be done.



> Currently only downloading as PNG is possible. In the future SVG and JPEG will be added.
![]()
![]()
> Account settings interactions example


> Link in Bio feature. More features to come after major refactor.
## Tech stack
- Node.js
- NestJS
- PostgreSQL ([Drizzle ORM](https://orm.drizzle.team/))
- Redis ([ioredis](https://github.com/redis/ioredis))
- Next.js
- React
- Docker
- Zookeeper ([node-zookeeper](https://github.com/yfinkelstein/node-zookeeper))
- Clickhouse ([clickhouse-js](https://github.com/ClickHouse/clickhouse-js))
- AWS S3 ([MinIO](https://min.io/))## Advanced concepts used in app
- [x] Asynchronous messaging (with BullMQ)
- [ ] Caching
- [ ] Rate-limiting
- [x] Error monitoring (with Sentry)## Features
- [ ] Email Verification
- [x] Social Authentication (Google, GitHub)
- [x] Email & Password Authentication
- [x] Reset Password flow
- [x] Google Recaptcha support
- [x] Paid monthly subscriptions (Stripe)
- [x] URL shortening
- [x] QR Codes generation
- [x] Reporting malicious URLs
- [x] UTM Generator
- [x] Mobile Redirects
- [x] Link Redirect Expiration
- [ ] Statistics for shortened URLs
- [x] Health checks
- [x] Link in bio
- [ ] Custom domains
- [x] Workspaces with members management### Todo
- write e2e tests (currently partially written for user, workspace and auth modules)
- create CI pipeline## Development
Project uses [Nx workspaces](https://nx.dev/) for building and handling monorepo structure.
### Run databases and services
```sh
cd docker
docker compose up
```### Run setup scripts
```sh
# will install depedencies and create .env file
npm run setup
# run migrations (will run migrations against database defined in env.POSTGRES_URI)
npm run db:migrate
# run migrations for stats database (definied CLICKHOUSE_ env variables)
npm run stats:migrate
```### Configure S3 with MiniO (optional)
Purly uses [MinIO](https://min.io/) to simulate AWS S3 for local development. We suggest to use AWS CLI for initial configuration.
Read about S3 local setup in `/tools/s3-local/README.md`
### Run applications (api, worker and frontend web app)
```sh
npm run serve
```### Forward Stripe webhook locally
Purly uses `STRIPE_WEBHOOK_PATH` variable for webhook URL obfuscation. Don't forget to replace it in production with your own random value.
```sh
stripe login # only once - stripe will remember your session
stripe listen --forward-to localhost:8000/api/stripe/webhook/e7a42abb5d31ec92bdfeec3cb0a4fa1b
```> Stripe CLI will give you webhook signing secret like `whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`. Save this value in .env as **STRIPE_WEBHOOK_SECRET** and restart API. CLI gives you the same secret so no need to repeat this step every time you run listen command.
## Contributing
Currently project is in early stage of development and many things are changing so often. Keep it in mind if you want to contribute.
1. Use [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) for commits and PRs.
2. If you want to introduce bigger change I recommend to create issue first with feature request and get approval from mantainer :) Otherwise your pull request can be declined and you will waste your time.
3. After changes in table schemas, run `db:generate` script to generate migrations and run `db:migrate` to run migration.## License
Distributed under the MIT License. See `LICENSE` for more information.
## Contributors
