Thanks for taking the time to contribute! ownz is a free, open-source, self-hostable link-in-bio and portfolio page builder, and it gets better every time someone opens an issue, fixes a typo, or ships a new block. Contributions of every size are welcome — you don't need to be an expert, and you don't need permission to get started.
If this is your first open-source contribution, you're in the right place. Look for issues labelled good first issue — they're scoped to be approachable, and maintainers are happy to help you through your first PR.
- Code of Conduct
- Ways to contribute
- Local setup
- Branch and PR flow
- Commit messages
- Checks your PR must pass
- Code style
- Sign your commits (DCO)
- Proposing a feature
- Adding a new block or template
- Reporting security issues
This project and everyone participating in it is governed by our Code of Conduct. By taking part, you agree to uphold it. Please report unacceptable behavior to conduct@ownz.net.
- Report a bug — open an issue with clear reproduction steps, what you expected, and what actually happened.
- Improve the docs — fix a broken link, clarify a confusing step, translate a string.
- Fix a bug or build a feature — grab an open issue or open one to discuss first (see Proposing a feature).
- Add a block or template — extend what people can put on their page (see Adding a new block or template).
- Help with translations — ownz is RTL-first with Arabic, French, and English support; improving any of these is very welcome.
ownz is a TypeScript monorepo using npm workspaces (shared, server, web):
- server — Node 20+, Hono, Drizzle ORM, PostgreSQL, Better-Auth
- web — the dashboard, built with React + Vite + Tailwind CSS v4
- shared — types and utilities used by both
The README has the full, up-to-date development steps (prerequisites, environment variables, database setup, and how to run the dev servers). Start there — this guide won't duplicate it. In short, you'll need Node 20+, a PostgreSQL database, and a .env file, then npm install at the repo root followed by the dev command described in the README.
If anything in the setup is unclear or out of date, that itself is a great first contribution.
We use a simple flow off main:
- Fork the repository and clone your fork.
- Create a branch off
mainwith a short, descriptive name:Prefixes likegit checkout -b fix/gallery-rtl-order
fix/,feat/,docs/,refactor/, andchore/help at a glance. - Make your change, keeping it focused (see Code style).
- Commit with a signed-off, conventional-style message (see below).
- Push to your fork and open a pull request against
ownz-network/ownz'smainbranch. - Fill in the PR description: what changed, why, and how to test it. Link the issue it closes with
Closes #123.
Keep PRs small and single-purpose — they're much easier to review and get merged faster. If you're working on something large, open an issue first so we can agree on the approach before you write a lot of code.
We follow Conventional Commits. The format is:
<type>(<optional scope>): <short summary>
Common types: feat, fix, docs, refactor, test, chore, perf, style, build, ci.
Examples:
feat(blocks): add audio embed block
fix(web): keep gallery order correct in RTL layouts
docs(readme): clarify DATABASE_URL format
refactor(server): extract link validation into shared
chore(deps): bump drizzle-orm to latest patch
Keep the summary in the imperative mood ("add", not "added"), under ~72 characters, and lowercase after the colon. Add a body if the change needs context.
Before you push, run these from the repo root — CI runs the same checks, and green locally means a smoother review:
npm run typecheck # TypeScript must type-check across all workspaces
npm run build # the project must build cleanly
npm run lint # if a lint script is present, it must passIf you touched something with tests, run them too (npm test). Please don't disable rules or // @ts-ignore your way past a failure — if a check is genuinely wrong, call it out in the PR so we can fix the root cause together.
- TypeScript everywhere. Prefer explicit types at module boundaries; let inference do the work inside functions.
- Formatting is automated. Run Prettier (and ESLint if configured) before committing, or enable format-on-save in your editor. Don't hand-format — let the tools own it so diffs stay about the change, not the whitespace.
- Keep changes focused. One concern per PR. Avoid drive-by reformatting of files you didn't otherwise touch — it buries the real change.
- Match the surrounding code. Follow the patterns already in the file and workspace rather than introducing a new style.
- Mind i18n and RTL. ownz is RTL-first and multilingual — don't hardcode user-facing strings, and make sure UI work behaves correctly in right-to-left layouts.
- No third-party trackers. ownz ships with self-hosted fonts and no external analytics or trackers; please keep it that way.
This project uses the Developer Certificate of Origin. It's a lightweight statement that you wrote the code you're contributing (or otherwise have the right to submit it under the project's license). You certify it by adding a Signed-off-by line to each commit, which git does for you with -s:
git commit -s -m "feat(blocks): add audio embed block"This appends a line like:
Signed-off-by: Your Name <you@example.com>
Use your real name and an email you can be reached at. If you forget, you can add the sign-off to your last commit with git commit --amend -s, or to a range with an interactive rebase. PRs without a sign-off can't be merged.
Have an idea? Open an issue before you build it. Describe the problem you're solving, who it's for, and a rough sketch of the approach. This lets us discuss scope and design up front and saves you from investing time in something that might need a different direction. Once there's rough agreement, you (or anyone) can pick it up.
Blocks (links, projects, gallery, embedded video, embedded audio, and so on) and page templates are core to what ownz does, and new ones are very welcome.
- Start by opening an issue describing the block or template and what it's for.
- Follow an existing block as your reference — mirror its structure for the shared type definition, the server-side handling/validation, and the dashboard editor UI in
web. - Make sure it renders correctly in all supported languages and in RTL layouts, and that it degrades gracefully in the static, self-contained HTML output.
- Add or update any relevant tests and documentation.
If you're unsure where a piece belongs, ask in your issue or draft PR — we'd rather help early than send you back at review time.
Please do not open a public issue for security vulnerabilities. Follow the process in SECURITY.md to report them privately.
If you just want to use ownz without running it yourself, there's a managed hosted version at ownz.net — the easiest way to try it out. Contributions here still benefit everyone, hosted and self-hosted alike.
Thank you for helping make ownz better. 💜