Source code handoff checklist for clients and agencies
Use this source code handoff checklist to export, document, rotate secrets, run migrations, validate builds, and confirm deployment ownership with clients.

What a source code handoff should achieve
A source code handoff is the moment the project stops being “something the agency can run” and becomes “something the client can own.” Without a clear handoff, common problems show up fast: the app builds only on one laptop, production depends on a secret that nobody can find, or a small update turns into days of guesswork.
The goal of any source code handoff checklist is simple: after the transfer, the client can build, run, and deploy the product without needing the agency on call. That does not mean “no support ever.” It means the basics are repeatable and documented, so the next person can pick it up with confidence.
What counts as deliverables should be explicit. At minimum, a complete handoff usually includes:
- The full repository (including deployment files and migration scripts)
- Setup docs that work for a clean machine
- Access handover (accounts, permissions, and where the system lives)
- A runbook for routine tasks (deploying, rollback, backups, logs)
- A final “known-good” version tag or snapshot the client can reference
Scope matters as much as content. Some handoffs cover only one environment (for example, production). Others include dev, staging, and production with separate settings and processes. If you do not name which environments are included, people assume different things, and that’s where outages happen.
A practical way to define success is a verification test: a person who did not build the app can export the code (for example, from a platform like Koder.ai), follow the docs, set environment variables, run migrations, build, and deploy to the agreed environment.
This checklist focuses on technical readiness: environment variables, secrets rotation, database migrations, deployment scripts, and build verification. It does not cover legal terms, contracts, IP clauses, or payment disputes. Those matter too, but they belong in a separate agreement.
Before you export: agree on ownership and timing
A clean handoff starts before any export happens. If you agree on who owns what and when, you avoid last-minute surprises like broken deployments, unpaid hosting, or missing access.
Set the handoff date and a short freeze window
Pick a handoff date and define a freeze window (often 24-72 hours) where only urgent fixes go in. This keeps the exported code and the running system in sync. If a hotfix is needed during the freeze, write down exactly what changed and make sure it is included in the final export.
Clarify ownership of accounts and billing
Decide who will own DNS, cloud hosting, and any paid services after the handoff. This is not just paperwork. If billing stays on the agency card, services can be paused later without warning.
A quick way to make it concrete:
- Name the account owner for DNS, hosting, and email
- Confirm who pays each bill starting on the handoff date
- Decide whether accounts are transferred or recreated under the client
- Record the support contact for each provider
Write this down in plain language so both sides can follow it.
List environments and where they run
Agree on what environments exist (local, staging, production) and where each one runs. Note whether staging is a separate server, a separate database, or just a feature flag. If you used a platform like Koder.ai, also confirm what is hosted there vs what is expected to run in the client’s infrastructure after export.
Collect access early
Do not wait until the last day to request access. Make sure the right people can reach what they need: the repo, CI, hosting, the database, and the email provider.
Also agree on the final acceptance test and sign-off process. For example: “Client can build from a clean machine, run migrations, deploy to staging, and pass the smoke test. Then both sides sign off in writing.”
Repo and documentation basics to include
A good source code handoff checklist starts with a repo that a new team can open and understand in minutes. Confirm what is included (app code, config templates, scripts) and what is intentionally missing (real secrets, private keys, large generated files). If something is excluded, say where it lives and who owns it.
Keep the structure predictable. Aim for clear top-level folders like frontend/, backend/, mobile/, infra/, scripts/, and docs/. If the project is a monorepo, explain how the pieces relate and how to run each one.
Your README should be usable by someone who did not build the project. It should cover prerequisites and the fastest path to a working dev run, without guesswork.
What to document (minimum)
Include a short, human README section that answers:
- What this repo contains and what it does (one paragraph)
- Prerequisites with exact versions (runtime, package manager, Docker if needed)
- One-command start steps for local dev (and what “success” looks like)
- How to run tests and build a production artifact
- Where to find key docs: architecture notes, migrations, deployment notes
Add simple architecture notes in plain language: what talks to what, and why. A small diagram is optional, but a few sentences are usually enough. Example: “React frontend calls the Go API. The API reads and writes PostgreSQL. Background jobs run as a separate worker process.”
Finally, include a versioned changelog or release notes for the handoff build. This can be a CHANGELOG.md or a short “handoff release notes” file that states the exact commit/tag, what was shipped, and known issues.
If the code was exported from a platform like Koder.ai, note the generated project type (web, server, mobile), the expected toolchain (for example React, Go, PostgreSQL, Flutter), and the supported OS/tooling versions the client should use to reproduce the build.
Environment variables: inventory and documentation
Environment variables are often the reason a “working app” fails right after handoff. A good source code handoff checklist treats them like part of the product, not an afterthought.
Start by writing an inventory that a new team can follow without guessing. Keep it in plain language, and include an example value format (not real secrets). If a variable is optional, say what happens when it is missing and what default is used.
A simple way to present the inventory is:
- Variable name, what it controls, and an example format
- Required vs optional, plus any default behavior
- Where it is set (CI, hosting dashboard, local .env file)
- Which environments need different values (dev, staging, production)
- Who owns changes (client, agency, or shared)
Call out environment-specific differences clearly. For example, staging might point to a test database and a sandbox payment provider, while production uses live services. Also note values that must match across systems, like callback URLs, allowed origins, or mobile app bundle identifiers.
Document where each value lives today. Many teams split values across places: local .env files for development, CI variables for builds, and hosting settings for runtime. If you used a platform like Koder.ai to export the app, include a .env.example file and a short note on which variables must be filled in before the first build.
Finally, prove there are no secrets hiding in the repo. Don’t just check the current files. Review commit history for accidental keys, old .env files, or copied credentials in sample configs.
Concrete example: a React frontend plus a Go API might need API_BASE_URL for the web app, and DATABASE_URL plus JWT_SIGNING_KEY for the backend. If staging uses a different domain, write both values and say where to change them, so the new team doesn’t ship staging settings to production.
Secrets rotation: transfer safely, then prove it works
A handoff is not complete until the client controls every credential the app needs. That means rotating secrets, not just sharing them. If an agency (or a former contractor) still has working keys, you have an open door you cannot audit.
Start by making a full inventory. Don’t stop at database passwords. Include third-party API keys, OAuth client secrets, webhook signing secrets, JWT signing keys, SMTP credentials, storage access keys, and any “temporary” tokens sitting in CI.
Here’s a simple source code handoff checklist for rotation day:
- List every secret, what it unlocks, and where it is currently set (local env files, CI, hosting dashboard, vault)
- Create new credentials under the client’s accounts, and set an owner for each (a person and a team inbox)
- Update the app config to use the new values, then deploy to a staging or test environment first
- Revoke the old credentials immediately after the new ones are confirmed working
- Write down the exact rotation steps so the next rotation is boring and fast
After rotation, prove nothing broke. Run quick “real user” tests instead of only checking logs.
Focus on flows that depend on secrets:
- Login, signup, password reset, and token refresh
- Payments, email sending, and file uploads
- Webhooks (signature verification and retry handling)
- Background jobs or scheduled tasks that call external APIs
- Admin actions that hit privileged endpoints
Example: if you exported a project from Koder.ai and the app uses a payment provider plus email delivery, rotate both keys, redeploy, then place a small test transaction and send a test email. Only after those succeed should you revoke the agency-owned keys.
Finally, document where secrets live going forward (vault, CI variables, or hosting settings), who can change them, and how to roll back safely if a rotation causes errors.
Database migrations and data handling
A handoff can look “done” while the database is the part that breaks first. Treat migrations and data like a product of their own: versioned, repeatable, and tested.
Start by writing down the current database version and where migrations live in the repo. Be specific: the folder path, naming pattern, and the latest migration ID (or timestamp). If you’re using PostgreSQL (common with Go backends), also note any required extensions.
What to document (so someone else can run it)
Include a short runbook that answers these questions:
- Which command runs migrations, and what order to run things in (create database, apply migrations, then seeds)
- How it differs by environment (local, staging, production), including any “safe mode” flags
- Whether migrations are automatic on deploy or must be run manually, and who is allowed to run them
- Seed data strategy: none, demo-only, or minimal required records (admin user, default settings)
- Rollback plan: what can be reversed, and what cannot (for example, destructive column drops)
Rollbacks deserve honesty. Some changes are reversible only with a backup restore. Call that out in plain language, and pair it with a backup step (snapshot before deploy, verify restore process).
Before handoff is complete, run migrations on a copy of production data if possible. This catches slow queries, missing indexes, and “works on empty data” issues. A realistic test is exporting code, setting environment variables, restoring an anonymized dump, then applying migrations from scratch. That single exercise validates a big part of any source code handoff checklist.
If the app was built in a platform like Koder.ai and then exported, double-check that migration files and any seed scripts are included in the export and still referenced correctly by the backend startup process.
Build and CI: make it repeatable
A handoff is only complete when someone else can rebuild the app from scratch on a clean machine. Your source code handoff checklist should include the exact build commands, required versions, and the expected output (for example: “web bundle in /dist”, “API binary name”, “Flutter APK location”).
Write down the tools and package managers you actually use, not what you think you use. For a typical stack this might be Node.js (and npm or pnpm) for a React web app, the Go toolchain for the server, PostgreSQL client tools for local setup, and the Flutter SDK for mobile.
Make dependency installs predictable. Confirm lockfiles are committed (package-lock.json, pnpm-lock.yaml, go.sum, pubspec.lock) and do a fresh install on a new computer or clean container to prove it works.
Capture what CI does, step by step, so it can be copied to another CI provider if needed:
- Install dependencies (with lockfiles)
- Run tests and lint checks
- Build outputs (web bundle, server binary, mobile build)
- Produce artifacts (zip, Docker image, release bundle)
- Store logs and build metadata (version, commit, date)
Separate build-time config from runtime config. Build-time config changes what gets compiled (like an API base URL baked into a web bundle). Runtime config is injected when the app starts (like database URLs, API keys, and feature flags). Mixing these is a common reason “it works on CI” but fails after deployment.
Provide a simple local verification recipe. Even a short set of commands is enough:
# Web
pnpm install
pnpm test
pnpm build
# API
go test ./...
go build ./cmd/server
# Mobile
flutter pub get
flutter test
flutter build apk
If you’re exporting from a platform like Koder.ai, include any generated CI files or build presets that were used during deployment so the client can reproduce the same build outside the platform.
Deployment scripts and release process
A good source code handoff checklist does not stop at “here’s the repo.” It also explains how the app gets from source code to a running service, and who pushes the button.
Start by writing down how deployments happen today: fully manual (someone runs commands on a server), CI-driven (a pipeline builds and deploys), or via a hosted platform. Include where configs live, and which environments exist (dev, staging, production).
Make the release steps repeatable. If the process depends on a person remembering 12 commands, turn those into scripts and note the permissions needed.
What to include with the deployment package
Give the client enough to deploy on day one:
- Build and run commands (and exact versions of Node, Go, Flutter, etc.)
- Deployment scripts (shell scripts, Makefile targets, or pipeline configs)
- Required access: cloud account roles, container registry, DNS, database admin
- Environment setup notes: where env vars are set and how they differ per env
- Release naming: tags/releases and how to identify what’s running
Agree on downtime expectations. If “zero downtime” is required, say what that means in practice (blue-green, rolling deploy, read-only window for migrations). If downtime is acceptable, define a clear window.
Static assets and caches are common failure points. Note how assets are built and served, when to bust caches, and whether a CDN is involved.
Rollback you can actually execute
A rollback should be a short, tested recipe tied to a tag or release ID. For example: deploy the previous tag, restore the prior database snapshot if needed, and invalidate caches.
If the app was created on Koder.ai and then exported, mention the last known good snapshot and the exact export version so the client can match code to a working release quickly.
Step-by-step: verify the build after export
Verification is the moment you learn whether the handoff is real. The goal is simple: someone new can take the exported code, set it up, and get the same app running without guesswork.
Before you start, record what “correct” looks like: the running app’s version, the current commit/tag (if you have it), and one or two key screens or API responses to compare. If the export came from a platform like Koder.ai, note the snapshot or export timestamp so you can prove you tested the latest state.
- Confirm the export matches production: check the commit history, release notes, or build metadata. Compare a visible version string or a small behavior (like a specific setting or UI label) to the running app.
- Set up environment variables and secrets: create the target environment config (local and staging). Use the provided env var inventory and make sure nothing is hard-coded in the repo.
- Install dependencies and run tests: do a clean install (no cached node_modules/vendor folders). Run unit tests and any lint checks exactly as documented.
- Run migrations and start locally: spin up the database, apply migrations in order, and start the app. Confirm the app can read/write basic data and that there are no pending migrations.
- Deploy to staging, smoke test, then promote: deploy using the same scripts/pipeline you plan to use in production. Only promote once staging matches expectations.
For smoke tests, keep it short and tied to risk:
- Log in/out (or create a test user)
- One core workflow end-to-end (create-edit-save)
- One email/webhook/payment callback if applicable
- Basic error handling (bad input, missing record)
- Logs show no repeated crashes or secret-related errors
If anything fails, capture the exact command, error output, and the env vars used. That detail saves hours when ownership changes hands.
Common handoff mistakes and how to avoid them
The fastest way to turn a handoff into a fire drill is to assume “the code is enough.” A good source code handoff checklist focuses on the small, boring details that decide whether the client can actually run and change the app without you.
The mistakes that cause most handoff headaches
Most problems fall into a few repeat patterns:
- Secrets are not rotated, so old agency passwords, API keys, or cloud tokens still work after handover.
- Environment variables are incomplete because some values live only in CI settings or a hosting dashboard, not in the repo.
- One-off production changes are forgotten, like a quick hotfix, a manual DB edit, or a config toggle set directly on the server.
- Database migrations work locally but fail in production due to missing permissions, extensions, or schema ownership.
- There is no rollback plan, and there is no tagged release (or release note) to return to when the first deploy goes wrong.
How to prevent them (without adding weeks)
Make rotation and access cleanup a scheduled task, not a “when we have time” item. Set a date when agency accounts are removed, service keys are regenerated, and the client confirms they can deploy using only their own credentials.
For env vars, do a simple inventory from three places: the repo, the CI system, and the hosting UI. Then validate it by running a clean build from a fresh machine or container.
For migrations, test with the same database role the production deploy will use. If production requires elevated steps (like enabling an extension), write them down and make ownership clear.
A realistic example: after exporting a project from Koder.ai, the client deploys successfully but background jobs fail because one queue URL was only set in the hosting dashboard. A quick env var audit would have caught it. Pair that with a tagged release and a documented rollback (for example, “redeploy tag v1.8.2 and restore the last snapshot”) and the team avoids downtime.
Final checklist, a simple example, and next steps
If you only keep one page from this source code handoff checklist, keep this one. The goal is simple: a clean clone should run on a new machine, with new secrets, and a database that can move forward safely.
Quick checks (do these from a fresh clone)
Run these checks on a laptop that has never seen the project before (or in a clean container/VM). That is the fastest way to catch missing files, hidden assumptions, and old credentials.
- Build from scratch: install deps, run tests (if any), and produce a release build without manual edits.
- Config works: set the documented environment variables and confirm the app boots with a fresh config file or env setup.
- Secrets are rotated: verify the app runs with the new keys, then revoke the old keys and confirm nothing breaks.
- Migrations run clean: start with an empty database, run migrations, then start the app and hit one basic flow.
- Deployment path is real: run the deployment script or CI workflow once and confirm it produces the same output.
A simple handoff example
An agency hands off a React frontend, a Go API, and a PostgreSQL database. The client team clones the repo, copies the provided .env.example into real env vars, and creates brand new credentials for the database, email provider, and any third-party APIs. They run go test (or the agreed test command), build the React app, apply migrations to a fresh Postgres instance, and start both services. Finally, they deploy using the documented script and confirm the same commit can be rebuilt later.
Next steps
Keep the handoff short and owned. A 30 to 60 minute walkthrough usually beats a long document.
- Schedule a walkthrough and record decisions (who owns deploys, secrets, and database changes).
- Assign one owner for production access and one backup.
- Agree on a final “acceptance build” commit hash and tag it.
- If you built in Koder.ai, export the source code, then use snapshots and rollback during the first client-run deployment to reduce risk.
FAQ
What should a source code handoff include?
A complete handoff lets the client build, run, and deploy the app without relying on the agency. Include the full repository, setup instructions, access details, deployment and rollback steps, migration files, and a tagged known-good release.
Why should we set a handoff freeze window?
Use a short freeze window, often 24 to 72 hours, before the final export. Only ship urgent fixes during that time, record each change, and include it in the final release.
How do we document development, staging, and production environments?
List every environment, such as local, staging, and production, and state where each runs. Document separate databases, domains, feature settings, and deployment processes so nobody sends staging settings to production.
What should an environment variable inventory contain?
Create an inventory with each variable's name, purpose, example format, required status, default behavior, and location. Include a .env.example file, but never put real passwords, tokens, or private keys in it.
How should we rotate secrets during handoff?
Create replacement credentials under accounts the client owns, test them in staging, deploy them, then revoke the old agency credentials. Cover database access, CI tokens, OAuth secrets, email, storage, payments, webhooks, and signing keys.
What do we need to document for database migrations?
Document where migrations live, the exact command that runs them, required database extensions, seed-data rules, and who may run them. Test the process against an empty database and, where practical, a safe copy of production data.
How can we prove the exported code builds from scratch?
Use a clean computer, container, or virtual machine with no old dependencies or config files. Install dependencies from committed lockfiles, run tests, build the app, set documented variables, apply migrations, and start the services.
What should deployment documentation include?
Give the client the actual scripts or pipeline configuration, required cloud and DNS permissions, build and run commands, environment setup notes, and release tags. The process should work without someone remembering a series of manual commands.
What makes a rollback plan usable?
Tie rollback to a tested release tag or snapshot. State who runs it, how to redeploy the previous version, when to restore a database backup, and whether caches or static assets need clearing.
What is a practical final acceptance test for handoff?
Have someone who did not build the app clone the final release, configure it with client-owned credentials, run migrations, deploy to staging, and complete a small smoke test. Confirm login and at least one core workflow, then record the accepted commit or tag.