CI/CD for a small team doesn't need a platform team or a 300-line pipeline. A setup that works well for two to ten developers has three parts: tests run automatically on every pull request, merging to main deploys to production, and each branch gets a preview URL for review. You can build all of it in an afternoon with GitHub Actions (or GitLab CI) and a host that deploys from Git.
The workflow in one picture
- A developer creates a branch and pushes commits.
- The branch deploys to its own preview URL so others can click through the change.
- They open a pull request. CI runs lint, type checks and tests.
- A teammate reviews the code and the preview.
- The PR can only merge when checks pass.
- Merging to
maindeploys production automatically.
Nobody runs a deploy command by hand, nobody uploads files over FTP, and production always matches main.
Step 1 - protect the main branch
Everything relies on main being the source of truth, so protect it:
- Require a pull request before merging (no direct pushes).
- Require status checks to pass (you'll add the CI check in step 2).
- Require at least one approval if you have more than one developer.
- Optionally require the branch to be up to date before merging.
In GitHub these are under Settings, Branches (branch protection rules or rulesets). GitLab has equivalent "protected branches" and merge request settings.
Step 2 - run checks on every pull request
Create .github/workflows/ci.yml:
name: CI
on:
pull_request:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run lint
- run: npm run typecheck --if-present
- run: npm test
- run: npm run build
Why each step:
npm ciinstalls exactly what's inpackage-lock.json, so CI matches production.- Lint and type checks catch whole classes of mistakes in seconds.
- Tests only need to be good enough to catch the bugs you'd be embarrassed to ship. Start with a handful around the most important flows.
- Build confirms the app actually compiles. A failing build in CI is far better than a failing deploy.
Once the workflow has run once, add the test job as a required status check in your branch protection.
Keep CI fast
A small team's CI should finish in a few minutes. If it gets slow, cache dependencies (the cache: npm line above does this), run only affected tests, and move slow end-to-end suites to a nightly job.
Step 3 - deploy on merge
The simplest reliable deploy is Git push to deploy: your host watches the repository and deploys when the production branch changes. On NewHost you connect a GitHub or GitLab repository, choose the branch, and set the install, build and start commands. Every push to that branch, which after step 1 means every merged PR, triggers a deployment through a webhook.
Typical settings for a Next.js app:
# Install
npm ci
# Build
npm run build
# Start
npm start
Production secrets live in the host's encrypted environment variables, not in the repository or in CI. See Git push to deploy for the full setup.
Should CI deploy instead of the host?
Some teams make the CI job call a deploy API after tests pass. It guarantees nothing deploys unless tests passed on that exact commit. With branch protection requiring checks before merge, you get most of that guarantee with fewer moving parts: code only reaches main after CI passed on the PR. For a small team the simpler setup usually wins.
Step 4 - preview deploys for review
Code review catches logic errors. Clicking through the actual change catches everything else: broken layouts on mobile, confusing copy, missing states.
On NewHost's Developer plan and up, pushes to non-production branches deploy to their own preview URL, up to five per app. Previews are removed when the branch is deleted or after 14 days without a deploy.
To get the most out of previews:
- Paste the preview URL in the PR description so reviewers (including non-developers) can test it.
- Point previews at a separate test database and test API keys, never production data.
- Keep previews out of search engines, for example with a
noindexheader on non-production environments.
Preview deployments explained goes deeper.
Step 5 - database migrations
Migrations are where small-team CI/CD most often goes wrong. A few rules:
- Run migrations as part of the deploy (for example
npx prisma migrate deploybefore start), not by hand. - Make migrations backwards compatible: add columns before code uses them, remove them only after code stops using them. That way a rollback of the code doesn't break against the new schema.
- Take an on-demand backup before risky migrations.
Step 6 - know when it breaks
Wire up notifications so a failed deploy doesn't go unnoticed. Deployment webhooks (such as deployment.succeeded) can post into your team chat. Webhooks explained covers receiving them safely.
A checklist for your first week
-
mainprotected; PRs required - CI runs lint, types, tests and build on every PR
- CI check required before merge
- Repository connected to hosting;
maindeploys automatically - Production secrets only in encrypted environment variables
- Preview deploys with a test database
- Migrations run during deploy
- Deploy notifications in chat
Frequently asked questions
Do small teams really need CI/CD?
Yes, arguably more than large teams, because nobody has time to deploy by hand or debug a release that "worked on my machine". A basic pipeline takes an afternoon to set up and saves that time within weeks.
Is GitHub Actions free?
GitHub includes a monthly allowance of Actions minutes, and public repositories have more generous terms. Check GitHub's current pricing for private repositories; a lean workflow like the one above uses few minutes per run.
How do I roll back a bad deploy?
Revert the offending commit on main with git revert and merge it. The host deploys the reverted code like any other change, and your history shows exactly what happened.
What if we have no tests yet?
Start with lint, type checks and the build step. They catch real bugs immediately. Add a few tests for your most important flows, such as sign-in and checkout, and grow from there.
Preview deploys start on the Developer plan. See the pricing page or read how Next.js hosting works with Git.