First App

Build your first OpenSya recruitment application.

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
OpenSya is designed to help you build modular and fully owned recruitment platforms with minimal boilerplate.

Create the Project

Start by creating a new OpenSya application.

pnpm create opensya my-first-app

Move into the project directory:

Terminal
cd my-first-app

Start the Development Server

Run the development runtime:

pnpm 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:

Structure
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:

server/services/recruitment/get-open-positions.ts
const getOpenPositions = async () => {
  return [
    {
      title: 'Frontend Engineer',
      department: 'Engineering',
      remote: true,
    },

    {
      title: 'Product Designer',
      department: 'Design',
      remote: false,
    },
  ];
};

export default defineService(getOpenPositions);
Services encapsulate reusable business logic.

Create Your First Controller

Create a controller:

server/controllers/recruitment/open-positions.ts

Add:

server/controllers/recruitment/open-positions.ts
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
  }
]
Your first OpenSya API endpoint is now running.

Create Your First Database Model

Create a model:

server/database/models/candidate-application.ts

Add:

server/database/models/candidate-application.ts
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:

server/services/recruitment/create-application.ts
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);
If the model name is not specified, OpenSya infers it automatically from the filename.

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.

Generated runtime files should not be edited manually.

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.

Architecture
Understand the OpenSya fullstack architecture.
Controllers
Learn how filesystem-based controllers work.
Models
Learn how database models are discovered and registered.