DX Project
A DX Project is the source-controlled directory that anchors a Salesforce DX workflow.
Definition
A DX Project is the source-controlled directory that anchors a Salesforce DX workflow. It contains the metadata for one or more Salesforce orgs as files in a standardized layout: force-app/main/default for source, config for scratch-org definitions, manifest for explicit manifest XML files, and sfdx-project.json at the root for project configuration. The Salesforce CLI (sf) operates on a DX Project: deploy, retrieve, test, and package commands all assume you are inside one.
A new DX Project is scaffolded by sf project generate --name MyProject, which creates the directory structure and the project file. From there, you connect to a Salesforce org (the Dev Hub for scratch orgs and any target org for deployment), retrieve initial metadata, commit to Git, and you have a working source-driven Salesforce project. The DX Project is the source of truth that scratch orgs are spun up from, that CI pipelines deploy from, and that managed packages are versioned from.
Anatomy of a Salesforce DX Project
The sfdx-project.json file
At the root of every DX Project sits sfdx-project.json. It defines packageDirectories (where source lives, with optional default flag), namespace, sfdcLoginUrl, sourceApiVersion, and packageAliases (for 2GP). This is the file the CLI reads first to understand the project''s layout. Most projects have one packageDirectory pointing to force-app; larger orgs split metadata across multiple directories for parallel development.
The force-app source structure
Inside force-app/main/default sits the source metadata, organized by metadata type. classes for Apex, flows for Flow, objects for object metadata, layouts for page layouts, profiles for profiles, and so on. Each type gets a subdirectory; each metadata component gets one or more files (an Apex class is a .cls file plus a .cls-meta.xml file). The CLI knows how to deploy any file under force-app to a target org.
The config directory and scratch-org definitions
The config directory holds scratch-org definition files: JSON documents that describe what a scratch org should look like. Edition (Developer, Enterprise), country, features to enable (EnableEinsteinDiscovery, EnableCdn, etc.), and settings (like a default fiscal year). Multiple definition files let you spin up specialized orgs: a basic dev org, an org with Industries features, an org with Service Cloud Voice enabled.
The manifest directory and explicit deploys
Some DX Projects keep manifest XML files (package.xml, destructiveChanges.xml) in a manifest directory. These let you target specific subsets for deploy or retrieve without grabbing the entire force-app source. Mature projects use them to scope production deployments precisely, or to script destructive changes that the source itself does not contain.
Multi-package projects and unlocked packages
For organizations building reusable Salesforce features as packages, the DX Project can declare multiple package directories, each becoming a separate unlocked or managed package. The sfdx-project.json''s packageAliases section names them. The CLI''s sf package create and sf package version create commands build each package''s versioned releases independently.
Source tracking and the .sfdx directory
Inside the .sfdx directory (typically gitignored), the CLI maintains source-tracking state: which files have changed since the last deploy, which org-side changes are pending retrieve. This lets sf project deploy preview and sf project retrieve preview return precise diffs without re-comparing everything. The CLI uses this metadata to make incremental operations fast.
CI integration and the standard pipeline
DX Projects integrate with CI through the CLI. A typical pipeline: PR opened, GitHub Actions checks out the project, authenticates the CLI against the Dev Hub, creates a scratch org from a config file, deploys force-app, runs Apex tests, reports back. The pipeline definition lives in the project (.github/workflows/ci.yml). This is the DaaS workflow in action: every PR gets a fresh, isolated org to test against.
How to create and structure a new Salesforce DX Project
A DX Project starts with sf project generate. From there, customize the structure for your team, connect to a Dev Hub, and commit to Git. The first 30 minutes set the foundation for years of source-driven development.
- Generate the project
From your work directory, run sf project generate --name MyProject. The CLI creates a MyProject directory with the standard layout: force-app/main/default, config, manifest, sfdx-project.json.
- Initialize a Git repository
cd MyProject, then git init. Salesforce DX projects belong in version control from day one. Treat .sfdx as gitignored (the project generator includes a .gitignore by default).
- Authenticate the CLI against a Dev Hub
Run sf org login web --alias DevHub --set-default-dev-hub. The CLI authorizes against your Dev Hub for scratch-org creation.
- Retrieve initial metadata from an org
To start from existing org content, run sf project retrieve start --source-org existing-org-alias. The retrieve writes metadata into force-app/main/default. Commit and move on.
- Customize the project for your team
Edit sfdx-project.json: set the sourceApiVersion, add packageDirectories if you have multiple sub-packages, set namespace if building a managed package. Update config/project-scratch-def.json with the org shape your team needs.
- Commit and push to a remote
git add then git commit -m Initial DX project. Push to GitHub, GitLab, or whichever remote you use. The project is now ready for collaborative development.
One packageDirectory at force-app, basic config and manifest. The starting point for most projects.
Multiple packageDirectories for separate 2GP or unlocked packages. Used when shipping reusable features.
Multiple scratch-org definition files for different feature sets (basic dev, Industries-enabled, Service Cloud Voice-enabled).
Add .github/workflows/ci.yml (or equivalent) to wire the CLI into pull-request automation.
- The sourceApiVersion in sfdx-project.json controls what API version metadata is retrieved against. Drift between this and your org''s release version creates deployment surprises; keep it current.
- Scratch-org definition files are not free-form. The fields are documented in the Scratch Org Definition Reference; typos or invalid feature names fail org creation with cryptic errors.
- Multi-package projects require disciplined dependency management. A package that depends on another must declare the dependency in sfdx-project.json''s packageDirectories; otherwise installs fail.
- Source tracking only works for orgs that support it (scratch orgs and Dev Hub-tracked sandboxes). Older sandboxes need explicit deploy/retrieve operations.
Trust & references
Straight from the source - Salesforce's reference material on DX Project.
- Salesforce DX Project StructureSalesforce Developers
- sfdx-project.json ConfigurationSalesforce Developers
Hands-on resources to go deeper on DX Project.
About the Author
Dipojjal Chakrabarti is a B2C Solution Architect with 29 Salesforce certifications and over 13 years in the Salesforce ecosystem. He runs salesforcedictionary.com to help admins, developers, architects, and cert/interview candidates sharpen their fundamentals. More about Dipojjal.
Test your knowledge
Q1. What is a DX Project?
Q2. What file defines a DX Project's structure?
Q3. Why use DX Projects?
Discussion
Loading discussion…