Contributing
Thank you for considering contributing to MyLinks! We want the contribution process to be as smooth and transparent as possible.
How to contribute
There are several ways to help:
- Reporting bugs
- Suggesting new features
- Improving the documentation
- Writing or improving tests
- Submitting code enhancements
Bug reports and feature requests
Open an issue on GitHub Issues.
For a bug, include a clear description of the problem, steps to reproduce it, and any relevant log or error messages. For a feature request, describe the problem you are trying to solve and how the feature would help.
Development setup
Toolchain
Node.js and pnpm versions are pinned in mise.toml at the repository root. With mise installed, mise install sets them up, and mise activates them automatically inside the repository.
mise install
pnpm installEnvironment
Copy the template to .env at the repository root, where Docker Compose and every just recipe read it. See Configuration for the variables, and for the ENV_PATH prefix a bare node ace run needs outside just.
cp .env.example .envRunning with Docker
The recommended method uses Docker for the PostgreSQL database. Recipes are defined in the Justfile and run with just:
just devThis starts a PostgreSQL container, resets the database and applies every migration, then starts the development server with hot reload.
Running without Docker
If you prefer a locally installed PostgreSQL:
Make sure PostgreSQL is running, and configure
DB_HOST,DB_PORT,DB_USER,DB_PASSWORDandDB_DATABASEin the root.env.Reset the database and apply migrations:
bashcd apps/webapp && ENV_PATH=../.. node ace migration:freshStart the development server, from the repository root:
bashENV_PATH=../.. pnpm run dev:webapp
The server is reachable at http://localhost:3333 (or the port set in your .env).
Working on the extension
The extension needs a running webapp to talk to. With one started, from the repository root:
pnpm run dev:extensionSee apps/extension/README.md for side-loading, Firefox builds, generating API types, and the rest of the extension-specific workflow.
Commands
Run just --list for every recipe, and see the scripts in the root package.json. Before opening a pull request, run:
pnpm run check && just testjust test brings the dev containers up and runs migration:fresh before the suites, so it wipes whatever is in the development database. The CI workflow does not call it: on every pull request and push to main it runs pnpm run check, then pnpm run test and pnpm run test:browser against a fresh database of its own.
just release does not run the tests and leaves the development database alone. release-it first runs pnpm run check, pnpm run build and just build-image, so a broken check, build or Dockerfile fails before the tag and the release exist.
Browser test suite
Most of the test suite is functional: real HTTP requests against the app, no browser involved. What a person actually clicks through is covered by the specs in apps/webapp/tests/browser, which drive a real (headless) browser with Playwright, against mailpit for the mail the app sends: registration with mail confirmation, account deletion and reactivation, the admin accounts table, collection visibility changes and their confirmations, and drag-and-drop reordering on the dashboard.
It needs two things a plain pnpm run test doesn't:
- mailpit running:
docker compose -f dev.compose.yml up -d mailpit, or the fulljust devstack. - A Chromium binary:
npx playwright install chromium, once per machine.
No separate build or dev server is required: node ace test boots the app the same way node ace serve does, embedded Vite dev middleware included, and serves real pages to the browser directly from source. If apps/webapp/public/assets exists from a previous pnpm run build, remove it first: its presence makes the app try to read a production manifest instead, which fails immediately.
With mailpit up and Chromium installed, pnpm --filter @my-links/webapp run test:browser runs the suite. pnpm run test never includes it; the two suites are deliberately kept apart so a routine pnpm run test never needs mailpit or a browser.
Pull requests
- Fork the repository and create your branch from
main. - Run
pnpm run check(lint, format check and typecheck across the monorepo) and make sure it passes. - Add tests for new features or bug fixes, co-located with the code they cover.
- Ensure existing tests still pass:
pnpm run testfor the webapp (needs PostgreSQL), andpnpm --filter @my-links/extension run checkwhen touching the extension (it runs the suite against both the Chromium and Firefox targets). If your change touches a flow the browser specs cover, also runpnpm --filter @my-links/webapp run test:browser(see above): it isn't part ofpnpm run testand reviewers won't assume it ran otherwise. - Write commit messages in the imperative mood, one logical change per commit.
- Clearly describe the purpose of your pull request, with relevant issue numbers if applicable.
Push your branch to your fork and submit a pull request against main. All contributions are reviewed by maintainers, who may request changes before merging.
Thank you for helping make MyLinks better!