Contributor access research: cloud-scoped vs fully-local development
Research date: 2026-09-09. Status: facts gathered from vendor documentation only. No recommendation, no configuration changed, no keys created. Primary sources only (Convex, Vercel, GitHub, Clerk official docs and pricing pages). Every claim is followed by the page that owns it.
Scope: what the platforms actually permit for outside contributors on a Next.js (Vercel) + Convex + Clerk project in a single-owner GitHub repo. Two models were investigated but not compared or scored here: (A) scoped cloud access — contributor pushes Vercel preview deployments and reads a shared dev Convex deployment; (B) fully-local development — local Convex backend plus seeded data, no cloud account.
1. Convex team membership, roles, and seats
Convex has two built-in team roles, Admin and Developer, plus a project-scoped Project Admin role.
A Developer can "Create new projects and deployments", "View existing projects, and create development and preview deployments for these projects", and "View the team's usage and billing status (such as previous and upcoming invoices)". Critically for a shared-cloud model: "Developers may read data from production deployments, but cannot write to them." Convex teams documentation
An Admin can do everything a Developer can, plus invite and remove team members, change other members' roles, manage the subscription and billing details, and change the team name, slug, and default region. "Team Admins are also implicitly granted project admin access to all projects within the team." Convex teams documentation
Project Admin is granted per project (automatically to the creator of a project) and adds the ability to update the project name and slug, update the project's default environment variables, delete the project, and write to production deployments. Convex teams documentation
Restriction of a member to one project: members are invited at the team level, and the built-in Developer role grants visibility of existing projects across the team. There is no documented built-in mechanism to scope a member to a single project; the only project-scoped grant documented is Project Admin, which adds permissions rather than removing them. Fine-grained scoping is described as a Business-tier feature: custom roles with fine-grained permissions. Convex teams documentation
Restriction to non-production deployments: partially available by role. A Developer cannot write to production, but the same page states a Developer may read production data. So "developer" is not equivalent to "cannot see production data". Convex teams documentation
Plan and seat facts as published in 2026:
- Free and Starter: "Free or $0/month and pay as you go", 1-6 developers, preview deployments included, no log streaming and no custom domains. Convex pricing
- Professional: "$25 per developer/month", 1-20 developers, adds log streaming, custom domains, exception reporting, and daily backups. Convex pricing
- Business/Enterprise: "$2,500 monthly minimum", 50+ members, adds SAML/SSO and dedicated deployments; no per-developer price is quoted. Convex pricing
Deployment count is also plan-limited: 40 deployments per team on Free/Starter, 300 on Professional, unlimited on Business/Enterprise. Every deployment created — including previews — counts against that limit. Convex limits, Convex preview deployments
Billing language confirms seats are per developer: the teams page refers to "seat fees (the amount paid for each developer in your team)". Convex teams documentation
2. Per-developer dev deployments
Convex documents the deployment topology explicitly: "A project has one production deployment, up to one cloud deployment for development per team member, and potentially many transient preview deployments." Convex local deployments
Data is not shared across those deployments: "Each Convex deployment contains its own data, functions, scheduled functions, etc." Convex local deployments
In the dashboard these appear as distinct entries — production, dev/<your name>, preview/<branch> — selectable
from the deployment picker.
Convex deployments dashboard
Consequence for model (A): there is no documented "shared dev database" primitive. A personal cloud dev deployment is per member and privately seeded; sharing one dataset between contributors means either pointing them all at one deployment's credentials or re-seeding each deployment from an export (see section 6).
npx convex dev targets your dev deployment and prompts for login on first run to create a project.
Convex CLI reference
That login requirement has an escape hatch. In anonymous/agent mode the CLI provisions a local backend instead:
"when no deployment is already configured and CONVEX_DEPLOY_KEY isn't set, the CLI defaults to provisioning a local
deployment automatically", and in non-interactive shells "npx convex will never prompt the agent to log in".
Convex agent mode
So: a cloud dev deployment inside someone else's project requires team membership (the Developer role is what grants "create development and preview deployments for these projects"), while a local deployment requires no account at all. Convex teams documentation, Convex local deployments
3. Convex preview deployments
Mechanism: a preview deploy key is generated on the project's dashboard settings page and supplied as
CONVEX_DEPLOY_KEY. Preview deploy keys have the form preview:team-slug:project-slug|eyJ2...0= and "modify
standard npx convex deploy behavior to direct code to preview branches rather than main production systems".
Convex deploy key types
Commands: npx convex deploy --preview-name="my-preview-deployment-name" creates or reuses a preview deployment by
name; npx convex deploy --preview-create="name" deletes and recreates it on every deploy; --preview-run=<functionName>
runs a Convex function against the freshly created deployment to seed sample data. If the seeding function fails,
the deployment is still provisioned but the deploy command fails.
Convex preview deployments
CI integration: "When deploying from Vercel, Netlify, Cloudflare Pages, or GitHub Actions, you can simply run
npx convex deploy and the preview name is determined automatically."
Convex preview deployments
Vercel wiring specifically: override the build command to npx convex deploy --cmd 'npm run build', and create the
CONVEX_DEPLOY_KEY environment variable in Vercel scoped to the Preview environment only (production and other
environments unchecked). "npx convex deploy will read CONVEX_DEPLOY_KEY from the environment, and use it to
create a Convex deployment associated with the Git branch name". Seeding is added by appending
--preview-run 'functionName' to the build command.
Convex on Vercel
Plan requirement and lifetime: preview deployments are listed on Free & Starter and above, and the feature is in beta. They are cleaned up automatically after "5 days (Free and Starter plans)" or "14 days (Professional, Business, and Enterprise plans)", and each one counts against the team's deployment limit. Convex pricing, Convex preview deployments
Seeding a preview from a real dataset is also documented as an import step rather than a function call — the import
docs give a Vercel example that runs npx convex import --preview-name "$VERCEL_GIT_COMMIT_REF" seed_data.zip when
VERCEL_ENV is preview.
Convex data import
On handing a preview deploy key to CI that runs fork PRs, the documentation supports these facts rather than a verdict:
- The key is project-scoped (
preview:team-slug:project-slug), and Convex's guidance for handing deployments to agents or CI jobs is to create keys "scoped just to it"; deploy keys belong in the CI provider's secret store, not in the repository. Convex deploy key types - The key's capability is creating and deploying arbitrary Convex functions into preview deployments of that project, and preview deployments consume the team's deployment quota. Convex preview deployments
- GitHub does not expose repository secrets to
pull_request-triggered workflows from forks in the first place (section 8), so a fork-PR workflow cannot readCONVEX_DEPLOY_KEYunless the workflow is deliberately switched to a privileged trigger, which GitHub warns against (section 8). GitHub events that trigger workflows
4. Local Convex backend
Current state: local deployments are a documented, in-beta feature. "Instead of syncing code to a Convex dev
deployment hosted in the cloud, you can develop against a deployment running on your own computer. You can even use
the Convex dashboard with local deployments!" Selection is via npx convex deployment select local, and
npx convex deployment select dev switches back to the personal cloud dev deployment.
Convex local deployments
Account requirement: none. "You can use local deployments to develop with Convex without having to create an
account. Whenever you want to create an account to deploy your app to production or to use more Convex features, you
can use npx convex login to link your local deployments with your account." Agent/CI shells can force this with
CONVEX_AGENT_MODE=anonymous, which also enables npx convex init to initialise a deployment before pushing code.
Convex local deployments,
Convex agent mode
Process model and persistence: "the local Convex backend runs as a subprocess of the npx convex dev command and
exits when that command is stopped", which means a convex dev must be running for npx convex run or a frontend to
reach it. "State for local backends is stored in a .convex directory in your project."
Convex local deployments
Documented limitations:
- No public URL. Local deployments listen on your own computer, so inbound HTTP from services like Twilio does not work, and you cannot power a website with Convex WebSocket connections that users' browsers must reach. The docs suggest a proxy such as ngrok or a cloud deployment for those cases.
- Node actions need a matching Node.js version. Actions in files marked
"use node;"require the same Node.js version the project is configured for, by default Node.js 20. - Node.js actions run directly on your machine with unrestricted filesystem access; queries, mutations, and Convex-runtime actions still run isolated.
- Logs are cleared every time
npx convex devrestarts. - Browser caveats: Safari blocks localhost requests, preventing the dashboard from working with local
deployments; Brave blocks them by default and needs the
#brave-localhost-access-permissionflag plus a per-site "Localhost access: Allow" setting. - Not recommended for production, because development deployments send function-result logs and full stack traces to connected clients.
Feature-by-feature gaps: the local-deployments page does not enumerate file storage, scheduled functions, vector search, auth, or components as unsupported. The nearest documented statements are (a) the limitation list above, which is about URLs, Node versions, isolation, logs, and browsers rather than product features, and (b) the agent mode page, which says local backends suit "ephemeral agents that don't require webhooks or default environment variables" and are not suitable for agents needing "crons, or integrations that aren't available locally". Convex local deployments, Convex agent mode
Windows support: not stated either way on the local-deployments page. See "Unknowns" below.
Export/import against a local deployment: the CLI's import/export commands target the currently selected deployment,
and npx convex deployment select local makes the local backend the current deployment; the import documentation's
first listed use case is "Seed dev deployments with sample data" via npx convex import seed_data.zip. The docs do
not contain an explicit sentence confirming export/import with a local backend, so treat this as inferred from the
deployment-selection model rather than stated.
Convex local deployments,
Convex data import
Self-hosting is a separate, documented path from local dev: "you can self-host a production deployment using the open source convex-backend repo", and self-hosted Convex "supports all the free-tier features of the cloud-hosted product". Convex local deployments, Convex self-hosting guide
5. Auth (Clerk or Convex Auth) against a local backend
Convex's Clerk integration is configured server-side in auth.config.ts with a domain (the Clerk Frontend API
issuer URL, https://verb-noun-00.clerk.accounts.dev in development, https://clerk.<your-domain>.com in
production) and applicationID: "convex", with the domain typically supplied through a CLERK_JWT_ISSUER_DOMAIN
environment variable. The configuration reaches the backend only when it is synced: "you must run npx convex dev or
npx convex deploy after adding a new provider to sync the configuration to your backend" — npx convex dev is the
command that runs the local backend, so the same sync step applies there.
Convex + Clerk
Convex's auth model is provider-agnostic by design: Convex accepts OpenID Connect ID tokens in JWT form, which any service implementing the appropriate OAuth endpoints can issue. Convex authentication overview
Convex Auth (the @convex-dev/auth library) is installed with npm install @convex-dev/auth @auth/core@0.41.1 and
initialised with npx @convex-dev/auth, adding authTables to the schema and swapping ConvexProvider for
ConvexAuthProvider. Its callback handling depends on a SITE_URL deployment environment variable pointing at the
frontend origin (set for local development with npx convex env set SITE_URL http://localhost:5173, port adjusted).
Convex Auth setup,
Convex Auth manual setup
The one structural caveat that the local-deployment docs do impose on any auth flow: a local backend has no public URL, so any provider callback or webhook that must reach the Convex backend from the internet needs a proxy. Convex local deployments
6. Sharing data: export, import, and a local dashboard
Export: "You can export your data to a zip file from Convex by taking a backup and downloading it. Alternatively, you
can export the same data with the command line: npx convex export --path ~/Downloads". A streaming/paginated export
path exists via the Data Sync API or third-party integrations.
Convex data export
Import: npx convex import <path>.zip restores a backup ZIP into a deployment; "Documents will retain their _id and
_creationTime fields so references between tables are maintained." Per-table import is
npx convex import --table <tableName> <path> for CSV, JSON, or JSONLines. "The default is to import into your dev
deployment. Use --prod to import to your production deployment or --preview-name to import into a preview
deployment."
Convex data import
Format and size constraints worth knowing before shipping a seed file:
.csvfiles must have a header, and cells are read as a float or a string;.jsonlneeds one JSON object per line;.jsonmust be an array of objects.- "JSON arrays have a size limit of 8MiB. To import more data, use CSV or JSONLines."
- ZIP imports can carry Convex-specific types (Int64, Bytes) preserved through
generated_schema.jsonl; JSON and JSONL cannot. - ZIP exports that include file storage import the files and preserve
_storagedocuments with their_id,_creationTime, andcontentType. - Imports into a table with existing data fail by default;
--appendor--replaceare required. - Imports are atomic per table (except
--append), so queries never observe a partial import. - "Data import is not always supported when importing into a deployment that was created before Convex version 1.7."
- Import consumes database bandwidth (and file bandwidth when file storage is included), metered as
_cli/import. - Manual edits to the ZIP between export and import are undocumented and discouraged.
Dashboard against a local backend: "You can use local deployments with an existing Convex project, and view your deployment in the Convex dashboard under your project. You can also use local deployments without a Convex account and debug and inspect them with a locally running version of the Convex dashboard." Safari and Brave block localhost requests and break this (section 4). Convex local deployments
Self-hosted dashboard image: the self-hosting guide runs two Docker services — a backend on http://127.0.0.1:3210
(with HTTP actions on :3211) and a dashboard on http://localhost:6791. Credentials come from
docker compose exec backend ./generate_admin_key.sh, and the CLI is pointed at it by setting
CONVEX_SELF_HOSTED_URL and CONVEX_SELF_HOSTED_ADMIN_KEY in .env.local, after which npx convex dev and other
npx convex commands operate against that backend.
Convex self-hosting guide
7. Vercel: fork PRs, preview deployments, and seats
Default behaviour: "Vercel for GitHub will deploy every push by default. This includes pushes and pull requests made to branches." Each PR's latest push gets a unique preview URL, posted as a PR comment. Vercel for GitHub
Forks are the exception. "If you receive a pull request from a fork of your repository, Vercel will require authorization from you or a team member to deploy the pull request. This behavior protects you from leaking sensitive project information such as environment variables and the OIDC Token. You can disable Git Fork Protection in the Security section of your Project Settings." Vercel for GitHub
That sentence is the whole exposure story: a fork preview build runs the fork's code with the project's Preview environment variables and, when enabled, the Vercel OIDC token, which is why authorization is required and why disabling Git Fork Protection is described as removing that protection. Vercel for GitHub
Preview environment variables are per-environment and can additionally be scoped per branch: "Branch-specific values override Preview variables with the same name", which is the documented way to give one branch different values from the general Preview set. Vercel environments
Preview URLs are not public-by-default if Deployment Protection is on: Standard Protection "protects all deployments except production domains" and is available on all plans, using Vercel Authentication (access limited to Vercel users with suitable access rights). Deployment Protection has been enabled by default for new projects. Vercel Deployment Protection
CLI deploys by a non-team-member: the CLI's own flow requires selecting a team and linking a project ("? Which team? My Awesome Team"), so a CLI deployment is made in the context of a team the acting account has access to. Vercel project linking
Seat costs for adding a contributor:
- Hobby is not a collaboration plan: "Team collaboration features" are listed as Pro-only, RBAC is marked
N/Aon Hobby, and the fair-use guidelines restrict Hobby "to non-commercial, personal use only". Vercel Hobby plan - On upgrade, "Developer seats cost $20 per user / month, while Viewer seats are free." Vercel Hobby plan
- Role shapes relevant to an outside contributor: Developer (team-level) can create deployments and control environment variables "particularly for preview and development environments", but is "restricted from altering production environment variables and team-specific settings" — while still able to "deploy to production by merging to the production branch in Git-based workflows". Contributor is the only role that can be scoped per project: "Contributors have no access to projects unless explicitly assigned", and only contributors can hold the project-level roles (Project Administrator, Project Developer, Project Viewer). Pro Viewer is read-only, can comment on preview deployments, and "Pro Viewer seats are provided free of charge on Pro teams". Vercel access roles
- Note the Project Viewer role can "Examine environment variables across all environments", so a read-only project grant is not the same as hiding secrets. Vercel access roles
8. GitHub Actions: fork PR triggers, secrets, and approval
Secrets on fork PRs: "With the exception of GITHUB_TOKEN, secrets are not passed to the runner when a workflow is
triggered from a forked repository. The GITHUB_TOKEN has read-only permissions in pull requests from forked
repositories."
GitHub events that trigger workflows
Also on that page: "Workflows don't run in forked repositories by default. You must enable GitHub Actions in the Actions tab of the forked repository", and "When a first-time contributor submits a pull request to a public repository, a maintainer with write access may need to approve running workflows on the pull request." GitHub events that trigger workflows
pull_request_target runs "in the context of the default branch of the base repository, rather than in the context
of the merge commit, as the pull_request event does", which is what makes secrets available — and dangerous:
"Running untrusted code on the pull_request_target trigger may lead to security vulnerabilities. These
vulnerabilities include cache poisoning and granting unintended access to write privileges or secrets." The docs add
"Avoid using this event if you need to build or run code from the pull request."
GitHub events that trigger workflows
The security-hardening guidance repeats it: "The pull_request_target and workflow_run workflow triggers, when
used with the checkout of an untrusted pull request, expose the repository to security compromises"; such workflows
are "privileged", sharing the main-branch cache and potentially holding write access and referenced secrets;
"Workflows that use these triggers must not explicitly check out untrusted code, including from pull request forks."
GitHub Actions secure use reference
Workflow approval settings for fork PRs, configurable at repository, organization, and enterprise level, with "all first-time contributors require approval to run workflows" as the default:
- "Require approval for first-time contributors who are new to GitHub" — approval only for users new to GitHub with no prior merged commits or pull requests in the repository.
- "Require approval for first-time contributors" — approval for users who have never had a commit or pull request merged into the repository.
- "Require approval for all external contributors" — approval for any user who is not a member or owner of the repository or an organization member.
GitHub Actions repository settings
9. Clerk: sharing a development instance
Clerk separates instances by environment. The development instance is intended for "local development" and has "a more relaxed security posture", signalled by a dashboard banner, prefixed email/SMS templates, and shared social credentials specifically so it is not mistaken for production. Clerk environments
Key semantics: the Publishable Key "will be prefixed with pk_test_ in development instances and pk_live_ in
production instances", and the Secret Key "will be prefixed with sk_test_ in development instances and sk_live_
in production instances" with the explicit instruction "Do not expose this on the frontend with a public
environment variable".
Clerk environment variables
Clerk states the publishable key is safe to expose on the frontend and does not need rotating if it becomes public; the secret key must be kept private, and development and production instances are independent — rotating the production secret key does not affect the development one, and vice versa. Clerk API key rotation
Localhost: development instances are built for it. Because the frontend runs on localhost while Clerk's API is on an
accounts.dev domain, sessions are carried by a "dev browser" value in a querystring parameter (__clerk_db_jwt)
rather than cookies, and this querystring mechanism "is not secure enough for production use" since the value can
appear in logs and browser history. Development instances are restricted to accounts.dev domains and are not
indexed by search engines.
Clerk environments
Per-instance user cap: "Development instances are capped at 100 users, and user data can not be transferred between instances." Clerk environments
Clerk publishes no statement that a dev-instance secret key is safe to hand to third parties; what it publishes is that the secret key must never reach the frontend, that dev instances have a deliberately relaxed security posture, and that dev and prod key material are independent. Anyone holding a dev secret key can act as the backend of that dev instance, including over its (capped) user records. Clerk environment variables, Clerk environments
Unknowns / could not verify
- Convex dashboard visibility of production environment variables for the Developer role. The teams page says Developers may read production data and that updating a project's default environment variables is a Project Admin power, but it does not say whether a plain Developer can view a production deployment's environment variable values in the dashboard. Not stated on Convex teams documentation.
- Windows support for
npx convex dev --local. The local-deployments page lists limitations (no public URL, Node version, filesystem access, logs, Safari/Brave) but makes no platform statement, and no other primary page found addresses Windows explicitly. Convex local deployments - Explicit confirmation that
npx convex export/importwork against a local backend. Inferred fromnpx convex deployment select localmaking the local backend the current deployment plus the documented "seed dev deployments" use case; no sentence in the docs names local deployments in the import/export pages. - Per-feature local parity list (file storage, scheduled functions/crons, vector search, auth, components). The docs give a limitation list and the agent-mode note about crons and "integrations that aren't available locally", but no authoritative supported/unsupported feature matrix for local backends was found.
- Whether a Convex preview deploy key can create deployments beyond the named project. The key format is
preview:team-slug:project-slug, which reads as project-scoped, but the docs do not enumerate the exact permission set of a preview key (as they do fordeployment:deployon production keys). - Vercel access-token scoping semantics for a non-team-member. The CLI flow requires choosing a team, and tokens are created from account settings, but the exact token scope options and whether a token can be limited to a single project were not confirmed from a primary page in this pass; the REST API reference index was retrieved but the access-token section was not read.
- Exact current wording and default state of Vercel's "Git Fork Protection" toggle. Its behaviour and location ("Security section of your Project Settings") come from Vercel for GitHub; the dedicated settings page describing the toggle itself was not retrieved.
- Whether Convex Business custom roles can restrict a member to a single project. The teams page mentions "custom roles with fine-grained permissions" on Business but does not enumerate them. Convex teams documentation
- Convex preview deployment count limits distinct from the team deployment limit. Only the shared per-team deployment ceiling (40/300/unlimited) was found. Convex limits