First App
First App
In this guide, you will create your first OpenSya application and discover how the runtime works through filesystem conventions.
By the end of this guide, you will have:
- A running OpenSya application
- Your first controller
- Your first service
- Your first database model
- A basic recruitment API endpoint
Create the Project
Start by creating a new OpenSya application.
pnpm create opensya my-first-app
yarn create opensya my-first-app
npm create opensya my-first-app
bun create opensya my-first-app
Move into the project directory:
cd my-first-app
Start the Development Server
Run the development runtime:
pnpm run dev
yarn dev
npm run dev
bun run dev
OpenSya automatically:
- Generates the backend runtime
- Starts the NestJS server
- Starts the Nuxt frontend
- Watches filesystem changes
Project Structure
Your project should look like this:
my-first-app/
├── server/
│ ├── controllers/
│ ├── services/
│ ├── database/
│ │ ├── models/
│ │ └── plugins/
│ ├── guards/
│ └── locales/
│
├── client/
│ ├── pages/
│ ├── components/
│ └── plugins/
│
├── .env
└── opensya.config.ts
The backend runtime is powered by NestJS while the frontend runtime is delegated to Nuxt.
Create Your First Service
Create a service inside:
server/services/recruitment/get-open-positions.ts
Add the following code:
const getOpenPositions = async () => {
return [
{
title: 'Frontend Engineer',
department: 'Engineering',
remote: true,
},
{
title: 'Product Designer',
department: 'Design',
remote: false,
},
];
};
export default defineService(getOpenPositions);
Create Your First Controller
Create a controller:
server/controllers/recruitment/open-positions.ts
Add:
export default defineController(
async () => {
return useService('recruitment.get-open-positions')();
},
{
public: true,
},
);
The controller automatically becomes available at:
/api/recruitment/open-positions
Test the Endpoint
Open:
http://localhost:3000/api/recruitment/open-positions
You should receive:
[
{
"title": "Frontend Engineer",
"department": "Engineering",
"remote": true
},
{
"title": "Product Designer",
"department": "Design",
"remote": false
}
]
Create Your First Database Model
Create a model:
server/database/models/candidate-application.ts
Add:
import { Model } from '#core/nest/types';
const model = {
schema: {
firstname: {
type: String,
required: true,
},
lastname: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
position: {
type: String,
required: true,
},
},
} satisfies Model;
export default model;
OpenSya automatically discovers and registers the model.
Access the Model
Models can be accessed using getModel().
Example:
const createApplication = async () => {
const CandidateApplicationModel = getModel(
'candidate-application',
);
return CandidateApplicationModel.create({
firstname: 'John',
lastname: 'Doe',
email: 'john@company.com',
position: 'Frontend Engineer',
});
};
export default defineService(createApplication);
Add Translations
Create a translation file:
server/locales/fr/common.json
Example:
{
"recruitment": {
"open_positions": "Postes ouverts"
}
}
Use translations anywhere in the backend runtime:
$t('common.recruitment.open_positions')
or:
useTranslate('common.recruitment.open_positions')
Generated Runtime
During development, OpenSya generates the backend runtime automatically inside:
.opensya/server/
This runtime is regenerated automatically whenever files change.
What You Learned
In this guide, you learned how to:
- Create an OpenSya application
- Run the development runtime
- Create services
- Create controllers
- Create models
- Access models
- Add translations
Most importantly, you discovered how OpenSya uses filesystem conventions to orchestrate the runtime automatically.
Next Steps
Continue with the core documentation to better understand the runtime architecture.