All notes >

Salesforce Project Setup with package.json, Hooks, and Sandbox Post-Copy

A tight setup for keeping a Salesforce DX project clean with package.json scripts, pre-commit and pre-push hooks, and sandbox initialization.


Setup package.json

A Salesforce DX project is meant to live in version control, and Salesforce’s CLI creates the project structure for metadata, tests, sample data, and config. I like to keep package.json at the center of that setup so the project has one place for repeatable commands. Salesforce also recommends using Node scripts in DX projects for tasks like formatting, linting, and testing.

A simple package.json is enough:

{
  ...
  "scripts": {
    ...
    "precommit": "npm run format && npm run lint",
    "prepush": "npm run test"
  }
}

The idea is straightforward: keep package.json for project-wide commands, then call those scripts from Git hooks. npm scripts are just named commands in the package descriptor, so this stays portable and easy to remember.

I keep hooks split like this:

  • pre-commit - fast checks only
  • pre-push - slower validation

Git supports both hooks. pre-commit runs before a commit is created, and pre-push runs before the push completes, so it is a good place to stop bad code before it leaves your machine.

Example Husky hooks:

# .husky/pre-commit
npm run precommit
# .husky/pre-push
npm run prepush

Sandbox Refresh

For sandboxes, refreshes matter because a refresh updates the sandbox metadata from the source org, and the sandbox org ID changes each time it is refreshed. Salesforce also notes that sandbox refreshes can take a long time, so it is best to plan around them.

If a sandbox needs setup after creation or refresh, I use SandboxPostCopy. Salesforce says a post-copy script can run the first time the sandbox is created and again on every refresh. That is the right place for cleanup, test user setup, feature flags, or other org-specific initialization.

Common SandboxPostCopy Tasks

Typical things I automate after a sandbox refresh:

  • assign permission sets
  • disable scheduled jobs
  • update named credentials
  • seed reference data
  • deactivate integrations
  • create test users
  • reset custom settings

Named Credentials after Sandbox Refresh

Another useful SandboxPostCopy task is setting up Named Credentials and External Credentials after a sandbox refresh.

Salesforce exposes APIs for populating external credential principals and secrets programmatically, which makes it possible to automate environment bootstrap instead of manually re-entering credentials after every refresh.

That is especially useful for:

  • integration users
  • API keys
  • OAuth client secrets
  • environment-specific endpoints

I usually keep the actual secret values outside the repository and inject them during sandbox setup instead of storing them in source control.

That gives me a clean flow:

  • package.json for repeatable project commands
  • Git hooks for local quality gates
  • SandboxPostCopy for sandbox initialization

It is a small amount of structure, but it removes a lot of manual work later.

References