Build Adonis/Vue apps without an API

Published 9/13/2020

In a previous post I created a prototype of seamless integration between frontend and backend.

To save you from reading the article, here's a gist:

No more fetch requests to the backend, no more setting up API routes, no need for controllers. Leaving you with what is essentially just calling a function (referred to as an action).

Under the hood, it creates the API routes automatically and turns backend imports on the frontend into network requests.

This time I've taken the same approach and applied it to something more realistic. An app that uses Adonis.js on the backend and Vue.js on the frontend.

Check out my e-book!

Learn to simplify day-to-day code and the balance between over- and under-engineering.

How it looks like

Here is the GitHub of the little app. It contains a couple of actions like getting all users, creating users, and logging in.

To keep this example simple, let's just see how we can get the list of all users.

Backend (extracted from Actions/user.js)

const User = use('App/Models/User')

exports.getAllUsers = async function() {
  return User.all()
}

Frontend (extracted from App.vue)

<template>
  <ul>
    <li v-for="user in users" :key="user.id">
      [{{ user.id }}] {{ user.email }}
    </li>
  </ul>
</template>

<script>
import { getAllUsers } from '../../api/app/Actions/user'

export default {
    data() {
        return { users: [] }
    },
    async mounted() {
        this.users = await getAllUsers()
    }
}
</script>

Seeeeamless ;)

Changes to the previous prototype

Mainly there's a new seamlesslyrc.json file that holds everything together. The backend will write all generated routes to this file and the frontend will then consume it.

Having this file comes with a lot of benefits over the previous prototype:

  • No need for language/framework parsing
  • single source of truth for the whole API generation
  • Can be used to look up the API
  • Can be used to store more things in the future like the endpoint prefix (currently always /api)
  • using other HTTP methods than just POST is a lot easier.

The loader and API generator is under a new package called seamlessly.

And you can find the integration for the above example here:


There are still some things that require some more thought, but I guess for the next test, I will try to use a non-JS language as the backend. Laravel 🤔🤔🤔