OutSystems lets you build full-stack web apps visually with no hand-written code. In Service Studio, create an Entity (database table), generate a screen from it, and publish with 1-Click Publish. Your first working app — with a list, form, and save logic — takes under 30 minutes.
What You Will Build
This tutorial walks you through building a simple Task Manager app — a classic first project that touches every layer of OutSystems: data model, user interface, and server logic. You will create a Task entity with title, description, and due date fields; generate a list screen and a detail/edit screen automatically; wire up a Save button to a Server Action; and publish to a live URL in one click. No code is required. Everything happens inside Service Studio's visual editor.
Prerequisites
- Service Studio installed (download free from outsystems.com/downloads/)
- A free OutSystems Personal Environment — sign up at outsystems.com/free-edition/
- Logged in to Service Studio and connected to your Personal Environment
Step-by-step guide
Create a New Reactive Web Application
Create a New Reactive Web Application
Open Service Studio. On the home screen click 'New Application'. In the dialog select 'Reactive Web App' and click 'Next'. Enter the name 'TaskManager' and choose a color/icon. Click 'Create App'. Service Studio creates a blank application with a default module. You are now inside the Service Studio IDE with the Interface, Logic, Data, and Processes tabs visible on the right side panel.
Expected result: The Service Studio IDE opens with a new blank Reactive Web module named 'TaskManager'. The right panel shows Interface, Logic, Data, and Processes tabs.
Create the Task Entity in the Data Tab
Create the Task Entity in the Data Tab
Click the 'Data' tab in the right panel. Expand 'Entities' → 'Database'. Right-click 'Database' → 'Add Entity'. Name it 'Task' and press Enter. An 'Id' attribute is auto-created as the primary key (Long Integer, auto-increment). Now add attributes: right-click the 'Task' entity → 'Add Entity Attribute'. Name it 'Title' (Data Type: Text, Mandatory: Yes). Repeat to add 'Description' (Text, Mandatory: No), 'DueDate' (Date, Mandatory: No), and 'IsComplete' (Boolean, Mandatory: Yes, Default: False). After adding all attributes, check the TrueChange tab at the bottom — it should show zero errors.
1/* Entity: Task2 Attributes:3 - Id Long Integer (auto, PK)4 - Title Text Mandatory5 - Description Text6 - DueDate Date7 - IsComplete Boolean Default: False8*/Expected result: The Task entity appears under Data tab → Entities → Database with five attributes. TrueChange tab shows 0 errors.
Scaffold Screens from the Entity
Scaffold Screens from the Entity
Click the 'Interface' tab in the right panel. Expand 'UI Flows' → 'MainFlow'. Now drag the 'Task' entity from the Data tab directly onto the 'MainFlow' node in the Interface tab. Service Studio displays a dialog asking which screens to generate. Select both 'Tasks' (list screen) and 'TaskDetail' (form screen for create/edit), then click 'Create Screens'. OutSystems auto-generates: a Tasks list screen with a Table widget pre-bound to a GetTasks Aggregate, and a TaskDetail screen with Input widgets pre-bound to each attribute and a Save button.
Expected result: Two screens appear under Interface tab → UI Flows → MainFlow: 'Tasks' and 'TaskDetail'. Both are fully scaffolded with widgets, aggregates, and save logic pre-generated.
Review and Verify the Save Logic
Review and Verify the Save Logic
In the Interface tab, expand 'MainFlow' → 'TaskDetail'. Double-click the 'SaveTask' Client Action (shown in the screen's action list). The action flow opens in the center editor. Trace the flow: Start → If(Form.Valid) → [True] CreateOrUpdateTask (Server Action call) → If(CreateOrUpdateTask.Success) → [True] Navigate to Tasks screen → [False] Message 'Error saving'. The form validation and database write are already wired. The Server Action 'CreateOrUpdateTask' lives under Logic tab → Server Actions — double-click it to see: Start → CreateOrUpdate<Task> (Entity Action) → Assign Success = True → End.
Expected result: You can trace the complete save flow from button click → validation → database write → navigation without any missing connections. TrueChange shows 0 errors.
Add a Navigation Button on the List Screen
Add a Navigation Button on the List Screen
Double-click the 'Tasks' screen to open it in the Screen Editor. In the Toolbox (left panel), drag a 'Button' widget onto the screen above the table. In the Properties panel (right side), set Label to 'New Task'. With the button selected, click the 'Events' section in Properties → 'OnClick' → 'New Client Action'. In the action flow editor that opens, drag a 'Navigate' element from the Toolbox. Set Destination to 'TaskDetail'. In the input parameter 'TaskId', set value to 'NullIdentifier()' (this tells the form to create a new record). Connect Navigate to End.
1/* Navigation action flow:2 Start3 → Navigate(Destination: TaskDetail, TaskId: NullIdentifier())4 → End5*/Expected result: The Tasks screen has a 'New Task' button in the Screen Editor. Clicking it in the running app will open the TaskDetail form with empty fields.
Publish and Open the App
Publish and Open the App
Click the large '1-Click Publish' button at the top center of Service Studio. The 1-Click Publish tab at the bottom shows three stages: Upload → Compile → Deploy. Wait for all three stages to show a green checkmark (typically 20-60 seconds). When complete, the button changes to 'Open in Browser' (blue). Click 'Open in Browser'. Your Task Manager app opens in a new browser tab at your Personal Environment URL. You will see the Tasks list screen. Click 'New Task' to open the form, fill in a title, and click Save — the task appears in the list.
Expected result: The app opens at a URL like https://yourenvironment.outsystemscloud.com/TaskManager/. You can create, view, and save tasks. The list updates immediately after saving.
Complete working example
1/* Server Action: CreateOrUpdateTask2 Input Parameters:3 - TaskRecord : Task45 Output Parameters:6 - Success : Boolean7 - ErrorMessage : Text89 Action Flow:10 Start11 → CreateOrUpdateTask(SourceRecord: TaskRecord)12 [On Exception: Database Exception]13 → Assign14 ErrorMessage = "Database error. Please try again."15 Success = False16 → End17 → Assign18 Success = True19 → End20*/2122/* Expression examples used on the Tasks screen:2324 Display due date with formatting:25 If(Task.DueDate = NullDate(), "No due date", FormatDate(Task.DueDate, "MMM dd, yyyy"))2627 Completion status badge:28 If(Task.IsComplete, "Complete", "Pending")2930 Days until due:31 If(Task.DueDate > CurrDate(),32 IntegerToText(DiffDays(CurrDate(), Task.DueDate)) + " days left",33 "Overdue")34*/Common mistakes
Why it's a problem: Setting attribute Length to 50 (default) for user-visible text fields like names and titles
How to avoid: Right-click the attribute → Edit → set Length to at least 200 for names/titles, 2000 for descriptions. The default 50-character limit causes silent truncation.
Why it's a problem: Accessing Aggregate.List.Current.Task without checking if the list is empty first
How to avoid: Always add an If check: If(GetTasks.List.Empty, show empty state, show list). Accessing .Current on an empty list throws a runtime error.
Why it's a problem: Trying to navigate to a screen from inside a Server Action
How to avoid: Server Actions run on the server and cannot control browser navigation. Put navigation logic in a Client Action that calls the Server Action first, then navigates.
Why it's a problem: Forgetting to refresh the Aggregate after saving data — the list shows stale data
How to avoid: After the Server Action call in the save flow, call 'Refresh Data' on the screen's Aggregate (right-click Aggregate on screen → 'Refresh'). This re-fetches from the database.
Best practices
- Always check the TrueChange tab before clicking 1-Click Publish — zero errors means a clean publish
- Set Max Records on every Aggregate to limit database load (e.g., Max Records: 50 for list screens)
- Use CreateOrUpdate<Entity> instead of separate Create/Update logic — it handles both cases with one action
- Store sensitive configuration (API URLs, credentials) in Site Properties (Data tab → Site Properties), not hardcoded in expressions
- Name your screens and actions clearly: 'SaveTask', 'GetActiveTasks' — OutSystems auto-propagates renames via TrueChange
- Use NullIdentifier() to distinguish 'create new' from 'edit existing' when passing IDs between screens
- Publish often during development — frequent small publishes are faster to debug than one large publish
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I am building my first OutSystems Reactive Web app. I have created a Task entity with Title (Text), Description (Text), DueDate (Date), and IsComplete (Boolean) attributes. I scaffolded a list screen and a form screen. Explain how the SaveTask action flow works — specifically the If(Form.Valid) check, the CreateOrUpdateTask server action, and the navigation back to the list. Also explain what NullIdentifier() does when passed as the TaskId input parameter.
In Service Studio, I have scaffolded screens from my Task entity. Review my SaveTask Client Action flow and check: (1) Is Form.Valid being checked before the Server Action call? (2) Is the Aggregate being refreshed after save? (3) Is error handling present for the Database Exception? Suggest improvements using OutSystems best practices.
Frequently asked questions
Do I need to know how to code to use OutSystems?
No. This tutorial builds a complete app without writing a single line of code. OutSystems generates .NET and SQL automatically from your visual definitions. You may eventually want to write expressions (OutSystems has its own expression language) or JavaScript for advanced UI effects, but basic apps require zero coding.
Is the Personal Edition really free and can I use it for production?
The Personal Edition is free forever with no credit card required. However, it is intended for learning and development only — it is limited to a single environment, up to 100 internal end-users, and does not include SLA guarantees. For production apps serving real users, you need a paid OutSystems license.
What happens to my app data when I republish?
1-Click Publish is safe for data. It deploys new code without wiping database records. The exception is when you delete an entity attribute — OutSystems will warn you that the column will be removed from the database. Always read the TrueChange and publish warning dialogs before confirming a breaking schema change.
Can I build mobile apps the same way?
Very similarly, yes. When creating a new application, choose 'Mobile App' instead of 'Reactive Web App'. The IDE experience is nearly identical. The same entities, server actions, and aggregates work across both. Mobile apps compile to native iOS and Android packages via MABS (Mobile Application Build Service).
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation