Skip to content
Salesforce Dictionary - Free Salesforce GlossarySalesforce Dictionary
DictionaryLLocal Project
PlatformBeginner

Local Project

A Local Project in Salesforce DX is the folder on a developer's machine that holds an org's metadata in source format.

§ 01

Definition

A Local Project in Salesforce DX is the folder on a developer's machine that holds an org's metadata in source format. It is the workspace created with the Salesforce CLI command sf project generate, opened in an editor like VS Code, and tracked in git. At its root sits the sfdx-project.json configuration file, which tells the CLI that the directory is a Salesforce DX project. Below it are package directories (force-app by default) that group every metadata type the developer touches: Apex classes, Lightning Web Components, objects, flows, permission sets, and more.

The Local Project is where modern Salesforce development happens. Source moves between the project and an org through the CLI: you deploy with sf project deploy and retrieve with sf project retrieve. Because the source format splits metadata into many small files, the project produces clean diffs that version control systems handle well. That makes branches, pull requests, and code review practical in a way the older Metadata API format never allowed.

§ 02

How a Local Project is put together

sfdx-project.json, the file that defines the project

Every Local Project is anchored by sfdx-project.json at the root. The Salesforce CLI reads this file on each command, and its presence is what marks the folder as a Salesforce DX project rather than an ordinary directory. The file is JSON, so it lives comfortably in git and is easy to diff. Inside, the packageDirectories array lists the folders that hold your source, with one entry flagged as the default. The sourceApiVersion property pins the metadata API version the project compiles against, which keeps a team on the same release behavior. The namespace property is set when the project builds a namespaced package, and sfdcLoginUrl can point the CLI at a non-standard login host such as a My Domain or a sandbox endpoint. Plug-ins and second-generation packaging read extra keys from the same file, including package aliases and version numbers. Because all of this configuration sits in one tracked file, a teammate who clones the repository inherits the exact project shape. You rarely edit sfdx-project.json by hand for everyday work, but understanding its keys helps when you add package directories or set up packaging.

The source-format folder structure

Under the default package directory, source is laid out as force-app/main/default, and each metadata type gets its own subfolder. Apex sits in classes, Lightning Web Components in lwc, Aura components in aura, custom objects in objects, flows in flows, and permission sets in permissionsets. The list grows as you add features, but the pattern stays the same: one folder per type, predictable file names per component. Salesforce calls this the source format, and it is deliberately different from the older metadata format. Source format splits a single metadata item into multiple files where that helps. A custom object, for instance, breaks into separate files for the object itself, each field, each list view, and each validation rule. The metadata format kept all of that in one large XML file per object, which made code review impractical because every change touched the same file. By splitting the pieces, source format gives version control a fighting chance: a one-field change shows up as a one-file diff. This layout is also what editors and the CLI expect, so retrieving and deploying just work.

Source format versus metadata format

Two formats exist in the Salesforce world, and the Local Project uses the newer one. Source format is, in Salesforce's own words, optimized for working with version control systems. Metadata format is the legacy shape that tools like the Force.com IDE produced, and you cannot open it directly in VS Code without converting it first. The practical difference shows up at review time and at merge time. Source format produces small, readable diffs and merges that humans can reason about. Metadata format produces giant XML blobs that hide real changes inside noise. When you inherit an old project in metadata format, you convert it with sf project convert source. The conversion is mostly mechanical, but it does not preserve git history cleanly if you convert everything at once. A bulk convert loses revision history because git cannot track that many simultaneous changes, so large migrations are usually done in chunks by metadata type. New projects should always start in source format, which sf project generate does for you by default. The two formats also map to different deploy paths, though the CLI hides most of that.

Local Project and the org are two different things

It helps to keep a clear line between the Local Project and an org. The Local Project is a file system on your machine, the source of truth you commit to git. An org, whether a scratch org, a sandbox, or production, is a running environment where that source executes. You move source between the two with the CLI. sf project deploy start pushes selected metadata into an org, and sf project retrieve start pulls metadata out and into your project. When you work against a scratch org, source tracking watches both sides and tells you what changed, so you can pull org-made edits back into the project and commit them. That two-way flow is the heart of source-driven development. A common mistake is treating the org as the source of truth and the project as a copy. The reverse is correct: the project is canonical, and any org can be rebuilt from it. Once you internalize that the project is what you protect with branches and reviews, the rest of the workflow follows naturally.

Why git and the Local Project fit together

The Local Project was designed with version control in mind, so the two work well together. Each metadata file is small and text-based, which means a feature branch shows only the files a feature actually touches. Developers cut a branch, build in a scratch org or sandbox, retrieve their changes into the project, commit, and open a pull request. Reviewers read file-level diffs that map to real intent: a new Apex class, an added field, an edited flow. Merges behave like merges in any codebase, with conflicts that a human can resolve line by line. A .forceignore file at the project root lets you exclude metadata you do not want tracked or deployed, similar to how .gitignore works for git. This keeps noisy or environment-specific files out of the repository. None of this is bolted on after the fact. It falls out of the source format itself, which is why teams that adopt Salesforce DX usually adopt git at the same time. Managing org metadata without version control, by contrast, tends to end in lost work and changes nobody can trace.

From Local Project to production with DevOps Center and CI/CD

A Local Project is the unit that release tooling consumes. DevOps Center is Salesforce's declarative release product, and it reads a Local Project from a git repository. Admins and developers pick work items, and DevOps Center assembles the right metadata and promotes it through a pipeline of environments, for example Dev to UAT to Production. Because the source already lives in git in source format, DevOps Center has clean inputs to work with. Third-party tools such as Copado, AutoRabit, and Gearset consume the same project and offer deeper configuration for teams that need it. Custom CI pipelines do the same thing with scripts: a pull request triggers a job that authenticates to an org with sf org login, runs Apex tests, and deploys with sf project deploy. The common thread is that everything starts from the Local Project in git. That single source feeds local development, automated testing, and every promotion up to production, which is exactly why the project format matters so much.

Multiple package directories in one project

A Local Project is not limited to a single force-app folder. The packageDirectories array in sfdx-project.json can list several directories, which lets a team split metadata into logical groupings inside one project. You might keep core shared code in one directory and a feature module in another, or carve out boundaries that line up with second-generation packages. Each directory is its own slice of source, and one of them carries the default flag that decides where new components land when you generate them. This structure pays off on larger teams. It lets different groups own different folders, keeps unrelated changes from colliding, and maps neatly onto modular packaging. Deploy and retrieve commands can target a specific directory, so you push only the slice you mean to. The trade-off is added planning: you decide the boundaries up front and keep them sensible as the project grows. Most projects begin with a single force-app directory and add more only when the codebase or the team gets big enough to need the separation. The CLI handles either case without special flags.

§ 03

Create a Local Project with the Salesforce CLI

You create a Local Project with the Salesforce CLI, then connect it to an org. These steps produce a source-format project ready for git and deployment.

  1. Generate the project

    Run sf project generate --name MyProject in the folder where you keep your code. The CLI scaffolds a source-format project with sfdx-project.json, a force-app package directory, a config folder, a manifest folder, and a .forceignore file. In VS Code you can run SFDX: Create Project from the Command Palette for the same result.

  2. Open it and authorize an org

    Open the new folder in VS Code, then authenticate with sf org login web. Pick the org as your default so commands target it. For scratch-org work, create the org from config/project-scratch-def.json with sf org create scratch.

  3. Bring in metadata or build new

    Pull an existing org's metadata with sf project retrieve start, or generate new components such as Apex classes and Lightning Web Components into the package directory. Source tracking on a scratch org tells you what changed on each side.

  4. Commit and deploy

    Initialize git, commit the project, and open pull requests for review. Deploy to an org with sf project deploy start, and let DevOps Center or a CI pipeline handle promotion to production.

--namerequired

The project name, which becomes the folder name and the name value inside sfdx-project.json. Required by sf project generate.

--templaterequired

The project template to scaffold. The standard template produces the force-app source-format layout used for most work; defaults to standard if omitted.

--output-dirrequired

The directory where the project folder is created. Defaults to the current working directory when not supplied.

--default-package-dirrequired

The name of the default package directory, force-app unless you change it. New components land here and it is flagged default in sfdx-project.json.

Gotchas
  • The project, not the org, is the source of truth. Treat any org as rebuildable from the committed project, and pull org-made changes back before you forget them.
  • Do not bulk-convert a large metadata-format project to source format in one shot if you care about git history; convert by metadata type in chunks instead.
  • Keep sfdx-project.json and .forceignore in version control. They define the project shape and what gets deployed, so a teammate who clones the repo needs both.

Prefer this walkthrough as its own page? How to Local Project in Salesforce, step by step

§

Trust & references

Sources

Cross-checked against the following references.

Official documentation

Straight from the source - Salesforce's reference material on Local Project.

Was this entry helpful?
Help us write better definitions. Quick reactions or detailed edit suggestions.

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. Which file sits at the root of a Salesforce DX Local Project and tells the CLI how the project is structured?

Q2. What relationship does a Local Project have with a scratch org during development?

Q3. How do you convert a legacy Metadata API-format project into the SFDX source format used by a Local Project?

§

Discussion

Loading…

Loading discussion…