This guide walks through the complete development workflow using sfp in a modular Salesforce project following the Flxbl framework.
Overview
The development workflow in an sfp-powered project follows an iterative approach where developers work in isolated environments, make changes using source-driven development, and submit their work through pull requests that trigger automated validation and review environments.
Prerequisites
DevHub Access Required
Before starting development with sfp, ensure you have:
# List available scratch orgs in pool (alias: pool:list)
sfp pool scratch list --tag dev-pool
# Fetch a scratch org from the pool (alias: pool:fetch)
sfp pool scratch fetch --tag dev-pool --alias my-feature-org
# Initialize a pool if empty (aliases: prepare, pool:prepare)
sfp pool scratch init --tag dev-pool \
--targetdevhubusername mydevhub \
--config config/project-scratch-def.json \
--count 5
# List available instances (works for both scratch orgs and sandboxes)
sfp server pool instance list \
--repository myorg/myrepo \
--tag dev-pool
# Fetch an org from the pool (scratch or sandbox)
sfp server pool instance fetch \
--repository myorg/myrepo \
--tag dev-pool \
--assignment-id feature-123
# Extend org expiration if needed
sfp server pool instance extend \
--repository myorg/myrepo \
--tag dev-pool \
--assignment-id feature-123 \
--expiration-hours 48
# Unassign and return to pool when done
sfp server pool instance unassign \
--repository myorg/myrepo \
--tag dev-pool \
--assignment-id feature-123
# Create a new sandbox directly
sfp sandbox create --name feature-sandbox \
--type Developer \
--source-org production \
--alias my-feature-sandbox
# Open the org to verify access (sfp-pro)
sfp org open --targetusername my-feature-org
# Open in a specific browser (sfp-pro)
sfp org open --targetusername my-feature-org --browser chrome
# For community edition, use Salesforce CLI
sf org open --target-org my-feature-org
# Set as default for convenience (sfp-pro)
sfp config set target-org my-feature-org
# Set globally (sfp-pro)
sfp config set target-org my-feature-org --global
# Pull all changes from the org (using aliases: pull, source:pull, project:pull)
sfp pull --targetusername my-feature-org
# Pull with conflict resolution
sfp pull --targetusername my-feature-org --ignore-conflicts
# Pull a specific package
sfp pull --targetusername my-feature-org --package my-package
# Pull and see what replacements were reversed (sfp-pro)
sfp pull --targetusername my-feature-org --json
# Create a new source package (sfp-pro)
sfp package create source -n "feature-payment" \
-r "src/payment-processing" \
--domain
# Create an unlocked package
sfp package create unlocked -n "feature-payment" \
-r "src/payment-processing" \
-v mydevhub
# Create a data package
sfp package create data -n "reference-data" \
-r "data/reference-data"
# For community edition, manually add to sfdx-project.json
# Push all changes (using aliases: push, source:push, project:push)
sfp push --targetusername my-feature-org
# Push a specific package
sfp push --targetusername my-feature-org --package my-package
# Push ignoring conflicts
sfp push --targetusername my-feature-org --ignore-conflicts
# Push and see what replacements were applied (sfp-pro)
sfp push --targetusername my-feature-org --json
# Build all packages (DevHub required)
sfp build --devhubalias mydevhub
# Build a specific domain
sfp build --devhubalias mydevhub --domain sales
# Build a specific package
sfp build --devhubalias mydevhub --package payment-processing
# Build with different options
sfp build --devhubalias mydevhub \
--branch feature/payment \
--buildnumber 123 \
--diffcheck
# Note: DevHub is required even for source packages to resolve dependencies
# Test a specific package (recommended)
sfp apextests trigger -o my-feature-org -l RunAllTestsInPackage -n sales-core
# Test all packages in a domain
sfp apextests trigger -o my-feature-org -l RunAllTestsInDomain \
-r config/release-config.yaml
# Quick test during development
sfp apextests trigger -o my-feature-org -l RunSpecifiedTests \
--specifiedtests PaymentProcessorTest
# Test with code coverage validation
sfp apextests trigger -o my-feature-org -l RunAllTestsInPackage \
-n sales-core -c -p 80
# Install a single package
sfp install --target-org my-feature-org \
--artifacts artifacts \
--package payment-processing
# Install with skip testing for faster deployment
sfp install --target-org my-feature-org \
--artifacts artifacts \
--skipifalreadyinstalled
# Commit your changes
git add .
git commit -m "feat: implement payment processing module"
# Push to your feature branch
git push origin feature/payment-processing
# Create PR using GitHub CLI (optional)
gh pr create --title "Payment Processing Module" \
--body "Implements new payment gateway integration"
# This runs automatically in CI/CD
sfp validate org --target-org validation-org \
--mode thorough \
--coverageThreshold 75
# CI/CD creates an ephemeral environment
sfp pool scratch fetch --pool review-pool \
--alias pr-123-review
# Install the changes
sfp install --target-org pr-123-review \
--artifacts artifacts
# This happens automatically in CI/CD
sfp build --branch main
sfp publish --artifacts artifacts \
--npm-registry https://your-registry.com
# Pull from a specific environment
sfp pull --targetusername dev-sandbox
# The correct variant is automatically selected
# src-env-specific/main/dev/* contents are used
# Create preDeploy/replacements.yml in your package
replacements:
- name: "API Endpoint"
glob: "**/*.cls"
pattern: "%%API_URL%%"
environments:
default: "https://api.dev.example.com"
prod: "https://api.example.com"
# Push replaces placeholders with environment values
sfp push --targetusername my-feature-org
# Pull reverses replacements back to placeholders
sfp pull --targetusername my-feature-org
sfp push --targetusername my-feature-org
# Check pool status
sfp pool scratch list --tag dev-pool
# Replenish the pool (aliases: prepare, pool:prepare)
sfp pool scratch init --tag dev-pool \
--targetdevhubusername mydevhub \
--count 5
# Check pool status
sfp server pool status --repository myorg/myrepo --tag dev-pool
# Replenish pool (works for both scratch orgs and sandboxes)
sfp server pool replenish \
--repository myorg/myrepo \
--tag dev-pool
# Ignore conflicts during pull
sfp pull --targetusername my-feature-org --ignore-conflicts
# Ignore conflicts during push
sfp push --targetusername my-feature-org --ignore-conflicts
# Check for issues in specific package
sfp build --devhubalias mydevhub \
--package problematic-package \
--loglevel DEBUG
# Validate dependencies
sfp dependency explain --package problematic-package
# Re-authenticate to DevHub
sf org login web --alias mydevhub --set-default-dev-hub
# Verify DevHub is enabled
sf org display --target-dev-hub
# Check DevHub limits
sf limits api display --target-org mydevhub