Thank you for your interest in contributing to @supabase/server! This document provides guidelines and instructions for contributing to the project.
- Getting Started
- Development Setup
- Development Workflow
- Testing
- Submitting Changes
- Contributing a middleware
- Contributing a framework adapter
- Release Process
Check the open issues for something to work on, or open one to discuss a bug or feature before sending a PR.
- Node.js: 22.x or higher
- pnpm
- Fork and clone the repository:
git clone https://github.com/YOUR_USERNAME/server.git
cd server- Install dependencies:
pnpm install- Build the project to verify setup:
pnpm buildBuild the library for distribution:
pnpm buildWatch mode for development (rebuilds on file changes):
pnpm run devFormat all code using Prettier:
pnpm formatRun the unit and integration tests (no external dependencies needed):
pnpm testThe E2E suite (e2e/) runs real JWT issuance, real JWKS validation, and real
Supabase client operations against a local Supabase stack, across all four
adapters. It imports the library from dist/, so build first:
pnpm build
cd e2e && supabase start && cd .. # requires Docker
pnpm gen:env
pnpm test:e2eSee e2e/README.md for details. CI runs this suite in a
separate workflow (.github/workflows/e2e.yml).
CI publishes every pull request as a preview package. From Node, install it by PR number:
npm install https://pkg.pr.new/@supabase/server@<pr-number>Deno's npm: specifier rejects tarball URLs, and an import map pointing at
an extracted dist/index.mjs passes deno check without checking anything,
so neither route exercises the build there. esm.sh serves the PR's commit
directly, subpaths included:
import { withSupabase } from 'https://esm.sh/pr/supabase/server/@supabase/server@<sha>?target=deno'
import { withPostgresClient } from 'https://esm.sh/pr/supabase/server/@supabase/server@<sha>/middleware/postgres?target=deno'Pin the full commit sha, and add &deps=@supabase/supabase-js@<version> so
esm.sh resolves the peer to the version your project uses.
To try a release published to npm the same day, pass
--minimum-dependency-age 0 to deno check. Deno 2.9 and later apply a
minimum dependency age to npm packages.
We use Conventional Commits for automated releases. Format:
<type>(<scope>): <description>
[optional body]
[optional footer]
Types:
feat: New feature (triggers minor version bump)fix: Bug fix (triggers patch version bump)docs: Documentation changes onlytest: Adding or updating testschore: Maintenance tasks, dependency updatesrefactor: Code changes that neither fix bugs nor add featuresperf: Performance improvementsci: CI/CD configuration changes
Breaking changes:
- Use
feat!:orfix!:for breaking changes (triggers major version bump) - Or include
BREAKING CHANGE:in the commit footer
Examples:
feat: add support for view operations
fix: handle empty namespace list correctly
docs: update README with new examples
test: add integration tests for table updates
feat!: change auth config structure
BREAKING CHANGE: auth configuration now uses a discriminated union-
Create a branch from
main:git checkout -b feat/my-feature
-
Make your changes following the guidelines above
-
Commit using conventional commit format:
git commit -m "feat: add support for XYZ" -
Push to your fork:
git push origin feat/my-feature
-
Open a Pull Request with:
- Clear title following conventional commit format
- Description of what changed and why
- Reference any related issues (e.g., "Fixes #123")
- Screenshots/examples if adding user-facing features
-
Respond to feedback - maintainers may request changes
- Keep PRs focused - one feature or fix per PR
- Update documentation if you change public APIs
- Add tests for new functionality
- Ensure all CI checks pass
- Rebase on
mainif needed to resolve conflicts - Be responsive to review feedback
@supabase/server holds the middleware Supabase maintains: withSupabase, withSupabaseClient, withSupabaseAdminClient, withClaims, withRequiredClaims, withPostgresClient, withPostgresAdminClient, and withOAuthProtectedResource. Fixes and improvements to these are welcome as PRs.
New middleware starts as an issue, not a PR. Every entry here needs Supabase (keys, environment variables, a database connection, or Supabase API surface) and works with zero configuration on Supabase Edge Functions. Say in the issue how the proposal meets both, and the maintainers decide whether it ships here.
Middleware with no Supabase surface lives in its own package on top of @supabase/middleware; the engine's authoring guide walks the full path. The engine itself ships only the composition primitives and two worked examples, so new middleware does not land there either.
Layout. A composable entry lives in src/middleware/<name>/ with an index.ts and an index.test.ts, and exports from its own subpath, @supabase/server/middleware/<name>. Wire the subpath in package.json#exports, tsdown.config.ts#entry, and jsr.json#exports, and add its row to the import table in README.md. The existing entries are the template. The two auth gates, withSupabase and withOAuthProtectedResource, also export from the package root.
Naming. The with prefix means middleware: composable, chainable, and never the last entry in a chain. A terminal handler resolves the request instead of passing it on; it takes no prefix and lives outside src/middleware/. MCP-specific code stays separate from general middleware. When something turns out not to be MCP-specific, rename it and place it by the rules above.
Framework adapters (Hono, H3, …) are community-maintained and live in this repo under src/adapters/. They have additional requirements on top of the general PR guidelines above — tests covering every auth mode, no new runtime deps beyond a peer-dep, matching the existing adapter shape, and updating both adapter tables (in README.md and src/adapters/README.md).
See src/adapters/README.md for the full checklist before opening an adapter PR.
This project uses release-please for automated releases. You don't need to manually manage versions or changelogs.
-
You commit using conventional commit format (see above)
-
release-please creates/updates a release PR automatically when changes are pushed to
main- Updates version in
package.json - Updates
CHANGELOG.md - Generates release notes
- Updates version in
-
Maintainer merges the release PR when ready to release
- Creates a GitHub release and git tag
- Automatically publishes to npm with provenance
Versions follow Semantic Versioning:
- Major (1.0.0 → 2.0.0): Breaking changes (
feat!:,fix!:, orBREAKING CHANGE:) - Minor (1.0.0 → 1.1.0): New features (
feat:) - Patch (1.0.0 → 1.0.1): Bug fixes (
fix:)
Commits with types like docs:, test:, chore: don't trigger releases on their own.
Publishing is fully automated via GitHub Actions:
- Merge the release-please PR when ready
- GitHub Actions will automatically publish to npm with provenance
- No manual
npm publishneeded
- Open an issue for bugs or feature requests
- Check existing issues and PRs before creating new ones
- Tag your issues appropriately (
bug,enhancement,documentation, etc.)
By contributing to @supabase/server, you agree that your contributions will be licensed under the MIT License.