Compile + output management
Where Ctrl+B writes files, how ownership works, and how to recover if something goes wrong.
Table of contents
- First compile
- Subsequent compiles
- What gets written
- Ownership rules
- .User.scss sidecar
- Backups
- Manifest
- Recovery scenarios
- See also
First compile
When you press Ctrl+B (or click Compile) the first time on a document:
- The validator runs (
SuiDocumentValidator). Errors are logged but don’t block. - The generator runs (
SuiGenerationPipeline.Run). Produces in-memory.razor+.razor.scss. - A folder picker opens — “Where should the generated files land?”
- You select a folder (typically
Code/UI/inside your project). - The writer (
SuiCompileWriter) writes the files and creates the manifest entry.
Subsequent compiles
After the first compile, the output folder is saved on the Document.Output.RootFolder. Subsequent compiles skip the picker and go straight to writing.
Change it later via File → Change Output Folder….
What gets written
For a document with Output.ClassName = "MyHud":
<outputFolder>/
├── MyHud.razor # Generated. Has SUI:GENERATED header
├── MyHud.razor.scss # Generated. Has SUI:GENERATED header
└── MyHud.User.scss # User-owned. Created once, never overwritten
# Imported by the .razor.scss via @import at the bottom
Plus, in <outputFolder>/.sui-manifest/:
<DocumentId>.json # Tracks file paths + hashes for this document
Ownership rules
Every generated file has a header:
@* SUI:GENERATED:BEGIN ==========================================================
Generated by Sbox UI Designer.
Source: my_hud.sui
DocumentId: sui_my_hud_a3b2c1d4
GeneratorVersion: 0.1.0
Do not edit this file manually. Changes will be overwritten.
SUI:GENERATED:END ============================================================ *@
On recompile, the writer checks each file:
- Has our header + DocumentId matches + hash matches the new content → Skipped (no-op)
- Has our header + DocumentId matches + hash differs → Preserved (backup the old, write the new)
- Has our header but DocumentId is different → Conflict — won’t touch. User must investigate.
- Has no header → Conflict. Could be a hand-written file at the same path.
- Doesn’t exist on disk → Generated (fresh write).
.User.scss sidecar
For every generated .razor.scss, the writer also writes a .User.scss file once. It contains a boilerplate stub:
// MyHud.User.scss — your custom styles for MyHud.
// This file is created once and never overwritten by the SUI compiler.
// Edit freely — your rules win the cascade because the generated
// .razor.scss imports this file last.
MyHud {
// Example:
// .my-class { color: red; }
}
You edit this file freely. Recompile never overwrites it.
The main .razor.scss imports it at the bottom:
/* ...generated rules... */
// User-protected styles for MyHud — safe to edit.
@import "MyHud.User.scss";
User rules cascade-win (later wins in CSS for same specificity).
Backups
When a file moves from “Generated” → “Preserved” (existing file with different hash gets overwritten), the prior content is backed up to:
<projectRoot>/.sui-backups/<DocumentName>/<UTC-timestamp>/<file>
Backups live OUTSIDE Code/ so the engine doesn’t compile them as duplicate partial class declarations.
Backups are never auto-cleaned. Use Tools → Clean All SUI Caches to wipe them when comfortable.
Manifest
The manifest at .sui-manifest/<DocumentId>.json tracks every file the document owns:
{
"GeneratedFiles": [
{
"Kind": "Razor",
"Path": "MyHud.razor",
"LastHash": "abc123…",
"OwnedByDocumentId": "sui_my_hud_a3b2c1d4",
"GeneratorVersion": "0.1.0"
},
{
"Kind": "Scss",
"Path": "MyHud.razor.scss",
"LastHash": "def456…",
...
}
]
}
The writer uses the manifest to detect Obsolete entries — files that were in the previous compile but not in this one (e.g. user renamed the class).
Recovery scenarios
“I edited the generated file and it got overwritten”
- Open the backup folder (path shown in Compile Results).
- Find the backup with timestamps before your overwrite.
- Manually re-merge your edits into
.User.scssso they survive future compiles.
“I renamed the class and now have orphan files”
The old files are marked as Conflicts (their header still references the old DocumentId, but the new compile didn’t write them). Manually delete the old files.
“Compile says Conflict on a file I didn’t touch”
Check the file’s header. If it’s missing or wrong, something else stripped it. Move it aside, recompile, then re-merge.
“Generation failed with SCSS errors”
Check the engine console for [Sui] scss emit blocked: messages — the validator rejected a property. Common causes: unsupported CSS in .User.scss (e.g. display: grid). Fix the property and recompile.