@@ -10,7 +10,9 @@ The `sf webapp dev` command enables local development of modern web applications
1010
1111### Key Features
1212
13- - ** Auto-Discovery** : Automatically finds ` webapplication.json ` files in your project
13+ - ** Auto-Discovery** : Automatically finds webapps in ` webapplications/ ` folder
14+ - ** Optional Manifest** : ` webapplication.json ` is optional - uses sensible defaults
15+ - ** Auto-Selection** : Automatically selects webapp when running from inside its folder
1416- ** Interactive Selection** : Prompts with arrow-key navigation when multiple webapps exist
1517- ** Authentication Injection** : Automatically adds Salesforce auth headers to API calls
1618- ** Intelligent Routing** : Routes requests to dev server or Salesforce based on URL patterns
@@ -22,18 +24,15 @@ The `sf webapp dev` command enables local development of modern web applications
2224
2325## Quick Start
2426
25- ### 1. Create ` webapplication.json ` in your project
27+ ### 1. Create your webapp in the ` webapplications/ ` folder
2628
27- ``` json
28- {
29- "name" : " myApp" ,
30- "label" : " My Application" ,
31- "version" : " 1.0.0" ,
32- "outputDir" : " dist" ,
33- "dev" : {
34- "command" : " npm run dev"
35- }
36- }
29+ ```
30+ my-project/
31+ └── webapplications/
32+ └── my-app/ # Your webapp folder
33+ ├── package.json
34+ ├── src/
35+ └── webapplication.json # Optional!
3736```
3837
3938### 2. Run the command
@@ -46,6 +45,12 @@ sf webapp dev --target-org myOrg --open
4645
4746Browser opens to ` http://localhost:4545 ` with your app running and Salesforce authentication ready.
4847
48+ > ** Note** : ` webapplication.json ` is optional! If not present, the command uses:
49+ >
50+ > - ** Name** : Folder name (e.g., "my-app")
51+ > - ** Dev command** : ` npm run dev `
52+ > - ** Manifest watching** : Disabled
53+
4954---
5055
5156## Command Syntax
@@ -90,62 +95,96 @@ SF_LOG_LEVEL=debug sf webapp dev --target-org myOrg
9095
9196## Webapp Discovery
9297
93- The command automatically discovers ` webapplication.json ` files in your project, making the ` --name ` flag optional in most cases .
98+ The command automatically discovers webapps in the ` webapplications/ ` folder. Each subfolder is treated as a webapp, with ` webapplication.json ` being optional .
9499
95100### How Discovery Works
96101
97102``` mermaid
98103flowchart TD
99- Start["sf webapp dev"] --> HasName{"--name provided?"}
100- HasName -->|Yes| SearchByName["Search for webapplication.json with matching name field"]
101- HasName -->|No| SearchAll["Search all webapplication.json files in project"]
104+ Start["sf webapp dev"] --> FindFolder["Find webapplications/ folder"]
105+ FindFolder --> Found{"Found?"}
106+ Found -->|No| ErrorNone["Error: No webapplications folder found"]
107+ Found -->|Yes| HasName{"--name provided?"}
102108
103- SearchByName --> FoundMatch{"Found?"}
104- FoundMatch -->|Yes| UseManifest["Use matched webapplication.json"]
105- FoundMatch -->|No| ErrorNotFound["Error: No webapp found with name X"]
109+ HasName -->|Yes| SearchByName["Find webapp by name"]
110+ HasName -->|No| InsideWebapp{"Running from inside a webapp?"}
106111
107- SearchAll --> Count{"How many found?"}
108- Count -->|0| ErrorNone["Error: No webapplication.json found"]
109- Count -->|1| UseManifest
112+ InsideWebapp -->|Yes| AutoSelect["Auto-select current webapp"]
113+ InsideWebapp -->|No| Count{"How many webapps?"}
114+
115+ Count -->|1| AutoSelectSingle["Auto-select single webapp"]
110116 Count -->|Multiple| Prompt["Interactive selection prompt"]
111- Prompt --> UseManifest
117+
118+ SearchByName --> UseWebapp["Use webapp"]
119+ AutoSelect --> UseWebapp
120+ AutoSelectSingle --> UseWebapp
121+ Prompt --> UseWebapp
122+
123+ UseWebapp --> HasManifest{"Has webapplication.json?"}
124+ HasManifest -->|Yes| UseManifest["Use manifest config"]
125+ HasManifest -->|No| UseDefaults["Use defaults (npm run dev)"]
112126
113127 UseManifest --> StartDev["Start dev server and proxy"]
128+ UseDefaults --> StartDev
114129```
115130
116131### Discovery Behavior
117132
118- | Scenario | Behavior |
119- | -------------------------------- | ----------------------------------------------------------- |
120- | ` --name myApp ` provided | Finds webapplication.json where ` name ` field equals "myApp" |
121- | No ` --name ` , single webapp found | Auto-selects the webapp |
122- | No ` --name ` , multiple found | Shows interactive selection with arrow keys |
123- | No ` --name ` , none found | Shows error with helpful message |
133+ | Scenario | Behavior |
134+ | --------------------------------- | ---------------------------------------------- |
135+ | ` --name myApp ` provided | Finds webapp by name (manifest name or folder) |
136+ | Running from inside webapp folder | Auto-selects that webapp |
137+ | Single webapp found | Auto-selects it |
138+ | Multiple webapps found | Shows interactive selection with arrow keys |
139+ | No webapplications folder | Shows error with helpful message |
140+
141+ ### Folder Structure
142+
143+ ```
144+ my-project/
145+ └── webapplications/ # Required folder (case-insensitive)
146+ ├── app-one/ # Webapp 1 (with manifest)
147+ │ ├── webapplication.json
148+ │ ├── package.json
149+ │ └── src/
150+ ├── app-two/ # Webapp 2 (no manifest - uses defaults)
151+ │ ├── package.json
152+ │ └── src/
153+ └── app-three/ # Webapp 3 (partial manifest)
154+ ├── webapplication.json # Only has dev.command
155+ └── src/
156+ ```
124157
125158### Search Scope
126159
127- The command searches the current directory and all subdirectories, excluding:
160+ The command searches for the ` webapplications/ ` folder:
161+
162+ 1 . ** Upward** : First checks if you're inside a webapplications folder
163+ 2 . ** Downward** : Then searches child directories recursively
128164
129- - ` node_modules `
130- - ` .git `
131- - ` dist ` , ` build ` , ` out `
132- - ` coverage `
165+ Excluded directories:
166+
167+ - ` node_modules ` , ` .git ` , ` dist ` , ` build ` , ` out ` , ` coverage `
133168- ` .next ` , ` .nuxt ` , ` .output `
134169- Hidden directories (starting with ` . ` )
135170
136171### Interactive Selection
137172
138- When multiple ` webapplication.json ` files are found, you'll see an interactive prompt:
173+ When multiple webapps are found, you'll see an interactive prompt:
139174
140175```
141- Found 3 webapplication.json files in project
176+ Found 3 webapps in project
142177? Select the webapp to run: (Use arrow keys)
143- ❯ myApp - My Application (webapplication.json )
144- adminPortal - Admin Portal (apps/admin/webapplication.json)
145- dashboard - Dashboard App (packages/dashboard/webapplication.json )
178+ ❯ MyApp - My Application (webapplications/app-one )
179+ app-two (webapplications/app-two) [no manifest]
180+ CustomName (webapplications/app-three )
146181```
147182
148- Use arrow keys to navigate and Enter to select.
183+ Format:
184+
185+ - ** With manifest + label** : ` Name - Label (path) `
186+ - ** With manifest, no label** : ` Name (path) `
187+ - ** No manifest** : ` name (path) [no manifest] `
149188
150189---
151190
@@ -196,39 +235,52 @@ Browser → Proxy → [Auth Headers Injected] → Salesforce → Response
196235
197236### webapplication.json Schema
198237
199- #### Required Fields
238+ The ` webapplication.json ` file is ** optional** . All fields are also optional - missing fields use defaults.
239+
240+ #### All Fields (All Optional)
200241
201242``` json
202243{
203244 "name" : " myApp" ,
204245 "label" : " My Application" ,
205246 "version" : " 1.0.0" ,
206- "outputDir" : " dist"
247+ "outputDir" : " dist" ,
248+ "dev" : {
249+ "command" : " npm run dev"
250+ }
207251}
208252```
209253
210- | Field | Type | Description |
211- | ----------- | ------ | ----------------------------------------- |
212- | ` name ` | string | Unique identifier (used with --name flag) |
213- | ` label ` | string | Human-readable display name |
214- | ` version ` | string | Semantic version (e.g., "1.0.0") |
215- | ` outputDir ` | string | Build output directory |
254+ | Field | Type | Description | Default |
255+ | ----------- | ------ | ----------------------------------------- | ------------------ |
256+ | ` name ` | string | Unique identifier (used with --name flag) | Folder name |
257+ | ` label ` | string | Human-readable display name | None |
258+ | ` version ` | string | Semantic version (e.g., "1.0.0") | None |
259+ | ` outputDir ` | string | Build output directory | None (deploy only) |
216260
217261#### Dev Configuration
218262
219- ** Option A: Auto-spawn dev server**
263+ ** Option A: No manifest (uses defaults)**
264+
265+ If no ` webapplication.json ` exists:
266+
267+ - Dev command: ` npm run dev `
268+ - Name: folder name
269+ - Manifest watching: disabled
270+
271+ ** Option B: Minimal manifest**
220272
221273``` json
222274{
223275 "dev" : {
224- "command" : " npm run dev "
276+ "command" : " npm start "
225277 }
226278}
227279```
228280
229- The command will spawn your dev server and automatically detect its URL .
281+ Only specify what you need to override .
230282
231- ** Option B : Explicit URL (dev server already running)**
283+ ** Option C : Explicit URL (dev server already running)**
232284
233285``` json
234286{
@@ -253,7 +305,37 @@ Use this when you want to start the dev server yourself.
253305}
254306```
255307
256- ### Complete Example
308+ ### Example: Minimal (No Manifest)
309+
310+ ```
311+ webapplications/
312+ └── my-dashboard/
313+ ├── package.json # Has "scripts": { "dev": "vite" }
314+ └── src/
315+ ```
316+
317+ Run: ` sf webapp dev --target-org myOrg `
318+
319+ Console output:
320+
321+ ```
322+ Warning: No webapplication.json found for webapp "my-dashboard"
323+ Location: my-dashboard
324+ Using defaults:
325+ → Name: "my-dashboard" (derived from folder)
326+ → Command: "npm run dev"
327+ → Manifest watching: disabled
328+ 💡 To customize, create a webapplication.json file in your webapp directory.
329+
330+ ✅ Using webapp: my-dashboard (webapplications/my-dashboard)
331+
332+ ✅ Ready for development!
333+ → Proxy: http://localhost:4545 (open this in your browser)
334+ → Dev server: http://localhost:5173
335+ Press Ctrl+C to stop
336+ ```
337+
338+ ### Example: Full Configuration
257339
258340``` json
259341{
@@ -287,6 +369,8 @@ Manifest changed detected
287369Dev server URL updated to: http://localhost:5174
288370```
289371
372+ > ** Note** : Manifest watching is only enabled when ` webapplication.json ` exists. Webapps without manifests don't have this feature.
373+
290374### Health Monitoring
291375
292376The proxy continuously monitors dev server availability:
@@ -311,29 +395,39 @@ Automatically detects Salesforce Code Builder environment and binds to `0.0.0.0`
311395
312396## Troubleshooting
313397
314- ### "No webapplication.json found"
398+ ### "No webapplications folder found"
315399
316- Ensure you have a ` webapplication.json ` file with required fields :
400+ Create a ` webapplications/ ` folder with at least one webapp subfolder :
317401
318- ``` json
319- {
320- "name" : " myApp" ,
321- "label" : " My Application" ,
322- "version" : " 1.0.0" ,
323- "outputDir" : " dist"
324- }
402+ ```
403+ my-project/
404+ └── webapplications/
405+ └── my-app/
406+ └── package.json
325407```
326408
409+ Note: ` webapplication.json ` is optional!
410+
327411### "No webapp found with name X"
328412
329- The ` --name ` flag matches the ` name ` field inside ` webapplication.json ` , not the file path:
413+ The ` --name ` flag matches either:
414+
415+ 1 . The ` name ` field in ` webapplication.json `
416+ 2 . The folder name (if no manifest or no name in manifest)
330417
331418``` bash
332- # This looks for webapplication.json where name= "myApp"
419+ # This looks for webapp named "myApp"
333420sf webapp dev --name myApp --target-org myOrg
334421```
335422
336- Check your ` webapplication.json ` content to verify the name.
423+ ### "Dependencies Not Installed" / "command not found"
424+
425+ Install dependencies in your webapp folder:
426+
427+ ``` bash
428+ cd webapplications/my-app
429+ npm install
430+ ```
337431
338432### "No Dev Server Detected"
339433
@@ -362,12 +456,37 @@ sf org login web --alias myOrg
362456
363457### Debug Mode
364458
365- Enable detailed logging:
459+ Enable detailed logging by setting ` SF_LOG_LEVEL=debug ` . Debug logs are written to the SF CLI log file (not stdout).
460+
461+ ** Step 1: Start log tail in Terminal 1**
462+
463+ ``` bash
464+ # Tail today's log file, filtering for webapp messages
465+ tail -f ~ /.sf/sf-$( date +%Y-%m-%d) .log | grep --line-buffered WebappDev
466+
467+ # Or for cleaner output (requires jq):
468+ tail -f ~ /.sf/sf-$( date +%Y-%m-%d) .log | grep --line-buffered WebappDev | jq -r ' .msg'
469+ ```
470+
471+ ** Step 2: Run command in Terminal 2**
366472
367473``` bash
368474SF_LOG_LEVEL=debug sf webapp dev --target-org myOrg
369475```
370476
477+ ** Example debug output:**
478+
479+ ```
480+ Discovering webapplication.json manifest(s)...
481+ Using webapp: myApp at webapplications/my-app
482+ Manifest loaded: myApp
483+ Starting dev server with command: npm run dev
484+ Dev server ready at: http://localhost:5173/
485+ Using authentication for org: user@example.com
486+ Starting proxy server on port 4545...
487+ Proxy server running on http://localhost:4545
488+ ```
489+
371490---
372491
373492## VSCode Integration
0 commit comments