Here’s a battle-tested, simple structure for one repo hosting many Business Central extensions, plus a clean naming/ID/range/versioning standard that won’t hurt you later when you add CI/CD.
Recommended
repo structure (one repo, many apps)
Option A
(recommended): One folder per extension under /apps
Works great
with pipelines later, easy to clone anywhere.
bc-extensions/
README.md
.gitignore
.editorconfig (optional)
.azure-pipelines/ (later)
apps/
CustomerExt-01/
src/ (AL project lives here)
app.json
.vscode/
launch.json
settings.json
HelloWorld.al (or your objects)
tables/
pageextensions/
codeunits/
docs/ (optional: specs)
overview.md
test/ (optional: test app later)
VendorExt-01/
src/
app.json
.vscode/...
...
tools/ (optional)
scripts/
Why this
is best
- Each app is self-contained.
- Developers open
apps/<AppName>/src and they’re productive immediately.
- CI/CD can build all apps or
only changed apps.
Option B:
Monorepo with shared “workspace” and common VS Code config
Only do this
if your team is mature with AL tooling; otherwise it adds complexity.
VS Code
launch.json strategy for multi-app repo
You have two
clean choices:
Choice 1
(simplest): each app has its own .vscode/launch.json
- Each
apps/<AppName>/src/.vscode/launch.json targets the correct sandbox.
- No confusion—open that app’s src
folder and publish.
Choice 2
(more advanced): one shared .vscode at repo root
- Use variables / multiple
configurations, but it’s easier to mess up.
- I’d avoid until CI/CD is in.
Naming
standards
Repo name
- bc-extensions (if it hosts
multiple)
- OR
bc-<customer>-extensions (if dedicated to one customer)
App
folder name
Use:
PascalCase + short suffix:
- CustomerExt-01
- SalesEnhancements-01
- IntegrationPack-01
app.json
name
Match
folder:
- "name":
"CustomerExt-01"
app.json
publisher
Use one
publisher consistently (important later for upgrades):
- "publisher":
"MicroCloud 360"
Avoid
“Default Publisher” once you start real work.
App IDs
(GUIDs)
Rule
- One unique GUID per extension
app
- Never change it after first
release (changing ID breaks upgrade path)
Practical
approach
- Let AL generate it once.
- Store it forever in app.json.
Tip: Keep a small registry in /README.md
or /docs/apps.md listing:
- App Name
- App ID (GUID)
- Range
- Purpose
Example:
|
App |
App ID |
Range |
|
CustomerExt-01 |
xxxxxxxx-xxxx-... |
50100–50149 |
Object
range strategy (IDs)
You need a
clean plan so multiple apps never collide.
Option A
(simple and scalable): allocate blocks per app
Example
allocation (easy to remember):
- CustomerExt-01: 50100–50149
- VendorExt-01: 50150–50199
- SalesExt-01: 50200–50249
- IntegrationExt-01: 50250–50299
This works
well if you keep apps small.
Option B
(more enterprise): allocate blocks per domain
- Customers: 50100–50999
- Vendors: 51000–51999
- Sales: 52000–52999
Then each
app inside the domain takes a smaller block.
Recommendation
for you
Since you’re
building multiple discrete extensions: Option A (block per app) is the
cleanest.
Versioning
standard (app.json version)
Use
Semantic-ish versioning
MAJOR.MINOR.PATCH.BUILD
- MAJOR: breaking change / major
release (rare)
- MINOR: new feature
- PATCH: bugfix
- BUILD: optional increment for
internal builds
Examples:
- 1.0.0.0 first release
- 1.0.1.0 bugfix release
- 1.1.0.0 new features
- 2.0.0.0 breaking change
Practical
rule (easy to follow)
- For each change you deploy to
sandbox: bump PATCH
- For new features: bump MINOR
- For hotfixes: bump PATCH
- Ignore BUILD unless CI uses it
later
Runtime /
platform / application fields
Keep
runtime aligned with your BC version
If your SaaS
is current (v25/26/27 etc), typical runtime is 13+, 14+, 15+, 16+, 17+
depending on the environment.
Rule:
- Don’t guess—use what your
sandbox expects (your earlier issue was caused by runtime mismatch).
Recommended
approach
- After creating the project,
download symbols successfully, then keep:
- "platform" and
"application" consistent with your environment symbols.
- If symbols download is ok, your
platform/application is typically fine.
Git
branching / workflow (simple but correct)
Branches
- main (protected ideally)
- feature branches per change:
- feature/customer-fields
- bugfix/customer-card-tooltip
Commit
message standard
- CustomerExt-01: Add MC Reviewed
fields
- VendorExt-01: Fix validation in
posting
Tagging
(later)
When you
release a version:
- tag: CustomerExt-01/v1.1.0
.gitignore
for multi-app repo
At repo
root:
# AL
generated artifacts (in any app)
**/.alpackages/
**/.alcache/
**/.snapshots/
**/*.app
# VS Code -
keep only shared config if you want
**/.vscode/*
!**/.vscode/launch.json
!**/.vscode/settings.json
# OS
.DS_Store
Thumbs.db
“Open the
right folder” rule (avoids confusion)
When working
on an app:
✅ Open folder:
- apps/CustomerExt-01/src
Not the repo
root, not /apps, not src of another app.
Suggested
“starter template” per app (clean folders)
Inside each
src:
src/
app.json
.vscode/
launch.json
settings.json
tableextensions/
pageextensions/
codeunits/
permissionsets/
profiles/ (optional)
No comments:
Post a Comment