<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://blog.ogrodowicz.net/feed.xml" rel="self" type="application/atom+xml" /><link href="https://blog.ogrodowicz.net/" rel="alternate" type="text/html" /><updated>2026-07-21T16:30:04+00:00</updated><id>https://blog.ogrodowicz.net/feed.xml</id><title type="html">Piotr’s Little (mostly) Salesforce Blog</title><subtitle>Writing stuff about  Salesforce and the technology around it.</subtitle><entry><title type="html">What makes a SFDX project?</title><link href="https://blog.ogrodowicz.net/2025/05/05/what-makes-a-sfdx-project.html" rel="alternate" type="text/html" title="What makes a SFDX project?" /><published>2025-05-05T00:00:00+00:00</published><updated>2025-05-05T00:00:00+00:00</updated><id>https://blog.ogrodowicz.net/2025/05/05/what-makes-a-sfdx-project</id><content type="html" xml:base="https://blog.ogrodowicz.net/2025/05/05/what-makes-a-sfdx-project.html"><![CDATA[<p>When working with SFDX, for most of the operations you need to be in a ‘project’. SF CLI will tell you if you are not. But…what makes the directory to BE a SFDX project?</p>

<h1 id="i-got-no-time-just-tell-me">I got no time, just tell me.</h1>
<p>Well, TL;DR version of this post is this:</p>

<p>By reading the <a href="https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_ws_config.htm">documentation</a>, you’ll find the information, that the only required property in <code class="language-plaintext highlighter-rouge">project-sfdx.json</code> file is <strong>packageDirectories</strong>.</p>

<p>So:</p>

<ol>
  <li>Create a <strong>project-sfdx.json</strong> file with <code class="language-plaintext highlighter-rouge">packageDirectories</code> property and at least one <strong>path</strong></li>
  <li>That path <strong>must be real</strong>. Meaning, that directory HAS to exist</li>
</ol>

<p>…and that’s it.</p>

<p>You don’t need any <code class="language-plaintext highlighter-rouge">sf project generate</code> command, you don’t need to do anything else. That’s the bare minimum and you’re good to go.</p>

<p><code class="language-plaintext highlighter-rouge">sfdx-project.json</code>, version <strong>bare minimum</strong>:</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
    </span><span class="nl">"packageDirectories"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
        </span><span class="p">{</span><span class="w">
            </span><span class="nl">"path"</span><span class="p">:</span><span class="w"> </span><span class="s2">"force-app/"</span><span class="w">
        </span><span class="p">}</span><span class="w">
    </span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>Fun fact, this directory has to exist, but you still are able to retrieve stuff in <strong>different directory</strong>, and it will work perfectly fine:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>~/Gitrepos/THE-salesforce-project/just-project » sf project retrieve start <span class="nt">-o</span> MDAPI <span class="nt">-m</span> CustomObject:Account <span class="nt">-r</span> force-something
</code></pre></div></div>

<p>It will create another directory (here, <code class="language-plaintext highlighter-rouge">force-something</code>) and retrieve stuff there. Can be useful in CI/CD stuff.</p>

<h1 id="whats-in-those-project-files-exactly">What’s in those project files, exactly?</h1>

<p>When you DO decide to do some <strong>sf cli</strong> magic, you’ll find a command <code class="language-plaintext highlighter-rouge">sf project generate</code> and that gives you an option to use one of 3 templates:</p>
<ol>
  <li>empty</li>
  <li>standard</li>
  <li>analytics</li>
</ol>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="nt">-t</span>, <span class="nt">--template</span><span class="o">=</span>standard|empty|analytics  Template to use <span class="k">for </span>project creation.

    The template determines the sample configuration files and directories that this <span class="nb">command </span>generates. For example, the empty template provides these files and directory to get you started.

    - .forceignore
    - config/project-scratch-def.json
    - sfdx-project.json
    - package.json
    - force-app <span class="o">(</span>basic <span class="nb">source </span>directory structure<span class="o">)</span>

    The standard template provides a <span class="nb">complete </span>force-app directory structure so you know where to put your source. It also provides additional files and scripts, especially useful when using Salesforce Extensions <span class="k">for </span>VS Code. For example:

    - .gitignore: Use Git <span class="k">for </span>version control.
    - .prettierrc and .prettierignore: Use Prettier to format your Aura components.
    - .vscode/extensions.json: When launched, Visual Studio Code, prompts you to <span class="nb">install </span>the recommended extensions <span class="k">for </span>your project.
    - .vscode/launch.json: Configures Replay Debugger.
    - .vscode/settings.json: Additional configuration settings.

    The analytics template provides similar files and the force-app/main/default/waveTemplates directory.
</code></pre></div></div>

<p>those files might not be <em>required</em>, but for sure are useful and you might simply <strong>want</strong> to have those in your repository.</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">.forceignore</code> file is similar to <code class="language-plaintext highlighter-rouge">.gitignore</code>, but it applies to the deployments.</li>
</ul>

<p>From <a href="https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_exclude_source.htm">docs</a>: <em>The .forceignore file excludes files when running most of the project commands, such as project deploy start, project retrieve start, project convert source, and project delete source.</em></p>

<p>So, want to have some files on your org, but you want to exclude them from deployments? Or maybe you have some metadata, that is <strong>always</strong> retrieved, even when not needed? Here you go.</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">config/project-scratch-def.json</code> - this one helps you with working with scratch orgs.</li>
</ul>

<p>This is the definition of your scratch org, so you can turn some features on and off, tell <em>exactly</em> how do you want your scratch org to look like. You can also have <strong>multiple</strong> definitions for multiple purposes! You can read more <a href="https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_scratch_orgs_def_file.htm">here</a></p>

<p>Damn, how many times in recent years I’ve said to myself <em>learn more about scratch orgs</em>… It’s still on my todo list.</p>

<ul>
  <li>
    <p><code class="language-plaintext highlighter-rouge">sfdx-project.json</code> is a definition of your project. You can define sourceApiVersion, source directories, namespace and much more. A very cool feature that I should mention here is <strong>replacements</strong>. That allows you to modify your metadata <em>just for this deployment</em>. That means, you can have some emails, addresses, values that are different for each environment. With this you can replace such value with ENV variable or a file. Neat feature for CI/CD. Read more <a href="https://developer.salesforce.com/docs/atlas.en-us.254.0.sfdx_dev.meta/sfdx_dev/sfdx_dev_ws_string_replace.htm">here</a>.</p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">package.json</code> this one is not strictly related to SFDX, but it has its purpose. It is used by Node (which you need to use SF CLI). It installs all the dev dependencies, other ESLints, prettiers etc.</p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">.gitignore</code> - this is a GIT file. It defines files (and directories) that should be ignored while commiting. This one is project-wide, so it applies to all devs working on this repository. And it has to be commited of course.</p>
  </li>
</ul>

<p>If you want your own exclusions, check <code class="language-plaintext highlighter-rouge">.git/info/exclude</code> file - this one is personal.</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">.prettierrc</code> and <code class="language-plaintext highlighter-rouge">.prettierignore</code> - both files are used by <a href="https://prettier.io/docs/">Prettier</a> to format your code.</li>
</ul>

<p><code class="language-plaintext highlighter-rouge">prettierrc</code> is a configuration file (like, how do you want your indent, bro?) and <code class="language-plaintext highlighter-rouge">prettierignore</code> is what you want to omit during formatting your code. To put it simply.
<a href="https://prettier.io/docs/configuration">Here</a> you can read about config file, and <a href="https://prettier.io/docs/ignore">here</a> about ignoring files.</p>

<p>Last 3 files are related to VSCode itself (which is currently “official” Salesforce IDE. So, I’ll just quote the output of <code class="language-plaintext highlighter-rouge">sf project generate --help</code> output:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">.vscode/extensions.json</code>: When launched, Visual Studio Code, prompts you to install the recommended extensions for your project.</li>
  <li><code class="language-plaintext highlighter-rouge">.vscode/launch.json</code>: Configures Replay Debugger.</li>
  <li><code class="language-plaintext highlighter-rouge">.vscode/settings.json</code>: Additional configuration settings.</li>
</ul>

<p>And there’s that!</p>]]></content><author><name>ogrodowiczp</name></author><category term="sfdx,sfcli,salesforce,devops" /><summary type="html"><![CDATA[When working with SFDX, for most of the operations you need to be in a ‘project’. SF CLI will tell you if you are not. But…what makes the directory to BE a SFDX project?]]></summary></entry></feed>