Create Application
This guide provides an overview of initial setup, covering the frontend, database, and API service. We will create a new fullstack application quickly and practically.
Introduction
Although the platform is polyglot and supports multiple programming languages, we will focus exclusively on using JavaScript in this tutorial. As a result, we will create a practical application consisting of a form displayed in a modal window (pop-up) with data export to PDF functionality.
Prerequisites
Before starting, make sure you have:
-
The Netuno platform previously installed on your machine. If you have questions about this step, see the Platform Installation guide.
-
Access to the terminal or command prompt of the development environment.
Create a New Application
Follow the instructions below to initialize your new application:
Open the terminal and navigate to the root folder where Netuno was installed.
Run the application creation command:
./netuno app
Creation with Parameter
You can define the application name directly when running the command, for example:
./netuno app name=my_application
When defining your application name, avoid using spaces, accents, or special characters. Prefer using lowercase letters separated by hyphens or underscores (example: app-sales or hr_management) to maintain compatibility with URLs and system folders.
Initial Configuration
The command-line wizard will ask a few questions to configure your project. Provide:
- Application name: Your project identifier.
- Database type: The database management system that will be used.
- Language: The default language of your application interface.
Database Recommendation for Beginners
During the step-by-step process, when prompted for the database type, we recommend choosing the H2 Database option.
The H2 Database is an embedded database that is already integrated into the Netuno server. The great advantage is that it does not require installing or configuring external servers (such as PostgreSQL or MySQL), making initial development and testing much more practical and faster.
Command to Start the Server
After creating your new application, start the Netuno platform server. This will make your project accessible in the browser and ready for continuous development.
Run the command below in your terminal and wait for startup.
./netuno server app=my_application
When passing the app=my_application parameter, the server understands that this will be the default application to run in this instance. With the server running, you can start editing your project.
All files and source code for your application are stored and organized inside the 📂 apps/myapp folder.
When accessing your application's Backoffice administration interface for the first time, the system will request authentication. For local development environments, use the following default credentials:
User: dev
Password: dev
We recommend changing these credentials when moving your application to a production environment.
Code Editor
To ensure the best development experience, we suggest using modern, lightweight code editors with a good extension ecosystem.
If you don't yet have a favorite editor, we recommend the following free and widely used community options:
- VS Codium: vscodium.com
- VS Code: code.visualstudio.com
- WebStorm: jetbrains.com/webstorm
Note: If you prefer more robust tools and don't mind investing in licenses, JetBrains WebStorm is an excellent premium option.
Open the application folder in your editor:
📂 apps/my_application
All application files are stored and organized inside this folder. All development, route creation, database logic, and visual interfaces will happen inside this folder.
To know exactly where to create each type of file and how Netuno organizes the backend and frontend, we recommend reading the detailed documentation about the application folder structure:
See the guide: Application Folders
Summary of Steps
With the initial Netuno knowledge consolidated, we will apply these concepts in practice by creating a complete feature, from start to finish.
The practical goal is to add two new interactive components to the interface:
- A button responsible for loading and displaying the customer form inside a floating window (Modal).
- A button dedicated to generating and exporting the list of registered customers to a PDF file.
To achieve this result with organization and clarity, we divided development into a logical sequence of steps. We will follow this roadmap:
-
Interface Mapping: Analyze the application folder structure to locate where the main dashboard HTML is defined.
-
React Integration: Configure and add the base of the two new buttons using the React framework in the frontend.
-
Modal Logic: Build and program the button behavior to correctly open the customer form.
-
Export Interface: Build and position the button that will trigger the PDF file download in the interface.
-
Service Development (API): Program the backend by creating the service that will read the data and dynamically generate the PDF file containing the customer list.
Let's get started!
Dashboard Template
Navigate to the server/templates folder and open the file responsible for providing the HTML for the dashboard screen.
server/templates/dashboard.html
When exploring the code in the dashboard.html file, scroll to the bottom of the page. You will find an isolated <div> element. This is exactly the point where the Netuno platform "injects" and starts all the interactive interface built in React.
...
<div id="app-dashboard"></div>
Although the HTML skeleton stays in the server/templates folder, the actual interface development and visual logic do not happen there.
To change the dashboard behavior or add new components with React, you must access the folder dedicated to frontend development.
It is in this 📂 ui/ folder that you will find the dashboard components and can develop the new visual features of your application.
Create Form
In this step, we will create the database structure necessary for this tutorial: a form called Customer containing a text field called Name.
- In the Backoffice, access the development area by clicking the Build button (top right).
- In the side menu, navigate to Management > Forms and create the new form with the Title: Customer.
- Click Save.
The table name will be automatically filled with customer (keep it lowercase, as recommended for databases).
If you have questions about the advanced settings on this screen, see the complete documentation in Forms.
Create Field
With the form created, it will appear in the left side menu under the Fields category.
- Click Customer to add a new column:
- Enter the text "Name" in the Field Title.
- Select the data type as "text" in the Type field.
- Check the Allow Filtering (to enable search) and Show in Result (to appear in the table) options.
- Click Save.
To understand all available data types and their properties, access the detailed documentation in Fields.
Insert Test Data
So that we can test PDF export in the next steps, we need real data in the system.
- Click the Preview button (top right) to return to the application's Backoffice.
- Access the newly created Customer menu on the side.
- Use the + Add button to register some test customers in the system.
- Click Save.
Query the Database
Netuno offers an integrated tool that allows you to run SQL commands directly on your application's database. This is essential for quickly running queries, validating information, or manipulating system data efficiently.
To access the query interface and run your commands, follow the steps below:
- In the main interface, access the development area by clicking the Build button.
- In the side navigation menu, locate the Management section.
- Click the Query option to open the database console.
- In the text editor that appears on the screen, type the SQL command you want to run.
- Confirm the command execution.
Run the command below to query registered customers:
SELECT * FROM customer
When you finish the queries and want to return to the system's user interface (backoffice), simply click the Preview button.
Add Buttons with React
In this step, we will configure the main dashboard file to display two new buttons.
In the interface architecture, we use the concept of Containers to define broad areas of the system, which encompass larger features and group multiple smaller components.
-
In your code editor, navigate to the containers folder at
📂 ui/src/containers. -
Locate and open the main dashboard file:
📂 DashboardContainer/index.jsx. -
Insert the import and rendering code for the components as in the example below.
import { Space } from 'antd';
import CustomerModalButton from '../../components/CustomerModalButton';
import PDFButton from '../../components/PDFButton';
import "./index.less";
function DashboardContainer() {
return (
<div className="my-dashboard">
<Space>
<CustomerModalButton />
<PDFButton />
</Space>
</div>
);
}
export default DashboardContainer;
Note that these button files do not yet physically exist in your project. Since they are smaller reusable components, we will create them inside the dedicated components folder.
Always keep the separation between Containers (broad-scope areas, such as entire pages or dashboards) and Components (isolated interface elements, such as buttons and modals). This makes your Netuno code much cleaner, easier to maintain, and scalable.
Form Button
Access the ui/src/components/ folder and create a new folder named CustomerModalButton.
Inside the CustomerModalButton folder, create the component's main file named index.jsx.
📂 ui/src/components/CustomerModalButton/index.jsx
Open the file and insert the code below:
import { Button } from 'antd';
function CustomerModalButton() {
const onClick = () => {
netuno.modal.create({
name: 'customer',
callback: function (modal) {
let form = modal.find('[netuno-form]');
form.on('netuno:new', () => {
console.log('Creating a new Customer.');
});
form.on('netuno:save', () => {
netuno.modal.hide(modal)
console.log('Saved a Customer.');
});
form.on('netuno:delete', () => {
netuno.modal.hide(modal)
console.log('Removed a Customer');
});
form.on('netuno:back', () => {
console.log('Clicked back');
});
netuno.loadForm(form);
netuno.modal.show(modal);
}
});
};
return (
<div>
<Button type="primary" onClick={ onClick }>
Open Customer Form
</Button>
</div>
);
}
export default CustomerModalButton;
Understanding the Code
The magic of this component happens inside the onClick function, which uses Netuno's global interface tools:
-
netuno.modal.create(): This method is responsible for instantiating the modal window on the screen and linking the desired form to it (in this case, the form named customer).
-
Form Events (form.on): The callback block allows us to "listen" to user actions. We can trigger custom actions when the user creates a record (netuno:new), saves (netuno:save), deletes (netuno:delete), or clicks back (netuno:back).
-
netuno.modal.hide() / show(): Methods used to hide the modal after a successful action or display it as soon as the form is loaded.
Now that the CustomerModalButton component has been created successfully, the import we made earlier in your DashboardContainer will work without errors, and the button should already be rendered on your screen!
PDF Export Button
In this step, we will create the Dashboard's second button: the PDF Export Button.
The main role of this component in the interface is to act as a trigger; that is, when clicked, it will make a request to a backend service responsible for processing the system data and generating the PDF file containing the list of registered customers.
-
Access the
ui/src/components/folder and create a new folder named PDFButton. -
Create a file named index.jsx inside the folder.
ui/src/components/PDFButton/index.jsx
Open the file and insert the code below:
import { Button } from 'antd';
function PDFButton() {
return (
<div>
<Button
type="primary"
href="/services/customer/export-pdf"
target="blank">
Export PDF
</Button>
</div>
);
}
export default PDFButton;
With the creation of the PDFButton component, both buttons declared in your DashboardContainer are ready.
The visual structure and components are complete. Compile the frontend to test the interface rendering.
Building the backend service that will actually generate the PDF will be covered in the next step.
Compile Frontend
Internet browsers do not natively understand code written in React, .jsx or .tsx files, or CSS preprocessors such as .less. For your interface to work correctly, it must go through a compilation (build) process. This process translates, bundles, and optimizes all your code into final static files (standard JavaScript and CSS) that the browser can process with maximum efficiency.
Prerequisites
Before starting compilation, make sure that:
-
You have the terminal or command prompt open in your development environment.
-
The
Bunpackage manager is correctly installed on your system.
Compilation Examples
Netuno provides different commands depending on your development stage. From the Netuno root folder, navigate to your application's ui folder.
Run the commands inside your application's interface folder: 📂 apps/myapp/ui
Production Compilation
Performs the complete and optimized compilation of files. It is the ideal command when you finish developing a screen or component and want to generate final lightweight files with better performance.
bun run build
Development Compilation
The watch command performs a quick compilation and keeps watching the folder. Whenever you save a file in your editor, the terminal automatically runs compilation.
bun run watch
Regardless of the command used, build or watch, changes do not appear instantly on the user's screen. Refresh the backoffice page in your browser to load the newly generated files.
During development, errors can occur at two different stages. Know where to look for them:
-
Compilation Errors: Syntax failures in React code or undeclared variables will be presented directly in your terminal, where the bun command is running.
-
Runtime Errors: Failures that occur while using the application will be presented in the browser console. Always remember to inspect the page to check for any warning or error.
Integrated Compilation
The integrated compilation feature allows you to run terminal commands automatically together with server startup. This optimizes the workflow by consolidating all logs and monitoring into a single central terminal.
To enable integrated compilation, you need to modify your application's development settings:
-
Access your application's root folder.
-
Open the development configuration file:
_development.json. -
Locate the code block referring to "commands".
-
Change the value of the "enabled" property from false to true.
-
Save the file.
Your _development.json file should have a structure similar to this:
...
"commands": [{
"command": "bun run watch",
"enabled": true,
"install": "bun install",
"path": "ui"
}],
...
For Netuno to read the updated file and apply the new configuration, you need to restart the server:
-
Go to the terminal where the Netuno server is running.
-
Stop the process by pressing CTRL + C simultaneously.
-
Start the server again, indicating your application name:
./netuno server app=myapp
After restarting the server, observe the logs in the terminal. You will notice that Netuno is now automatically running the frontend compilation commands bun run watch in the background. From now on, everything works integrated in the same window.
API Service to Generate PDF
In the previous step, we configured the Export PDF button in the frontend with the "href" attribute pointing to the address services/customer/export-pdf. However, if you click it now, nothing will happen. This occurs because the API service responsible for generating the file does not yet exist.
All API development takes place inside the 📂 server folder.
In this section, we will create the script that fetches records from the database and visually builds the PDF document.
Prerequisites
- Having created the PDFButton component in the frontend pointing to the correct URL.
- Having the Netuno server running.
Netuno automatically routes your API URLs based on the folder structure inside server/services/. To create the service, follow the steps:
-
Navigate to the backend services folder:
server/services/. Create a folder named customer. -
Inside this folder, create a file named
export-pdf.js.
Netuno is polyglot. We will use JavaScript in this example; use the extension corresponding to your preferred language.
Open the file and insert the code below to generate your PDF structure:
- JavaScript
- TypeScript
- Python
- Ruby
- Kotlin
- Groovy
server/services/customer/export-pdf.js
server/services/customer/export-pdf.ts
server/services/customer/export-pdf.py
server/services/customer/export-pdf.rb
server/services/customer/export-pdf.kts
server/services/customer/export-pdf.groovy
- JavaScript
- TypeScript
- Python
- Ruby
- Kotlin
- Groovy
_header.contentType("pdf")
const pdfDocument = _pdf.newDocument(_pdf.pageSize("A5"))
pdfDocument.add(
_pdf.paragraph("Customer List:")
.setFontSize(16)
.setFontColor(_pdf.color("#1abc9c"))
)
const dbCustomers = _db.form("customer").all()
for (const dbCustomer of dbCustomers) {
pdfDocument.add(
_pdf.paragraph(dbCustomer.getString("name"))
.setFontSize(12)
.setFontColor(_pdf.color("#748dae"))
)
}
pdfDocument.close()
_header.contentType("pdf")
const pdfDocument = _pdf.newDocument(_pdf.pageSize("A5"))
pdfDocument.add(
_pdf.paragraph("Customer List:")
.setFontSize(16)
.setFontColor(_pdf.color("#1abc9c"))
)
const dbCustomers = _db.form("customer").all()
for (const dbCustomer of dbCustomers) {
pdfDocument.add(
_pdf.paragraph(dbCustomer.getString("name"))
.setFontSize(12)
.setFontColor(_pdf.color("#748dae"))
)
}
pdfDocument.close()
_header.contentType("pdf")
pdfDocument = _pdf.newDocument(_pdf.pageSize("A5"))
pdfDocument.add(
_pdf.paragraph("Customer List:")
.setFontSize(16)
.setFontColor(_pdf.color("#1abc9c"))
)
dbCustomers = _db.form("customer").all()
for dbCustomer in dbCustomers:
pdfDocument.add(
_pdf.paragraph(dbCustomer.getString("name"))
.setFontSize(12)
.setFontColor(_pdf.color("#748dae"))
)
pdfDocument.close()
_header.contentType("pdf")
pdfDocument = _pdf.newDocument(_pdf.pageSize("A5"))
pdfDocument.add(
_pdf.paragraph("Customer List:")
.setFontSize(16)
.setFontColor(_pdf.color("#1abc9c"))
)
dbCustomers = _db.form("customer").all()
dbCustomers.each do |dbCustomer|
pdfDocument.add(
_pdf.paragraph(dbCustomer.getString("name"))
.setFontSize(12)
.setFontColor(_pdf.color("#748dae"))
)
end
pdfDocument.close()
_header.contentType("pdf")
val pdfDocument = _pdf.newDocument(_pdf.pageSize("A5"))
pdfDocument.add(
_pdf.paragraph("Customer List:")
.setFontSize(16)
.setFontColor(_pdf.color("#1abc9c"))
)
val dbCustomers = _db.form("customer").all()
dbCustomers.forEach {
pdfDocument.add(
_pdf.paragraph(it.getString("name"))
.setFontSize(12)
.setFontColor(_pdf.color("#748dae"))
)
}
pdfDocument.close()
_header.contentType("pdf")
def pdfDocument = _pdf.newDocument(_pdf.pageSize("A5"))
pdfDocument.add(
_pdf.paragraph("Customer List:")
.setFontSize(16)
.setFontColor(_pdf.color("#1abc9c"))
)
def dbCustomers = _db.form("customer").all()
for (dbCustomer in dbCustomers) {
pdfDocument.add(
_pdf.paragraph(dbCustomer.getString("name"))
.setFontSize(12)
.setFontColor(_pdf.color("#748dae"))
)
}
pdfDocument.close()
Understanding the Code
-
_header.contentType("pdf"): Tells the browser that the response to this request is not ordinary text or JSON, but a PDF file.
-
_pdf: This is Netuno's native resource for manipulating PDFs. With it, we define the page size (A5), create paragraphs, and adjust font sizes (setFontSize) and colors (setFontColor).
-
_db.form("customer").all(): Queries the database and returns all records saved in the "customer" form. The loop (for) goes through each of these customers and extracts the information from the "name" field to print in the document.
-
pdfDocument.close(): Finalizes document construction and sends it as a response.
Validation and Tests
You do not need to click the dashboard button every time you want to test your service. Since this is a simple request (GET), you can validate execution by accessing the API URL directly in the browser.
For this example, access the following address: http://localhost:9000/services/customer/export-pdf
If the PDF file is generated and displayed on the screen containing the customer list, the service is working perfectly! Consequently, the Export PDF button in your Dashboard will start working automatically.
If the page is blank or returns an error message when accessing the URL, immediately check the terminal where the Netuno server is running. Unlike the frontend, whose errors appear in the browser console, any execution failure in scripts in the server folder will be displayed in detail in the backend server terminal.
Conclusion
In this tutorial, you went through a practical fullstack development journey using Netuno.
The main goal was to demonstrate how the platform integrates the construction of visual interfaces with the robustness of the server, always focusing on high productivity.
Recapping the completed steps:
-
Frontend Development: customized the dashboard in React, creating interface components and interactive buttons in a modular way.
-
Data Management and Structure: saw how quick it is to create forms and fields in the panel to register and manipulate information without needing to write complex persistence routines.
-
Direct Queries: Used the Query feature to run SQL commands quickly, testing the database.
-
Backend API Creation: Developed a service to generate PDF and observed one of Netuno's great advantages: hot-reload. You do not need to restart the server every time you change backend code, which greatly speeds up programming.
-
Optimized Environment: Configured integrated compilation, centralizing frontend and backend processes in a single terminal to stay focused and avoid distractions.
The platform was designed from its essence to optimize and accelerate software development. Now that you understand the basic flow of integration between low-code and custom code, you are ready to build much more complex and scalable applications.
Continue exploring the next sections of the documentation to master new features.
Development becomes much easier when you are part of an active community. Access the social media links in the footer of this page.