Skip to content

Getting started

Requirements

  • Node v20+
  • A running MongoDB server optional
  • Git command line utility optional
  • A POSIX-like environment optional
    • Some scripts will require commands such as mv and sh to be available. On Windows, those are commonly packed together with git.

Initial setup

The official and easiest way to start an Aeria project is through the create-aeria-app command line utility. It is done the following way (it may vary according to the package manager you use):

npm create -y aeria-app project-name

The utility will scaffold a new project with some defaults:

  • TypeScript
  • ESlint installed with the official Aeria style guideline
  • Husky and commitlint with conventional commits set up
  • Tailwind preconfigured in the frontend with the tw- prefix in classes

If you wish for a more vanilla approach instead, simply install the aeria package and start your project from a .js or a .mjs file. The only important thing is to make sure the main property inside the package.json exists and points to the right file.

Running the project and signing in

Make sure the MongoDB server is running. Next, navigate into the project root and run the dev script:

npm run dev

This command will serve the backend and frontend at once. If execution is successful, a sign in page will be made available in the following location:

http://localhost:8080/user/signin

Finally, to grant you access to the application during development, sign in using the default credentials specified in the .env file, create another user with the root role, change its password, and sign in again with it instead. Do not skip this step as the default user (the one that signs in with the credentials specified in env vars) lacks some important attributes.

Collections

Adding collections

Collections are declared in the schemas/main.aeria file. Below there is an example of a "person" collection being declared with Aeria Lang.

aeria
collection Person {
  icon "person-simple"
  properties {
    name str
    age num
  }
  presets {
    crud
  }
  functions {
    get @expose
    getAll @expose
    insert @expose
    remove @expose
  }
}

The development server will reload upon changes on schemas/*.aeria with the changes being automatically applied. No migration is needed after the data structure of a collection is changed. Needed migrations are performed automatically under the hood by diffing the current data structure with the previous one (todo).

Adding functions to collections

In order to enable file uploading for our example Person collection, it is required to add the upload function to the functions set. The @expose attribute that comes right after the function name can be used without any arguments, meaning the function is exposed to every signed in user, or an array of roles can be passed to mean the function is only exposed to users whose role is contained within the set. To illustrate this, let's make files only uploadable by root users.

Available functions can be seen in their respective section of the documentation.

aeria
collection Person {
  properties {
    name str
    age num
    picture File @accept(["image/*"]) 
  }
  presets {
    crud
  }
  functions {
    get @expose
    getAll @expose
    insert @expose
    remove @expose
    upload @expose(["root"]) 
  }
}

Setting user roles

Roles are set by extending the default user collection. The default boilerplate already comes with some roles set. You may replace them with the ones your application needs. No matter which roles you set, the guest and root roles are special roles used internally by the framework and will always be available.

aeria
collection User extends aeria.user {
  properties {
    roles []enum @values([
      "root",
      "supervisor", 
      "customer"
    ])
  }
}

Business logic

Adding routes

Open the scaffolded routes/index.ts file and add a route by calling the chosen method (GET, POST, route for multiple methods, etc). Request and response data and methods, as long as collections and API utilities can be accessed through the context parameter made available in the route callback.

To indicate error and successful responses, use Result.error() and Result.result() respectively. Learn more about how Aeria handlers errors in the Error Handling page.

typescript
import { createRouter, Result } from 'aeria'

export const router = createRouter()

router.GET('/test', async (context) => {
  const {
    error,
    result: people
  } = await context.collections.person.functions.getAll()

  if( error ) {
    return Result.error(error)
  }

  return Result.result({
    message: 'Hello, world!',
    people,
  })
})

Frontend

Creating pages in the frontend

Aeria UI uses unplugin-vue-router under the hood to provide a Nuxt-like filesystem-based routing. This means that, in order to create a page in the frontend, you must simply place your .vue file inside the pages/ folder. For example, to make /dashboard/hello-world view, create the pages/dashboard/hello-world.vue file and put something in the template:

vue
<script setup lang="ts">
definePage({
  meta: {
    title: 'Hello World',
    icon: 'globe-hemisphere-east',
  },
})
</script>

<template>
  <h1>Hello, world!</h1>
</template>

Changing the default menu schema

In order to change the navbar that appears in the dashboard to add or rearrange items you must add the menuSchema property inside defineOptions(). More information on how the menu can be customized can be seen at Menu configuration.

typescript
const options = defineOptions({
  // ...
  menuSchema: [
    '/dashboard/hello-world',
    {
      meta: {
        title: 'Collections',
      },
      children: [
        '/dashboard/person',
        '/dashboard/user',
      ],
    },
  ],
})

Retrieving data from the frontend

There should be a point in the development of the application that it will be needed to request an endpoint and get back the response. You shouldn't use fetch() or any other HTTP client for this (except when really needed). Instead, use Aeria SDK to interact with the backend with 1:1 typing and authentication handling.

vue
<script setup lang="ts">
const metaStore = useStore('meta')
const people = ref([])

onMounted(async () => {
  const { error, result } = await aeria().test.GET()

  if( error ) {
    return metaStore.$actions.spawnToast({
      title: 'Error!',
      message: 'There was an error fetching people from the API'
    })
  }

  people.value = result.people
})
</script>

<template>
  <ul>
    <li
      v-for="person in people"
      :key="person._id"
    >
      {{ person.name }} ({{ person.age }} years old)
    </li>
  </ul>
</template>

Adding a custom action in the tabular view

It is possible to change the tabular view presented by default by Aeria when a collection is added. Some details, like table buttons, can be defined directly in the collection schema. It is also possible to alter the DOM directly as will be shown next.

In this example, a "Toggle active" button that toggles the value of the active property will be added.

aeria
collection Person {
  properties {
    name str
    age num
    active bool
    picture File @accept(["image/*"])
  }
  presets {
    crud
  }
  functions {
    get @expose
    getAll @expose
    insert @expose
    remove @expose
    upload @expose(["root"])
  }
  individualActions { 
    toggleActive { 
      label "Toggle active"
    } 
  } 
}

Customizing the DOM of the tabular view

Aeria UI uses NextJS-style filesystem-routing. So the first step to override the runtime-generated /dashboard/person route is to create a page named accordingly. Next, simply use the aeria-crud component to render the table, actions, forms, etc and structure the page as needed. Last thing, slots can be used to customize pieces of DOM inside the aeria-crud component.

To see all accepted slots, refer to the Aeria UI documentation.

vue
<script setup lang="ts">
definePage({
  meta: {
    title: 'People',
    icon: 'person-simple',
  },
})
</script>

<template>
  <h1>This is a header!</h1>

  <aeria-crud collection="person">
    <template #row-active="{ row, column }">
      {{ row[column] ? 'Active' : 'Inactive' }}
    </template>
  </aeria-crud>
</template>

Further reading

Details and advanced usage of steps covered in this guide can be found in the documentation of each project (Aeria and Aeria UI).

Released under the MIT License.