create-flowmo 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,272 @@
1
+ ---
2
+ name: outsystems-sql
3
+ description: >-
4
+ OutSystems SQL query authoring for both O11 (MSSQL) and ODC (PostgreSQL).
5
+ Covers entity references, aggregate syntax, advanced SQL, joins, functions,
6
+ parameterized queries, and platform-specific syntax differences. Use when the
7
+ developer is writing SQL queries, creating aggregates, or working with data
8
+ retrieval logic in OutSystems.
9
+ compatibility: Designed for OutSystems Service Studio. Requires knowledge of target platform (O11 or ODC).
10
+ metadata:
11
+ version: "1.0"
12
+ source: "OutSystems documentation and SQL best practices"
13
+ ---
14
+
15
+ # OutSystems SQL Skill
16
+
17
+ ## Platform Detection
18
+
19
+ Before writing any SQL, determine the target platform:
20
+
21
+ - **O11 (OutSystems 11)** — Uses Microsoft SQL Server syntax (T-SQL)
22
+ - **ODC (OutSystems Developer Cloud)** — Uses PostgreSQL syntax
23
+
24
+ Ask the developer which platform they are targeting if not already clear. The syntax differences are significant and mixing them will produce runtime errors.
25
+
26
+ ## Entity & Attribute References
27
+
28
+ ### O11 (MSSQL)
29
+ ```sql
30
+ SELECT {Entity}.[Attribute1], {Entity}.[Attribute2]
31
+ FROM {Entity}
32
+ WHERE {Entity}.[IsActive] = 1
33
+ ```
34
+ - Entities: `{EntityName}` in curly braces
35
+ - Attributes: `[AttributeName]` in square brackets
36
+ - Boolean: `1` / `0`
37
+
38
+ ### ODC (PostgreSQL)
39
+ ```sql
40
+ SELECT entity."Attribute1", entity."Attribute2"
41
+ FROM entity
42
+ WHERE entity."IsActive" = true
43
+ ```
44
+ - Entities: lowercase, no braces
45
+ - Attributes: `"AttributeName"` in double quotes (case-sensitive)
46
+ - Boolean: `true` / `false`
47
+
48
+ ## Syntax Differences Quick Reference
49
+
50
+ | Operation | O11 (MSSQL) | ODC (PostgreSQL) |
51
+ |-----------|-------------|------------------|
52
+ | Current date/time | `GETDATE()` | `NOW()` |
53
+ | Top N rows | `SELECT TOP N ...` | `SELECT ... LIMIT N` |
54
+ | Null coalesce | `ISNULL(x, default)` | `COALESCE(x, default)` |
55
+ | String concat | `'a' + 'b'` | `'a' \|\| 'b'` |
56
+ | Boolean values | `1` / `0` | `true` / `false` |
57
+ | Identity insert | `SCOPE_IDENTITY()` | `RETURNING Id` |
58
+ | Date diff | `DATEDIFF(day, d1, d2)` | `d2 - d1` or `EXTRACT(...)` |
59
+ | Substring | `SUBSTRING(s, start, len)` | `SUBSTRING(s FROM start FOR len)` |
60
+ | Type cast | `CAST(x AS INT)` | `CAST(x AS INTEGER)` or `x::integer` |
61
+ | IF/ELSE in query | `IIF(cond, t, f)` | `CASE WHEN cond THEN t ELSE f END` |
62
+ | String length | `LEN(s)` | `LENGTH(s)` |
63
+ | Trim | `LTRIM(RTRIM(s))` | `TRIM(s)` |
64
+ | Regex match | `LIKE` + `PATINDEX` | `~` or `SIMILAR TO` |
65
+ | Pagination | `OFFSET N ROWS FETCH NEXT M ROWS ONLY` | `LIMIT M OFFSET N` |
66
+ | Auto-increment | `IDENTITY(1,1)` | `SERIAL` or `GENERATED ALWAYS AS IDENTITY` |
67
+ | Temp tables | `#TempTable` | `CREATE TEMP TABLE` |
68
+ | Table variable | `DECLARE @t TABLE(...)` | Not supported — use CTEs |
69
+ | Merge/Upsert | `MERGE INTO ... USING ...` | `INSERT ... ON CONFLICT ... DO UPDATE` |
70
+
71
+ ## Common Query Patterns
72
+
73
+ ### CRUD — Create
74
+ **O11:**
75
+ ```sql
76
+ INSERT INTO {Entity} ([Attr1], [Attr2], [CreatedDate])
77
+ VALUES (@Param1, @Param2, GETDATE())
78
+ ```
79
+
80
+ **ODC:**
81
+ ```sql
82
+ INSERT INTO entity ("Attr1", "Attr2", "CreatedDate")
83
+ VALUES (@Param1, @Param2, NOW())
84
+ RETURNING "Id"
85
+ ```
86
+
87
+ ### CRUD — Read with Join
88
+ **O11:**
89
+ ```sql
90
+ SELECT {Order}.[Id], {Order}.[Total], {Customer}.[Name]
91
+ FROM {Order}
92
+ INNER JOIN {Customer} ON {Customer}.[Id] = {Order}.[CustomerId]
93
+ WHERE {Order}.[Status] = @Status
94
+ ORDER BY {Order}.[CreatedDate] DESC
95
+ ```
96
+
97
+ **ODC:**
98
+ ```sql
99
+ SELECT o."Id", o."Total", c."Name"
100
+ FROM "order" o
101
+ INNER JOIN customer c ON c."Id" = o."CustomerId"
102
+ WHERE o."Status" = @Status
103
+ ORDER BY o."CreatedDate" DESC
104
+ ```
105
+
106
+ ### CRUD — Update
107
+ **O11:**
108
+ ```sql
109
+ UPDATE {Entity}
110
+ SET [Attr1] = @NewValue, [ModifiedDate] = GETDATE()
111
+ WHERE [Id] = @Id
112
+ ```
113
+
114
+ **ODC:**
115
+ ```sql
116
+ UPDATE entity
117
+ SET "Attr1" = @NewValue, "ModifiedDate" = NOW()
118
+ WHERE "Id" = @Id
119
+ ```
120
+
121
+ ### CRUD — Delete (Soft)
122
+ **O11:**
123
+ ```sql
124
+ UPDATE {Entity}
125
+ SET [IsActive] = 0, [DeletedDate] = GETDATE()
126
+ WHERE [Id] = @Id
127
+ ```
128
+
129
+ **ODC:**
130
+ ```sql
131
+ UPDATE entity
132
+ SET "IsActive" = false, "DeletedDate" = NOW()
133
+ WHERE "Id" = @Id
134
+ ```
135
+
136
+ ### Aggregation with Group By
137
+ **O11:**
138
+ ```sql
139
+ SELECT {Category}.[Name], COUNT(*) AS Total, SUM({Product}.[Price]) AS Revenue
140
+ FROM {Product}
141
+ INNER JOIN {Category} ON {Category}.[Id] = {Product}.[CategoryId]
142
+ WHERE {Product}.[IsActive] = 1
143
+ GROUP BY {Category}.[Name]
144
+ HAVING COUNT(*) > 5
145
+ ORDER BY Revenue DESC
146
+ ```
147
+
148
+ **ODC:**
149
+ ```sql
150
+ SELECT c."Name", COUNT(*) AS "Total", SUM(p."Price") AS "Revenue"
151
+ FROM product p
152
+ INNER JOIN category c ON c."Id" = p."CategoryId"
153
+ WHERE p."IsActive" = true
154
+ GROUP BY c."Name"
155
+ HAVING COUNT(*) > 5
156
+ ORDER BY "Revenue" DESC
157
+ ```
158
+
159
+ ### Pagination
160
+ **O11:**
161
+ ```sql
162
+ SELECT {Entity}.[Id], {Entity}.[Name]
163
+ FROM {Entity}
164
+ ORDER BY {Entity}.[Name]
165
+ OFFSET @StartIndex ROWS
166
+ FETCH NEXT @MaxRecords ROWS ONLY
167
+ ```
168
+
169
+ **ODC:**
170
+ ```sql
171
+ SELECT e."Id", e."Name"
172
+ FROM entity e
173
+ ORDER BY e."Name"
174
+ LIMIT @MaxRecords OFFSET @StartIndex
175
+ ```
176
+
177
+ ### Subquery / EXISTS
178
+ **O11:**
179
+ ```sql
180
+ SELECT {Customer}.[Id], {Customer}.[Name]
181
+ FROM {Customer}
182
+ WHERE EXISTS (
183
+ SELECT 1 FROM {Order}
184
+ WHERE {Order}.[CustomerId] = {Customer}.[Id]
185
+ AND {Order}.[Total] > 1000
186
+ )
187
+ ```
188
+
189
+ **ODC:**
190
+ ```sql
191
+ SELECT c."Id", c."Name"
192
+ FROM customer c
193
+ WHERE EXISTS (
194
+ SELECT 1 FROM "order" o
195
+ WHERE o."CustomerId" = c."Id"
196
+ AND o."Total" > 1000
197
+ )
198
+ ```
199
+
200
+ ### CTE (Common Table Expression)
201
+ **O11:**
202
+ ```sql
203
+ WITH RecentOrders AS (
204
+ SELECT {Order}.[CustomerId], MAX({Order}.[CreatedDate]) AS LastOrder
205
+ FROM {Order}
206
+ GROUP BY {Order}.[CustomerId]
207
+ )
208
+ SELECT {Customer}.[Name], ro.LastOrder
209
+ FROM {Customer}
210
+ INNER JOIN RecentOrders ro ON ro.[CustomerId] = {Customer}.[Id]
211
+ ```
212
+
213
+ **ODC:**
214
+ ```sql
215
+ WITH recent_orders AS (
216
+ SELECT o."CustomerId", MAX(o."CreatedDate") AS "LastOrder"
217
+ FROM "order" o
218
+ GROUP BY o."CustomerId"
219
+ )
220
+ SELECT c."Name", ro."LastOrder"
221
+ FROM customer c
222
+ INNER JOIN recent_orders ro ON ro."CustomerId" = c."Id"
223
+ ```
224
+
225
+ ## Parameters
226
+
227
+ Always use parameters (`@ParamName`) for input values — NEVER concatenate user input into SQL strings. OutSystems enforces this in Advanced SQL but ensure it in any generated queries.
228
+
229
+ ```sql
230
+ -- CORRECT
231
+ WHERE {Entity}.[Name] LIKE '%' + @SearchTerm + '%'
232
+
233
+ -- WRONG (SQL injection risk)
234
+ WHERE {Entity}.[Name] LIKE '%' + 'user input here' + '%'
235
+ ```
236
+
237
+ ## OutSystems Aggregates vs Advanced SQL
238
+
239
+ Prefer **Aggregates** (visual query builder) for simple queries:
240
+ - Single entity or simple joins
241
+ - Standard filters, sorting, pagination
242
+ - Calculated attributes
243
+
244
+ Use **Advanced SQL** when you need:
245
+ - Complex joins (3+ entities, self-joins)
246
+ - CTEs, window functions, recursive queries
247
+ - UNION / INTERSECT / EXCEPT
248
+ - Database-specific functions
249
+ - Bulk operations
250
+ - Performance-critical queries with hints
251
+
252
+ ## Validation
253
+
254
+ After writing a SQL query, verify:
255
+ 1. All input values use `@ParamName` parameters — no string concatenation of user input
256
+ 2. `Max Records` is explicitly set on the Advanced SQL node (never leave it unlimited)
257
+ 3. The Output Structure is defined and its attributes match the SELECT column names
258
+ 4. Entity/attribute references use the correct syntax for the target platform (curly braces + square brackets for O11, lowercase + double quotes for ODC)
259
+ 5. Reserved words (`Order`, `User`, `Group`, `Table`) are properly quoted in ODC
260
+
261
+ If any check fails, fix the query before presenting the output.
262
+
263
+ ## Gotchas
264
+
265
+ 1. **OutSystems Nulls**: In O11, `NullTextIdentifier()`, `NullDate()`, etc. map to NULL in SQL. In ODC, use standard NULL comparisons.
266
+ 2. **Max Records**: Always set `Max Records` on Advanced SQL queries. Default is unlimited — this can cause performance issues.
267
+ 3. **Output Structure**: Advanced SQL queries must have an Output Structure defined. The column names in SELECT must match the Output Structure attributes.
268
+ 4. **Test Queries**: O11 allows testing SQL in Service Studio. ODC requires deployment to test. Always validate syntax for the target platform.
269
+ 5. **Reserved Words**: `Order`, `User`, `Group`, `Table` are reserved in PostgreSQL. In ODC, always double-quote these entity names.
270
+ 6. **Date Comparisons**: O11 uses `BETWEEN` or `DATEDIFF`. ODC prefers range comparisons with `>=` and `<` or `EXTRACT()`.
271
+ 7. **Aggregate Functions in WHERE**: Use `HAVING` for aggregate conditions — `WHERE` runs before `GROUP BY`.
272
+ 8. **Index Awareness**: Filter on indexed attributes when possible. In O11 check Query Analyzer; in ODC check the database logs.
@@ -0,0 +1,237 @@
1
+ ---
2
+ name: outsystems-ui
3
+ description: >
4
+ Build OutSystems UI screens using the official pattern library and utility-first
5
+ CSS classes. Use when creating .visual.html prototypes, styling components, using
6
+ layout patterns (Cards, Columns, Forms, Tables, Tabs), applying spacing, colors,
7
+ typography, or scaffolding screens — even if the user doesn't mention "OutSystems"
8
+ explicitly. Covers all 87 UI patterns across 7 categories, 16 core widgets, and
9
+ the complete design token system (spacing, colors, borders, shadows, typography).
10
+ compatibility: Requires outsystems-ui.css linked in the HTML file. Designed for VS Code agents.
11
+ metadata:
12
+ version: "1.0"
13
+ source: "OutSystems UI Cheat Sheet"
14
+ ---
15
+
16
+ # OutSystems UI — Vibe Coding Skill
17
+
18
+ Build pixel-perfect OutSystems-compatible `.visual.html` prototypes using only the official OSUI pattern library and utility classes. Every class and CSS variable below comes directly from the OutSystems UI Cheat Sheet.
19
+
20
+ ## General Rules
21
+
22
+ 1. **Utility-first styling** — use OSUI utility classes (`.padding-m`, `.text-bold`, `.background-primary`). Never use raw CSS properties or inline `style=""` attributes.
23
+ 2. **12-column grid** — use `.columns2` through `.columns6` for responsive layouts. These auto-stack on mobile — do not add custom media queries.
24
+ 3. **No external JavaScript** — all interaction patterns are CSS/class-driven.
25
+ 4. **Layout Wrapper required** — every screen must be wrapped in:
26
+ ```html
27
+ <div class="layout active-screen">
28
+ <!-- header, content, footer -->
29
+ </div>
30
+ ```
31
+ The `.active-screen` class is REQUIRED or utility classes and CSS variables will not resolve.
32
+ 5. **Strip platform IDs** — never include `os-internal-id` or similar platform-generated attributes.
33
+ 6. **Widget slots** — use `{{content}}` placeholders in templates where nested widgets would go.
34
+ 7. **Base template** — see [assets/layout-template.html](assets/layout-template.html) for the starting scaffold.
35
+
36
+ ## Buttons
37
+
38
+ From the Cheat Sheet. Buttons are the most commonly used widget.
39
+
40
+ ### Types
41
+
42
+ | Visual | Classes |
43
+ |--------|---------|
44
+ | Secondary (default) | `.btn` |
45
+ | Primary | `.btn .btn-primary` |
46
+ | Cancel | `.btn .btn-cancel` |
47
+ | Success | `.btn .btn-success` |
48
+ | Error | `.btn .btn-error` |
49
+
50
+ ### Sizes
51
+
52
+ | Size | Classes |
53
+ |------|---------|
54
+ | Small | `.btn .btn-small` |
55
+ | Default | `.btn` |
56
+ | Large | `.btn .btn-large` |
57
+
58
+ ### Shapes
59
+
60
+ Combine any button type/size with a border-radius class:
61
+
62
+ | Shape | Add class |
63
+ |-------|-----------|
64
+ | None (square) | `.border-radius-none` |
65
+ | Soft | `.border-radius-soft` |
66
+ | Rounded | `.border-radius-rounded` |
67
+ | Circle | `.border-radius-circle` |
68
+
69
+ ### Loading State
70
+
71
+ Add `.btn-loading` to the button and include a spinner element inside. This is CSS-driven, not JavaScript.
72
+
73
+ ```html
74
+ <button class="btn btn-primary btn-loading">
75
+ <span class="btn-loading-spinner"></span>
76
+ Loading...
77
+ </button>
78
+ ```
79
+
80
+ ## Borders
81
+
82
+ ### Border Radius
83
+
84
+ | Size | Value | Class | CSS Variable |
85
+ |------|-------|-------|--------------|
86
+ | None | 0 | `.border-radius-none` | `--border-radius-none` |
87
+ | Soft | 4px | `.border-radius-soft` | `--border-radius-soft` |
88
+ | Rounded | 100px | `.border-radius-rounded` | `--border-radius-rounded` |
89
+ | Circle | 100% | `.border-radius-circle` | `--border-radius-circle` |
90
+
91
+ ### Border Sizes
92
+
93
+ | Size | Value | Class | CSS Variable |
94
+ |------|-------|-------|--------------|
95
+ | None | 0 | `.border-size-none` | `--border-size-none` |
96
+ | S | 1px | `.border-size-s` | `--border-size-s` |
97
+ | M | 2px | `.border-size-m` | `--border-size-m` |
98
+ | L | 3px | `.border-size-l` | `--border-size-l` |
99
+
100
+ ## Spacing
101
+
102
+ 8px base scale. Every spacing utility has a corresponding CSS variable.
103
+
104
+ | Size | Value | Padding Class | Margin Class | CSS Variable |
105
+ |------|-------|---------------|--------------|--------------|
106
+ | None | 0 | `.padding-none` | `.margin-none` | `--space-none` |
107
+ | XS | 4px | `.padding-xs` | `.margin-xs` | `--space-xs` |
108
+ | S | 8px | `.padding-s` | `.margin-s` | `--space-s` |
109
+ | Base | 16px | `.padding-base` | `.margin-base` | `--space-base` |
110
+ | M | 24px | `.padding-m` | `.margin-m` | `--space-m` |
111
+ | L | 32px | `.padding-l` | `.margin-l` | `--space-l` |
112
+ | XL | 40px | `.padding-xl` | `.margin-xl` | `--space-xl` |
113
+ | XXL | 48px | `.padding-xxl` | `.margin-xxl` | `--space-xxl` |
114
+
115
+ ### Directional Variants
116
+
117
+ Append direction to the class for single-side or axis spacing:
118
+
119
+ - **Single side**: `.padding-top-m`, `.padding-right-s`, `.padding-bottom-l`, `.padding-left-base`
120
+ - **Axis**: `.padding-vertical-m` (top + bottom), `.padding-horizontal-s` (left + right)
121
+ - Same pattern for `.margin-*` variants.
122
+
123
+ ## Typography
124
+
125
+ ### Font Sizes
126
+
127
+ | Name | Value | Class | CSS Variable |
128
+ |------|-------|-------|--------------|
129
+ | Display | 34px | `.font-size-display` | `--font-size-display` |
130
+ | H1 | 30px | `.font-size-h1` | `--font-size-h1` |
131
+ | H2 | 26px | `.font-size-h2` | `--font-size-h2` |
132
+ | H3 | 24px | `.font-size-h3` | `--font-size-h3` |
133
+ | H4 | 20px | `.font-size-h4` | `--font-size-h4` |
134
+ | H5 | 18px | `.font-size-h5` | `--font-size-h5` |
135
+ | H6 | 17px | `.font-size-h6` | `--font-size-h6` |
136
+ | Base (body) | 16px | `.font-size-base` | `--font-size-base` |
137
+ | S (body small) | 14px | `.font-size-s` | `--font-size-s` |
138
+ | XS (body extra small) | 12px | `.font-size-xs` | `--font-size-xs` |
139
+
140
+ ### Font Weights
141
+
142
+ | Weight | Value | Class |
143
+ |--------|-------|-------|
144
+ | Light | 300 | `.font-weight-light` |
145
+ | Normal | 400 | `.font-weight-normal` |
146
+ | Semi-Bold | 600 | `.font-weight-semi-bold` |
147
+ | Bold | 700 | `.font-weight-bold` |
148
+
149
+ ### Text Transforms
150
+
151
+ | Transform | Class |
152
+ |-----------|-------|
153
+ | Lowercase | `.text-lowercase` |
154
+ | Uppercase | `.text-uppercase` |
155
+ | Capitalize | `.text-capitalize` |
156
+ | Ellipsis overflow | `.text-ellipsis` |
157
+
158
+ ## Shadows
159
+
160
+ | Level | Class | CSS Variable |
161
+ |-------|-------|--------------|
162
+ | None | `.shadow-none` | `--shadow-none` |
163
+ | XS | `.shadow-xs` | `--shadow-xs` |
164
+ | S | `.shadow-s` | `--shadow-s` |
165
+ | M | `.shadow-m` | `--shadow-m` |
166
+ | L | `.shadow-l` | `--shadow-l` |
167
+ | XL | `.shadow-xl` | `--shadow-xl` |
168
+
169
+ ## Colors — Quick Reference
170
+
171
+ Most-used palette entries. Load [references/colors.md](references/colors.md) for the full extended + neutral palettes and all CSS variables.
172
+
173
+ ### Brand Colors
174
+
175
+ | Name | Hex | Class (bg) | Class (text) | CSS Variable |
176
+ |------|-----|------------|--------------|--------------|
177
+ | Primary | #1068EB | `.background-primary` | `.text-primary` | `--color-primary` |
178
+ | Secondary | #303D60 | `.background-secondary` | `.text-secondary` | `--color-secondary` |
179
+
180
+ ### Semantic Colors
181
+
182
+ | Name | Class (bg) | Class (text) | CSS Variable |
183
+ |------|------------|--------------|--------------|
184
+ | Info | `.background-info` | `.text-info` | `--color-info` |
185
+ | Success | `.background-success` | `.text-success` | `--color-success` |
186
+ | Warning | `.background-warning` | `.text-warning` | `--color-warning` |
187
+ | Error | `.background-error` | `.text-error` | `--color-error` |
188
+
189
+ ## UI Pattern Categories
190
+
191
+ OutSystems UI includes 87 patterns across 7 categories plus 16 core widgets. Load the appropriate reference file when working with patterns in that category.
192
+
193
+ | Category | Count | When to load |
194
+ |----------|-------|--------------|
195
+ | Adaptive | 12 | Load [references/patterns-adaptive.md](references/patterns-adaptive.md) if the user mentions columns, gallery, grid, responsive, Master-Detail, or multi-column layout |
196
+ | Content | 16 | Load [references/patterns-content.md](references/patterns-content.md) if the user mentions Card, Accordion, Alert, Tag, Tooltip, Section, Blank Slate, or content display |
197
+ | Interaction | 18 | Load [references/patterns-interaction.md](references/patterns-interaction.md) if the user mentions Carousel, DatePicker, Sidebar, Search, Notification, drag, modal, or interactive elements |
198
+ | Navigation | 9 | Load [references/patterns-navigation.md](references/patterns-navigation.md) if the user mentions Breadcrumb, Tabs, Pagination, Wizard, Timeline, or navigation |
199
+ | Numbers | 6 | Load [references/patterns-numbers.md](references/patterns-numbers.md) if the user mentions Badge, Counter, Progress Bar, Progress Circle, Rating, or numeric display |
200
+ | Utilities | 9 | Load [references/patterns-utilities.md](references/patterns-utilities.md) if the user mentions centering, separator, swipe, touch, Inline SVG, or alignment helpers |
201
+ | Widgets | 16 | Load [references/widgets.md](references/widgets.md) if the user mentions form, table, checkbox, dropdown, switch, upload, popup, radio, or input widget |
202
+
203
+ For complete screen scaffolds (Dashboard, List/Detail, Form, Login, etc.), load [references/screen-templates.md](references/screen-templates.md).
204
+
205
+ ## Pattern-Scoped CSS Variables
206
+
207
+ Some patterns expose CSS custom properties for fine-tuning. Set these on the pattern's root element.
208
+
209
+ | Pattern | CSS Variables |
210
+ |---------|-------------|
211
+ | Carousel | `--{element-id}-width` |
212
+ | Floating Actions | `--delay` |
213
+ | Master Detail | `--master-detail-height`, `--left-percentage: 50` |
214
+ | Gallery | `--grid-desktop: 4`, `--grid-tablet: 2`, `--grid-phone: 1`, `--grid-gap: var(--space-base)` |
215
+ | Rating | `--rating-size: 16px` |
216
+ | Scrollable Area | `--scrollable-area-width`, `--scrollable-area-height` |
217
+
218
+ ## Validation
219
+
220
+ After generating a `.visual.html` file, verify:
221
+ 1. The root `<div>` has class `layout active-screen`
222
+ 2. No inline `style=""` attributes exist anywhere in the file
223
+ 3. All classes used are from the OSUI cheat sheet — no custom CSS class names
224
+ 4. The OSUI stylesheet `<link>` is present in `<head>`
225
+ 5. No `@media` queries or custom breakpoints were added
226
+
227
+ If any check fails, fix the issue before presenting the output.
228
+
229
+ ## Gotchas
230
+
231
+ - `.active-screen` class is **REQUIRED** on the layout wrapper `<div>`. Without it, utility classes and CSS variables will NOT resolve correctly.
232
+ - OutSystems pattern previews render inside iframes — CSS resolves against the OSUI framework, not browser defaults. Your `.visual.html` must link the OSUI stylesheet.
233
+ - **Never mix** inline `style=""` attributes with utility classes. Pick one approach — always prefer utility classes.
234
+ - `.columns*` patterns auto-stack on mobile breakpoints. Do NOT add custom `@media` queries to override this behavior.
235
+ - Button loading state is purely CSS (`.btn-loading` + spinner element), not a JavaScript toggle.
236
+ - Use `{{content}}` placeholders in component templates to indicate where nested child widgets go.
237
+ - Always test your prototype with the OSUI CSS linked — plain browser rendering will look wrong.
@@ -0,0 +1,43 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>{{screen-name}} — OutSystems Visual Prototype</title>
7
+ <!--
8
+ OutSystems UI CSS Framework
9
+ This stylesheet provides all OSUI utility classes, pattern styles,
10
+ and CSS variables used in this prototype.
11
+ -->
12
+ <link rel="stylesheet" href="../theme/outsystemsui.css" />
13
+ <style>
14
+ /* Only add overrides here if absolutely necessary.
15
+ Prefer OSUI utility classes over custom CSS. */
16
+ </style>
17
+ </head>
18
+ <body>
19
+ <!--
20
+ Layout Wrapper
21
+ The .active-screen class is REQUIRED for OSUI utility classes
22
+ and CSS variables to resolve correctly.
23
+ -->
24
+ <div class="layout active-screen">
25
+
26
+ <!-- Header -->
27
+ <header class="header padding-base">
28
+ <h1 class="font-size-h2 margin-bottom-none">{{screen-title}}</h1>
29
+ </header>
30
+
31
+ <!-- Main Content -->
32
+ <main class="main-content padding-base">
33
+ {{content}}
34
+ </main>
35
+
36
+ <!-- Footer (optional) -->
37
+ <footer class="footer padding-base">
38
+ {{footer}}
39
+ </footer>
40
+
41
+ </div>
42
+ </body>
43
+ </html>