Ariel Costas

The tech stack I'm using and the reasons behind it

During the last year I’ve been experimenting with several web technologies, both in frontend (React with NextJS, Vue, and Svelte) and backend (like graphql-apollo, some ORMs, and few languages). After these experiments, I changed from using PHP for the backend (in a REST-like manner) and React SPAs for the frontend to using Node with GraphQL in my server and Sapper for my frontend.


For the backend, I’m currently using NodeJS, as it allows me to use the same language and syntax for all the parts of my app.

Around the summer, I discovered GraphQL, a query language for APIs that replaces REST and allows the client to specify which data they want to get. This way, if you’re trying to get a book and the name of its author, you can do one single query like this and get as a response just the fields you asked for, and a predictable response (in this case, the title of ten books, their ISBN and an author object, which just contains the user).

	books(limit: 10) {
		author {

However, building raw SQL queries to fetch data from our DB can be painful and give some headaches. That’s why I’m using MikroORM, an Object-Relational Mapping built on TypeScript (a JS superset that adds static typing) that uses classes and decorators to define database entities. Also, I’m using a framework called TypeGraphQL that allows me to define entities once, using the same class for both the database and the GraphQL schema. This way, my entities are defined like so:

export class Article {
	slug: string;

	title: string;

	@Field(() => User)
	@ManyToOne(() => User, (user) =>
	author: User;

With this class, I have a single source of truth for my data, instead of maintaining one for the DB and another one for the Graph.


For frontends, I’m using Svelte, a compiler to create web applications. It’s similar to React and Vue, but instead of shipping a Svelte library to the browser to run your app, you compile it beforehand and just ship the code needed to run your app. This leads to lower bundle sizes and faster loading.

Using svelte was hard at first, not for the syntax but for the configuration file; as svelte uses Rollup instead of Webpack. However, once you learn how to tweak things in rollup.config.js, it’s great to use.

However, to build full applications, instead of using Svelte, which is comparable to React or Vue, you have to use Sapper (the equivalent for NextJS or Nuxt). One of the main features is SSR for the first page. This way, the server makes the first request to your backend (handling cookies and all that stuff for you) and sends a rendered page to the user, with some JS code to handle routing. Then the app works similar to a SPA, running everything on the browser as create-react-app would do.

But what would be a good web application without some styles? Initially, I used vanilla CSS and Bootstrap, but around summer 2020 I came around this library called TailwindCSS, which makes CSS easier to handle by using utility classes instead of giving you a bunch of pre-made components. So, to define a button you would make something like this:

<button class="px-4 py-2 m-32 font-semibold text-white transition-colors duration-500 bg-blue-600 rounded-md hover:bg-blue-700 dark:bg-red-600">Click me!!</button>

These classes add some padding to the button, set the text to white and a weight of 600, add some rounding, background color, and when hovering make it darker, with just some classes.

In combination with Svelte’s component-based architecture, TailwindCSS allows me to define a button only once and adding all the variants I want. Then I can use this Svelte component all across my application. Or I could even build a design system that I can publish to a package registry and use in all my projects.


I’m using node with GraphQL and MikroORM for my backends, and Sapper with Tailwind for my frontends.

If you’ve liked this article or found it useful, consider sharing it on social media to help this blog grow!