Salesforce Development Fundamentals: Part 1 - The Developer Mindset & Toolkit
Updated 24/04/2026
You’ve built a strong foundation. You understand the Salesforce data model, security, automation with Flow, approval processes, custom metadata, and sandbox governance. You can configure an org to support real business processes, and you know how to move those changes safely through environments. It has been a deliberate move to guide you through the fundamentals and administration first, giving you a broad and deep understanding of the platform before you ever write a line of code. The best Salesforce developers are those who know when not to write code, relying on their administrative knowledge to avoid building costly, hard-to-maintain custom solutions for problems that declarative tools can solve out of the box.
Now comes the question every capable admin eventually asks: what happens when clicks aren’t enough?
This article is the bridge. It won’t turn you into a developer overnight, but it will shift your mental model from “configuration only” to “configuration AND code,” give you a working local development environment, and walk you through the professional workflow that Salesforce developers use every day. By the end, you’ll understand when to reach for code, how your tools fit together, and what the development lifecycle actually looks like from the inside.
🧭 Reframing “Development” on Salesforce
Section titled “🧭 Reframing “Development” on Salesforce”🧠 The Admin-Developer Evolution
Section titled “🧠 The Admin-Developer Evolution”For many, the word “developer” conjures images of complex code, command-line interfaces, and a world far removed from the familiar point-and-click interface of Salesforce. But on the Salesforce platform, the journey from administrator to developer is more of an evolution than a binary jump. It’s about shifting your mental model from “clicks only” to “clicks AND code.”
Salesforce development isn’t about abandoning everything you know; it’s about extending it. The same data model, the same security settings, the same business processes you’ve configured as an admin are the foundation upon which developers build. We use new tools and languages to express logic and create user experiences that are simply not possible with declarative tools alone. Many of the most effective Salesforce developers started their careers as administrators, bringing invaluable business context and platform understanding to their coding endeavors.
⚖️ When to Use Code vs Clicks
Section titled “⚖️ When to Use Code vs Clicks”The most important skill in Salesforce development isn’t writing code: it’s knowing when to write it. Salesforce invests heavily in declarative tools, and for good reason. Flow, validation rules, formula fields, and approval processes handle a huge range of business requirements without code. Code should be the exception, not the default.
Use declarative tools (Flow, validation rules, formula fields) when:
- The logic is straightforward and well supported by the tool (field updates, record creation, simple branching, scheduled actions)
- Non-developers need to understand and maintain the automation
- The requirement maps cleanly to a standard Flow pattern (screen flows, record-triggered flows, scheduled flows)
- You need rapid iteration and the logic may change frequently
Reach for Apex when:
- The logic involves complex cross-object operations that would result in a deeply nested or fragile Flow (e.g., recalculating rollup values across multiple relationship levels based on conditional criteria)
- You need to call external APIs or web services (HTTP callouts, REST/SOAP integrations)
- Performance is critical and you need fine-grained control over query patterns and data processing
- You’re processing large data volumes in batch (thousands or millions of records)
- The business logic requires transaction control that Flow doesn’t support (partial commits, savepoints, custom error handling)
- You need a custom user interface that goes beyond what standard Lightning pages and screen flows can deliver
Reach for Lightning Web Components (LWC) when:
- You need a custom UI component that doesn’t exist in the standard Lightning component library
- The user experience requires real-time interactivity, dynamic rendering, or client-side logic
- You require highly reusable components with layers that will appear on multiple pages or apps
🔀 How Code and Clicks Work Together
Section titled “🔀 How Code and Clicks Work Together”In practice, most Salesforce solutions use a mix of declarative and programmatic tools. Understanding how they interact is just as important as knowing how to use each one individually.
Common patterns include:
- Flow calls Apex: A Flow handles the user-facing orchestration (screen inputs, branching logic, record creation) but invokes an Apex action for a specific step that needs code, like a complex calculation, an API callout, or a bulk data operation. This is done via Invocable Apex methods.
- Apex fires, Flow reacts: An Apex trigger modifies data, and a record-triggered Flow picks up the change and handles downstream automation. Both execute within the same transaction.
- LWC calls Apex: A Lightning Web Component provides the user interface, and Apex methods (exposed via
@AuraEnabled) serve as the backend, handling data queries, business logic, and DML operations. - Apex enriches configuration: Custom metadata and custom settings (which you covered in Administration Part 4) store configuration that Apex reads at runtime. The admin controls the values; the code controls the behaviour.
This hybrid approach lets each tool do what it’s best at. Declarative tools handle orchestration and simple logic; code handles complexity, integrations, and performance-sensitive operations.
🧰 Your Development Toolkit
Section titled “🧰 Your Development Toolkit”Every craft requires its tools. As an admin, your primary tool has been the browser: Setup pages, Flow Builder, the Lightning App Builder. As a developer, you’ll add a local development environment to your workflow. The browser doesn’t go away, but most of your coding work happens locally, with changes deployed to Salesforce when they’re ready.
🔧 The Core Tools
Section titled “🔧 The Core Tools”Three tools form the foundation of every Salesforce developer’s setup:
Salesforce CLI (sf)
Section titled “Salesforce CLI (sf)”The Salesforce CLI is your command centre. It’s a command-line tool that lets you interact with Salesforce orgs from your local machine. You’ll use it to:
- Authenticate to sandboxes, scratch orgs, and production orgs
- Retrieve metadata (your configurations, Apex classes, and components) from an org to your local machine
- Deploy code and metadata from your local machine back to an org
- Run Apex tests
- Create scratch orgs for isolated development
- Execute anonymous Apex for quick scripts and debugging
- Execute SOQL queries and manipulate records directly from your terminal
The CLI replaces the browser for many tasks that admins traditionally do in Setup. Instead of clicking through menus to deploy a change, you run a command. This might feel unfamiliar at first, but it becomes faster and more repeatable than the UI for most development tasks.
Visual Studio Code (VS Code)
Section titled “Visual Studio Code (VS Code)”VS Code is your code editor and the central hub of your Salesforce development workflow. It matters because it gives you a consistent, extensible environment for writing, testing, and version‑controlling all your Salesforce code. Instead of bouncing between the Developer Console, browser tabs, and external tools, you keep everything in one place—making it easier to navigate, debug, and collaborate on real projects.
While Salesforce has a built-in Developer Console (accessible from Setup), professional development happens in VS Code. It provides:
- Syntax highlighting and intelligent autocomplete for Apex, SOQL, HTML, JavaScript, and CSS
- An integrated terminal for running CLI commands without leaving the editor
- A file explorer for navigating your project structure
- Debugging tools for stepping through Apex code
- Git integration for version control
- Extensions for almost anything else you might need
Think of VS Code as the equivalent of Flow Builder, but for code. It’s where you spend most of your working day.
To help get up to speed with Visual Studio Code, check out the Quick Start: Visual Studio Code for Salesforce Development Trailhead project. This guided module walks you through installing VS Code, setting up the Salesforce Extension Pack, connecting to your Salesforce org, and running your first commands. It’s the perfect hands-on introduction to the editor and tools you’ll use daily as a Salesforce developer.
Salesforce Extension Pack for VS Code
Section titled “Salesforce Extension Pack for VS Code”The Salesforce Extension Pack is what turns VS Code from a generic text editor into a full fledged Salesforce development environment. It matters because it gives you deep, first‑class support for Salesforce languages and tools right inside your editor, so you don’t have to juggle between the UI and your IDE. With this pack installed, almost every core Salesforce development task, from writing Apex to querying data can happen in a single, familiar workspace.
This extension pack is what makes VS Code understand Salesforce. Without it, VS Code is just a generic text editor. With it, you get:
- Apex language support (autocomplete, error checking, go-to-definition)
- SOQL language support and an inline query editor
- Lightning Web Component support (HTML templates, JavaScript controllers)
- Commands to retrieve and deploy metadata directly from the editor
- Org Browser to explore your connected org’s metadata without leaving VS Code
- Apex Replay Debugger for stepping through debug logs
Beyond the Extension Pack
Section titled “Beyond the Extension Pack”A few more tools you’ll see across professional Salesforce teams. None are required, but knowing they exist will save you time.
- Salesforce Inspector / Inspector Reloaded: Browser extensions that surface org limits, run inline SOQL, edit records in bulk, and inspect metadata directly from any Salesforce page. Already familiar to many admins; just as useful for developers.
- Apex Replay Debugger: Bundled with the Extension Pack. Capture a debug log when your code runs, then “replay” it locally with breakpoints, variable inspection, and step-through navigation — without re-running the transaction.
- Apex PMD / SFDX Scanner: Static-analysis tools that flag bug patterns, security issues (SOQL injection, missing CRUD/FLS checks), and style problems before you commit. Most teams wire them into pre-commit hooks or CI.
- Prettier (with
prettier-plugin-apex): Consistent code formatting across Apex, JavaScript, and HTML so your diffs only show real changes, not whitespace noise. - Code Builder: Salesforce’s browser-hosted, fully-configured VS Code environment. Useful when you can’t install software locally (locked-down corporate machines) or need a quick, ephemeral workspace tied to an org.
AI-assisted development
Section titled “AI-assisted development”Salesforce now ships several AI tools targeted at developers:
- Agentforce Vibes brings agent-driven workflows into VS Code, so you can describe a change and have it scaffold the metadata, classes, and tests.
- Einstein for Developers offers in-IDE Apex code generation and explanation grounded in your project context.
- Most general-purpose AI coding assistants also work well against Salesforce projects once the Extension Pack is installed.
These are accelerators, not substitutes for understanding the platform — the chapters that follow are still the foundation you’ll lean on when reviewing what an AI assistant produces. For a deeper look at how AI is changing the developer role, see the companion article: AI & the Salesforce Developer.
🚀 Setting Up Your Environment
Section titled “🚀 Setting Up Your Environment”Setting up a Salesforce development environment is a one‑time process, but it’s the foundation for everything you’ll build. Once configured, the same toolchain persists across projects and orgs, letting you move quickly from “Hello World” to real features.
-
Install the Salesforce CLI
- Download and install from developer.salesforce.com/tools/salesforcecli
- The installer handles everything. Once complete, open a terminal and verify:
Terminal window sf --version- You should see a version number (e.g.,
@salesforce/cli/2.x.x). If you see “command not found,” the installation didn’t complete. Revisit the installer
-
Install Visual Studio Code
- Download from code.visualstudio.com
- Install like any other application. VS Code is free and runs on macOS, Windows, and Linux
-
Install the Salesforce Extension Pack
- Open VS Code
- Open the Extensions panel (click the Extensions icon in the left sidebar, or press
Cmd+Shift+Xon Mac /Ctrl+Shift+Xon Windows) - Search for “Salesforce Extension Pack” and click Install
- This installs several extensions at once: Apex, Apex Replay Debugger, Aura Components, Lightning Web Components, SOQL, and the Salesforce CLI Integration
-
Authenticate to Your Org
- Open the VS Code Command Palette (
Cmd+Shift+Pon Mac /Ctrl+Shift+Pon Windows) - Type “SFDX: Authorize an Org” and select it
- Choose the login URL (use
https://login.salesforce.comfor production/developer orgs, orhttps://test.salesforce.comfor sandboxes) - A browser window opens. Log in to your Salesforce org. Once authenticated, VS Code is connected
- Alternatively, from the terminal:
Terminal window sf org login web --alias my-sandbox --instance-url https://test.salesforce.com - Open the VS Code Command Palette (
-
Create a Salesforce Project
- Open the Command Palette and type “SFDX: Create Project”
- Choose Standard project type
- Give it a name (e.g.,
my-salesforce-project) - VS Code creates a project structure with the necessary configuration files
- Alternatively, from the terminal:
Terminal window sf project generate --name my-salesforce-project -
Initialize Source Control (or Clone Existing Repo)
- If this is a new project, initialize Git in the project directory so changes are tracked from day one:
Terminal window cd my-salesforce-projectgit initgit add .git commit -m "Initial Salesforce DX project setup"- If your team already has a repository, clone it instead of running
git init:
Terminal window git clone <your-repo-url>cd <repo-name>- If you initialized a new repo and want to publish it:
Terminal window git branch -M maingit remote add origin <your-repo-url>git push -u origin main -
Retrieve Metadata and Validate Your Workflow
- Pull a small set of metadata from your org to confirm your local setup is working end to end
- Example:
Terminal window sf project retrieve start --metadata "ApexClass:MyFirstClass"- Then deploy a safe test change (or deploy back the retrieved metadata) to verify your auth, project config, and CLI workflow
- This gives you confidence that your environment is ready before you start real feature work
After these steps, you have a local project connected to a Salesforce org. You can retrieve metadata, write code, and deploy changes, all from VS Code.
For a step-by-step walkthrough, you can also complete the Salesforce CLI Setup Guide Trailhead module, which covers setting up your environment and building your first project. Or use the Quick Start: Salesforce DX trailhead project.
📁 Understanding the Project Structure
Section titled “📁 Understanding the Project Structure”When you create a Salesforce project, the CLI generates a specific directory structure. Understanding this structure is important because it maps directly to the metadata you’ve been working with as an admin in Setup.
my-salesforce-project/├── force-app/│ └── main/│ └── default/│ ├── classes/ ← Apex classes (.cls + .cls-meta.xml)│ ├── triggers/ ← Apex triggers (.trigger + .trigger-meta.xml)│ ├── lwc/ ← Lightning Web Components│ ├── objects/ ← Custom objects and fields│ ├── flows/ ← Flow definitions│ ├── layouts/ ← Page layouts│ ├── permissionsets/ ← Permission sets│ └── ... ← Other metadata types├── sfdx-project.json ← Project configuration├── .forceignore ← Files to exclude from deployment└── package.json ← Node.js dependencies (if using LWC)The key file is sfdx-project.json. It tells the CLI where your source code lives and which API version to use:
{ "packageDirectories": [ { "path": "force-app", "default": true } ], "namespace": "", "sfdcLoginUrl": "https://login.salesforce.com", "sourceApiVersion": "62.0"}In a typical unmanaged project, namespace is left blank. The force-app directory is the default location for your source, and sourceApiVersion controls which Salesforce metadata API version the project uses.
The sourceApiVersion field deserves a special mention: it pins your project to a specific Salesforce API release. We cover what that means, plus the broader topic of metadata formats and the package.xml manifest, in Understanding Salesforce Metadata below.
Every piece of metadata in your org has a corresponding file in this structure. The Apex class you see in Setup → Apex Classes is a .cls file in the classes directory. The Flow you built in Flow Builder is an XML file in flows. This is the core insight: everything in Salesforce is metadata, and metadata is just files. When you work locally, you’re editing those files directly instead of clicking through Setup.
🔁 Retrieving and Deploying Metadata
Section titled “🔁 Retrieving and Deploying Metadata”As an admin, you’re used to making changes directly in the org. As a developer, the workflow shifts: you pull metadata to your local machine, make changes locally, then push them back. This retrieve‑edit‑deploy cycle is the heartbeat of Salesforce development.
📥 Retrieving Metadata
Section titled “📥 Retrieving Metadata”To pull metadata from your org to your local project, you have several options:
Using the Command Line:
# Retrieve a specific Apex classsf project retrieve start --metadata ApexClass:MyClassName
# Retrieve a specific object and all its fieldssf project retrieve start --metadata CustomObject:Expense_Claim__c
# Retrieve using a manifest (package.xml) filesf project retrieve start --manifest manifest/package.xml
# Retrieve everything in your project's package directoriessf project retrieve startUsing the VS Code UI:
- Right-Click Retrieve: If the metadata file already exists in your local project, you can right-click the file (or its parent folder) in the VS Code Explorer and select SFDX: Retrieve Source from Org. This is often the fastest way to pull down changes made directly in Setup.
- Org Browser: You can use the Org Browser (the cloud icon in the VS Code sidebar) to visually explore all metadata in your connected org and retrieve specific components with a single click.
📤 Deploying Metadata
Section titled “📤 Deploying Metadata”To push local changes back to your org, you have similar options:
Using the Command Line:
# Deploy everything in your projectsf project deploy start
# Deploy a specific filesf project deploy start --source-dir force-app/main/default/classes/MyClassName.cls
# Deploy using a manifest (package.xml) filesf project deploy start --manifest manifest/package.xml
# Deploy and run all tests (required for production deployments)sf project deploy start --test-level RunAllTestsInOrgUsing the VS Code UI:
- Right-Click Deploy: Just like retrieving, you can right-click a file (or its parent folder) in the VS Code Explorer and select SFDX: Deploy Source to Org. This is the standard, everyday way to push an individual file you’ve just edited (like a new Apex class) directly up to your sandbox or scratch org.
🔄 Source Tracking
Section titled “🔄 Source Tracking”When working with scratch orgs or sandboxes that have source tracking enabled, the CLI automatically tracks what’s changed on both sides (your local files and the org). This makes it easy to stay in sync:
# See what's changed locally and in the orgsf project deploy previewsf project retrieve preview
# Push local changes to the orgsf project deploy start
# Pull org changes to your local projectsf project retrieve startSource tracking is particularly useful when you make some changes locally (Apex code) and some changes in the org (a new field via Setup), and need to keep both sides synchronised.
🏗️ Scratch Orgs vs Sandboxes for Development
Section titled “🏗️ Scratch Orgs vs Sandboxes for Development”Developers often use sandboxes alongside scratch orgs, but scratch orgs add a second, more source-driven option.
When to Use Each
Section titled “When to Use Each”| Feature | Scratch Orgs | Developer Sandboxes |
|---|---|---|
| Created from | A Dev Hub-enabled org | Production org |
| Lifespan | Temporary; 1–30 days, with a 7-day default | Persistent until refreshed or deleted |
| Data | No copied production data by default; seed your own test data | Copies configuration from production; some sandbox types can include data |
| Source tracking | Built-in | Available in some workflows when enabled |
| Cost | Does not consume sandbox entitlements | Uses available sandbox entitlement |
| Configuration | Defined in a scratch org definition file | Based on the selected sandbox type or clone |
| Best for | Feature development, CI/CD, isolated testing | UAT, integration testing, training, longer-lived work |
Scratch orgs are disposable, purpose-built environments. You define the features and settings you need in a JSON file, create the org quickly, deploy your source, test, and delete it when you are done. They work especially well for feature branches and CI/CD pipelines because they start in a known, repeatable state.
Sandboxes are still the better choice when you need a longer-lived environment, production-like data, or a place for user acceptance testing and integration testing.
🏗️ Creating a Scratch Org
Section titled “🏗️ Creating a Scratch Org”To use scratch orgs, you need a Dev Hub org with the Dev Hub feature enabled. In many setups, this is a production org or a dedicated Partner Business Org.
-
Enable Dev Hub
- In your production org: Setup → Development → Dev Hub → Enable
-
Authenticate to the Dev Hub
Terminal window sf org login web --alias my-devhub --set-default-dev-hub -
Create a Scratch Org Definition Create a file called
config/project-scratch-def.jsonin your project:{"orgName": "My Feature Org","edition": "Developer","features": ["EnableSetPasswordInApi"],"settings": {"lightningExperienceSettings": {"enableS1DesktopEnabled": true},"mobileSettings": {"enableS1EncryptedStoragePref2": false}}} -
Create the Scratch Org
Terminal window sf org create scratch --definition-file config/project-scratch-def.json --alias my-feature-org --duration-days 7 --set-default -
Push Your Code
Terminal window sf project deploy start -
Open the Org
Terminal window sf org open
The scratch org is now running with your code deployed. When you’re done, delete it:
sf org delete scratch --target-org my-feature-org --no-prompt🛠️ The Development Workflow: End to End
Section titled “🛠️ The Development Workflow: End to End”Let’s put it all together. Here’s how a typical development task flows from a business requirement to a deployed solution. This isn’t theoretical; it’s the workflow you’ll follow for every piece of code you write.
📋 A Realistic Scenario
Section titled “📋 A Realistic Scenario”Imagine this requirement:
“When an Expense Claim is submitted for approval, if the amount exceeds $10,000, automatically create a Compliance Review task assigned to the Finance Compliance team.”
As an admin, you’d evaluate whether Flow can handle this. In this case, Flow probably can: a record-triggered flow on Expense_Claim__c that checks the amount and creates a Task. But imagine the requirement grows: the threshold varies by department, the compliance team assignment depends on the expense category and the submitter’s region, and the task description needs to include data from three related objects. At some point, the Flow becomes unwieldy. That’s when you’d reach for Apex.
Here’s how the development workflow would look:
🔄 The Workflow
Section titled “🔄 The Workflow”-
Create or Switch to a Feature Branch
Start by creating a Git branch for your work. This isolates your changes from the main codebase:
Terminal window git checkout -b feature/compliance-review-task -
Set Up Your Development Environment
Either create a fresh scratch org or connect to your developer sandbox:
Terminal window # Option A: Create a scratch orgsf org create scratch --definition-file config/project-scratch-def.json --alias compliance-feature --duration-days 7 --set-defaultsf project deploy start --target-org compliance-feature# Option B: Use an existing sandboxsf org login web --alias my-dev-sandbox --instance-url https://test.salesforce.com -
Write the Code
Create your Apex class and trigger in VS Code. We’ll cover the actual Apex syntax in Part 2, but the files would live under
force-app/main/default:force-app/main/default/classes/ComplianceReviewService.clsforce-app/main/default/classes/ComplianceReviewService.cls-meta.xmlforce-app/main/default/triggers/ExpenseClaimTrigger.triggerforce-app/main/default/triggers/ExpenseClaimTrigger.trigger-meta.xmlforce-app/main/default/classes/ComplianceReviewServiceTest.clsforce-app/main/default/classes/ComplianceReviewServiceTest.cls-meta.xml
-
Deploy and Test Locally
Deploy your changes to the development org and run tests (explicitly set
--target-orgso you do not accidentally deploy to the wrong org):Terminal window sf project deploy start --target-org compliance-featuresf apex run test --target-org compliance-feature --test-level RunSpecifiedTests --tests ComplianceReviewServiceTest --result-format human -
Commit and Push
Once your code works and tests pass, commit to your feature branch:
Terminal window git add .git commit -m "feat: auto-create compliance review task for high-value expenses"git push origin feature/compliance-review-task -
Open a Pull Request
Create a pull request to merge your feature branch into
integration. The CI pipeline validates the deployment and runs tests automatically. Your team reviews the code. -
Merge and Promote
After approval, the code follows the release pipeline: integration → release branch → UAT → production (exactly as covered in Administration Part 4’s CI/CD section).
This workflow might seem like a lot of steps compared to building a Flow directly in the org. That’s intentional. Each step adds a layer of safety: version control means you can roll back, CI validation catches errors before they reach production, and code review catches logic issues before they affect users. For simple changes, Flow remains the faster and safer choice. For complex logic, this structured workflow pays for itself many times over.
🖥️ The Developer Console
Section titled “🖥️ The Developer Console”Before we leave the tooling section, let’s cover the Developer Console. It is best described as a browser-based utility for debugging and ad hoc execution directly in your org. While VS Code is your primary workspace, the Developer Console remains useful for specific tasks.
🖥️ Accessing the Developer Console
Section titled “🖥️ Accessing the Developer Console”From any Salesforce org: click the gear icon (⚙️) in the top-right corner → Developer Console. It opens in a new browser window.
🎯 What It’s Good For
Section titled “🎯 What It’s Good For”Running Anonymous Apex: The “Execute Anonymous” window (Debug → Open Execute Anonymous Window or Ctrl+E) lets you run Apex code without creating a class or trigger. This is invaluable for:
- Quick data queries during debugging
- One-off data fixes (carefully)
- Testing small code snippets before integrating them into a class
// Quick anonymous Apex to check dataList<Expense_Claim__c> highValueClaims = [ SELECT Id, Name, Amount__c, Department__c FROM Expense_Claim__c WHERE Amount__c > 10000 AND Status__c = 'Submitted'];System.debug('Found ' + highValueClaims.size() + ' high-value claims');for (Expense_Claim__c claim : highValueClaims) { System.debug(claim.Name + ': $' + claim.Amount__c + ' (' + claim.Department__c + ')');}Viewing Debug Logs: The Logs tab shows real-time debug output. You can filter by log level, search for specific debug statements, and inspect the execution flow of your code.
Checking Test Coverage: Navigate to Test → New Run to execute test classes and view line-by-line coverage results overlaid on your code.
⚠️ What It’s Not Good For
Section titled “⚠️ What It’s Not Good For”The Developer Console is not a replacement for VS Code for day-to-day development:
- No Git integration (no version control)
- Limited autocomplete and error checking
- No project-level file management
- Changes are made directly in the org (bypassing your local source of truth)
- Can be unstable with large files or long sessions
Think of the Developer Console as a debugging tool and scratchpad, not your primary development environment.
To build your skills and explore the features discussed above in more detail, check out the Developer Console Basics Trailhead module. This guide walks you through accessing the Developer Console, executing anonymous Apex, working with debug logs, running tests, and understanding its strengths and limitations.
📦 Understanding Salesforce Metadata
Section titled “📦 Understanding Salesforce Metadata”As a developer, “metadata” will be the most common term you encounter. Understanding the distinction between metadata and data is foundational to mastering the platform.
📦 Metadata vs. Data
Section titled “📦 Metadata vs. Data”This is the business information users create and manage every day, such as Account records, Contact details, Opportunity pipeline values, or Case history. Data lives in records in the database and changes constantly as users interact with the system through sales, service, and operations work.
Metadata
Section titled “Metadata”This is the configuration that defines how Salesforce behaves, including structure, automation, security behavior, and user experience. This includes object definitions, field types, page layouts, validation rules, Apex classes, Flow logic, permission models, and Lightning Web Components. In short, metadata is what tells Salesforce how to store, display, secure, and process data.
A useful mental model is:
- Metadata = the blueprint (how the org is designed to work)
- Data = the runtime content (the records moving through that design)
When you create a custom field in Setup, you are defining metadata. When a user populates that field on a record, they are creating data. When you write an Apex class, you are creating metadata. When that class executes and inserts a record, it is manipulating data.
🗂️ The Metadata API
Section titled “🗂️ The Metadata API”The Metadata API is the bridge between your local environment and your Salesforce org. When you run sf project retrieve start, the CLI uses this API to pull metadata into your local Salesforce DX source format. In practice, that local source includes both implementation files (for example .xml, .cls, .trigger, .js, .html) and metadata descriptor files (commonly -meta.xml). When you run sf project deploy start, the CLI converts and packages that local source back into the format Salesforce expects and deploys it to the org.
Every metadata component is represented in local source files, often paired with metadata descriptor XML (or bundled, as with LWC), in your project:
| Setup Component | Metadata Type | Local File Path |
|---|---|---|
| Apex Class | ApexClass | classes/MyClass.cls |
| Custom Object | CustomObject | objects/Object__c/Object__c.object-meta.xml |
| Custom Field | CustomField | objects/Object__c/fields/Field__c.field-meta.xml |
| Flow | Flow | flows/My_Flow.flow-meta.xml |
| Permission Set | PermissionSet | permissionsets/MyPerm.permissionset-meta.xml |
| Lightning Component | LightningComponentBundle | lwc/myComponent/myComponent.js (html etc.) |
Because everything is just a file, you can treat your entire org configuration like source code. You can track changes in Git, perform code reviews, and deploy updates reliably across your development, test, and production environments.
🧬 Source Format vs Metadata API Format
Section titled “🧬 Source Format vs Metadata API Format”When you read older Salesforce docs you’ll see two metadata formats mentioned. They describe the same components, just packaged differently:
- Source format (Salesforce DX) — what your
force-appdirectory uses today. Components are split into one-file-per-thing (one file per custom field, one folder per Lightning Web Component bundle). It’s friendlier to Git, code review, and parallel teamwork. - Metadata API format — the older “zip with
package.xml” format used by Change Sets, Workbench, and the classicforce:mdapi:deploycommand. Some legacy tools still emit this format.
The CLI converts between them automatically when needed (sf project convert source and sf project convert mdapi). For new development, stay in source format.
📜 The package.xml Manifest
Section titled “📜 The package.xml Manifest”You’ll see package.xml referenced in CLI examples. It’s a small XML file that lists the metadata components you want to retrieve or deploy — essentially a manifest. In source-tracked workflows (scratch orgs, source-tracked sandboxes) you rarely need to touch it because the CLI infers what’s changed. Manifests come back into play when:
- Working with non-source-tracked sandboxes (e.g. Full Copy)
- Building deterministic CI/CD packages
- Deploying to production from a curated set of components
A typical package.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?><Package xmlns="http://soap.sforce.com/2006/04/metadata"> <types> <members>AccountTriggerHandler</members> <members>ExpenseClaimService</members> <name>ApexClass</name> </types> <version>62.0</version></Package>Notice the <version> element — every metadata bundle is tied to a specific API version, which is the topic of the next subsection.
🗓️ API Versions
Section titled “🗓️ API Versions”Salesforce releases three times a year (Spring, Summer, Winter), and every release bumps the platform’s API version (62, 63, 64…). Three places carry an API version that needs to stay roughly in sync:
sfdx-project.json— thesourceApiVersionyour CLI uses by default.<apiVersion>in each-meta.xml— pinned per Apex class, trigger, LWC, etc.<version>inpackage.xml— pinned per deployment manifest.
Two practical rules:
- You don’t need to be on the latest version. Older API versions keep working. Most teams pin to a version they’ve validated and bump it deliberately a release or two after a major Salesforce release.
- You can mix versions per Apex class. Each
.cls-meta.xmlhas its own<apiVersion>, useful when you need a new feature in one class without forcing the whole org to a new version.
📖 Navigating Salesforce Developer Documentation
Section titled “📖 Navigating Salesforce Developer Documentation”As you start writing code, you’ll spend significant time in Salesforce’s developer documentation. Knowing where to find information saves hours of frustration.
📚 Key Resources
Section titled “📚 Key Resources”Apex Developer Guide — The definitive reference for Apex syntax, classes, interfaces, and platform features. This is where you go when you need to know exactly how a method works or what parameters it accepts.
Apex Reference — The API reference for all Apex system classes and methods. Use this when you know the class name and need to find the right method.
Lightning Web Components Developer Guide — The guide for building Lightning Web Components. Covers HTML templates, JavaScript controllers, data binding, events, and wire services.
Metadata API Developer Guide — Reference for all metadata types. Useful when you need to understand how a specific metadata type is structured in XML.
Salesforce CLI Command Reference — The full list of CLI commands with options and examples.
🎯 Final Thoughts
Section titled “🎯 Final Thoughts”You now have a working mental model for Salesforce development: when to use code versus declarative tools, how the core tools (CLI, VS Code, Extension Pack) fit together, what the project structure looks like, and how the retrieve-edit-deploy workflow connects to the CI/CD pipeline you already understand from your admin training.
The most important takeaway isn’t any specific tool or command. It’s this: development on Salesforce is an extension of administration, not a replacement for it. The same platform, the same data model, the same security framework. You’re adding a new set of tools to work with the system you already understand deeply.
In Part 2, we’ll start writing Apex. You’ll learn variables, collections, control flow, classes, SOQL, and DML: the building blocks that let you express business logic in code. The environment you’ve set up today is where that code will live.
🚀 Next steps
Section titled “🚀 Next steps”Now that your toolchain is in place, it’s time to start writing code. In Part 2 — Apex Fundamentals, you’ll learn the language itself: variables, collections, control flow, classes, SOQL, and DML — the building blocks behind every Salesforce automation, integration, and trigger you’ll write later.