Nhost

Nhost: The Open Source Firebase Alternative with GraphQL
Кратко: аналог 0! Supabase, и встроен удобный инструмент GraphQL
GraphQL похож на View в Supa, только удобней делать запросы (текстом)
интеграции с Flutterflow нет, запросы делаем через API (они легко пишутся)

🔹 Когда использовать GraphQL?

✅ Если клиенту нужно гибко получать данные.
✅ Когда API обслуживает разные клиенты (веб, мобильные приложения).
✅ Если важно уменьшить количество сетевых запросов.

Краткое содержание видео (1 вариант)

Вот основные мысли из текста:

  • Введение в проблему: Создание сложных приложений требует надёжного бэкенда. Supabase - хороший вариант, но возникают сложности с получением точных данных из-за реляционной структуры базы данных.
  • Решение: GraphQL и এনHost: Автор представляет альтернативу - GraphQL в связке с платформой এনHost. GraphQL позволяет более интуитивно работать с данными и запрашивать их. এনHost упрощает работу с GraphQL, предоставляя готовую инфраструктуру.
  • Преимущества এনHost и GraphQL:
    • Простота: Легче, чем Supabase, создавать запросы и получать нужные данные.
    • Гибкость: Возможность запрашивать данные из нескольких таблиц с помощью одного запроса (GraphQL).
    • Производительность: Один API-запрос для всех операций (получение, изменение, удаление данных) делает приложение более быстрым.
    • Интуитивность: UI для управления данными, создания запросов, разрешений и связей.
    • Реляционные связи: Простая настройка связей между данными, например, "комментарий - родительский комментарий" (threading).
    • Hasura: Используется Hasura для трансляции запросов GraphQL в SQL для работы с базой данных.
  • Демонстрация в FlutterFlow: Автор показывает, как использовать এনHost и GraphQL в приложении, разработанном с помощью FlutterFlow (no-code разработка). Показывает примеры запросов, которые:
    • Получают список статей с информацией об авторах, количестве комментариев и т. д.
    • Отображают подробную информацию об отдельной статье (контент, комментарии).
    • Позволяют создать новый пост.
  • Ключевые моменты FlutterFlow интеграции:
    • Использование одного API-запроса.
    • Динамическая передача GraphQL запроса для изменения данных.
    • Преобразование JSON данных в пользовательские типы данных для удобства работы.
  • Заключение: GraphQL и এনHost упрощают и ускоряют разработку приложений, избавляя от необходимости создания множества отдельных запросов и представлений.

Краткое содержание видео (2 вариант)

  • Введение в проблему: Создание сложных приложений требует надёжного бэкенда. Supabase - хороший вариант, но возникают сложности с получением точных данных из-за реляционной структуры базы данных.
  • Решение: GraphQL и এনHost: Автор представляет альтернативу - GraphQL в связке с платформой এনHost. GraphQL позволяет более интуитивно работать с данными и запрашивать их. এনHost упрощает работу с GraphQL, предоставляя готовую инфраструктуру.
  • Преимущества এনHost и GraphQL:
    • Простота: Легче, чем Supabase, создавать запросы и получать нужные данные.
    • Гибкость: Возможность запрашивать данные из нескольких таблиц с помощью одного запроса (GraphQL).
    • Производительность: Один API-запрос для всех операций (получение, изменение, удаление данных) делает приложение более быстрым.
    • Интуитивность: UI для управления данными, создания запросов, разрешений и связей.
    • Реляционные связи: Простая настройка связей между данными, например, "комментарий - родительский комментарий" (threading).
    • Hasura: Используется Hasura для трансляции запросов GraphQL в SQL для работы с базой данных.
  • Демонстрация в FlutterFlow: Автор показывает, как использовать এনHost и GraphQL в приложении, разработанном с помощью FlutterFlow (no-code разработка). Показывает примеры запросов, которые:
    • Получают список статей с информацией об авторах, количестве комментариев и т. д.
    • Отображают подробную информацию об отдельной статье (контент, комментарии).
    • Позволяют создать новый пост.
  • Ключевые моменты FlutterFlow интеграции:
    • Использование одного API-запроса.
    • Динамическая передача GraphQL запроса для изменения данных.
    • Преобразование JSON данных в пользовательские типы данных для удобства работы.
  • Заключение: GraphQL и এনHost упрощают и ускоряют разработку приложений, избавляя от необходимости создания множества отдельных запросов и представлений.

Полная расшифровка видео на английском

Here's the cleaned-up and properly formatted transcript with corrected punctuation:

Now, when it comes to building apps, especially production-ready, complex apps—apps that are going to be used by tens of thousands of people, and maybe even tens of millions of people or even more—one of the most important elements that you need to be aware of is the backend. What backend are you going to be using? What backend is going to form the basis of the app that you're going to be building? And one of my favorite backends, and this is a backend that I recommend everyone to use, is Supabase. Supabase is an incredible backend; it's an industry standard, and it's fairly simple to use Supabase to build all kinds of apps, anything from very, very simple apps to very, very complex apps. But even Supabase comes with its own challenges and forces you to deal with and solve a lot of problems.

One of the main qualms that I hear with Supabase is it's hard to get the exact data that you want after you have all that data in Supabase, and that is because Supabase is a relational database. In order to get the data that you want, especially data that spans multiple tables, you need to use something called joins, or in many cases, you need to be creating views that are tailored for your specific application use case. So, one page has this view, another page has that view, and over time, that can get fairly burdensome. Okay, and what if I told you that there's another backend, an industry-standard backend that's used by many, many big and successful companies that build amazing apps, that pretty much gives you all the benefits of Supabase without many of the drawbacks?

Yes, this backend exists, and in today's video, I'm going to be showing you exactly what this backend is, how to get it to store the data that you want, and most importantly, to spit out the data that you want. A little bit later in the video, I'm going to be showing you a FlutterFlow proof-of-concept app that I built that shows you how you can build no-code apps with FlutterFlow that rely on this backend. Now, the type of backend that we're going to be talking about today is called GraphQL. And before we jump into GraphQL, I want to introduce you to an amazing tool that will help us use GraphQL, as well as give us some of these other benefits that are going to be super helpful for the apps that we're going to be building, and this tool is called এনHost.

Okay, so if you head over to এনHost, you're going to be on this page, and this is an open-source tool. Here in the front page, it says, "Build apps users love." এনHost is an open-source backend and development platform that enables developers to build and scale their web and mobile apps. Okay, and so you can scroll down, you can see a dashboard right here, you can also see some of the people using it, and you can kind of learn more about this tool. Right, this is a "backend without limits." Get a database and backend configured and ready to use in minutes so you can focus on your app and your users. Okay, and so this is actually a layer on top of a PostgreSQL database, and this should be familiar to many of you because that is exactly what Supabase uses. Okay, so this is going to be very, very similar to Supabase, but it's going to have one major difference—one major benefit, I should say—that you're going to see in just a second.

And so here's the main star of the show, and this is a GraphQL API: instant, real-time GraphQL API based on your database schema. And then you also have something called Hasura right here, which gives you role-based permissions, web consoles, event triggers, cron jobs, and more. You have Auth, you have storage, you have functions, you have run, and you have AI. Okay, so you have lots and lots of awesome things here. And so the next thing that we want to do is we want to sign up for our free account. Okay, you can simply click over here; you're going to sign up for your free account.

Now, when you log into এনHost, you're going to be on a page that looks something like this, and this page right here, this screen, is very, very similar to another tool that many of you might be using or have been using for quite a while if you've been watching my videos, and that tool is Supabase. Okay, they're very, very similar, but there are still some major differences. Okay, so right here, I have one of my projects here; this is my only project, and I can simply create it by clicking over here, going to projects, and I can create a new project over here. Now, if I select my project, I'm going to be looking at my dashboard, and if I look at this menu on the left-hand side, we have a bunch of interesting things, right? So, we have something called a database. Okay, and this right here is a relational database, which is pretty much the same as in Supabase, right? Supabase relies on PostgreSQL, and this tool relies on PostgreSQL as well. Okay, and I have a bunch of tables here that I'm going to be explaining in just a minute.

But we also have something called GraphQL. Now, GraphQL is something that we're going to be covering in just a few minutes, but suffice it to say, it's an amazing, amazing way to work with the data that you have that's a lot more intuitive than, you know, when you work with the data using some of these other backends. And so we're going to be coming back to this in just a couple of minutes. We also have something called Hasura, right? Hasura is the dashboard you'll use to edit your schema and permissions, as well as browse your data, and we'll get back to this as well. Then we also have Auth, we have storage, we have run, we have AI, we have deployments, and so we have a bunch of other things that are important to have, you know, in your backend, right, if you're using it for production app purposes. But the main thing that I want to focus on in today's video are these things, more specifically, the database, GraphQL, and Hasura.

Okay, so first, what makes এনHost radically different than things like Supabase, and why should you be using এনHost instead of some of these other tools? Well, the main reason that you should try out এনHost and see if you like it is because of something called GraphQL support, and this is really, really amazing. Okay, and so to show you how this works, let me jump into this database tab, and let's talk a little bit about the kind of app that we want to build and the kind of data that we have. So, in this database tab, you are essentially working with a relational database. This is exactly the same as Supabase. Okay, so you have your schemas over here, you have your tables over here, you can create a new table, you also have a SQL editor over here, and so it's very, very similar to Supabase's own interface where you can create new tables. You also have a SQL editor, stuff like that.

And so here, I have two tables: I have the post table and the comments. And the reason I have those two tables is I want to show you how you would build a simple publishing site, or like a blog site, where you might have multiple articles, and each article can have multiple comments. Okay, and so this post table here, the fields are very, very simple. We have the title of the post, we have the content, we have the date that it was created, and we have the user ID who wrote the article. Okay, and if we click over here and we edit this table, you can see that it's very, very similar to Supabase. Okay, we have our fields over here, and we also have a foreign key. So, this user ID is not just a random UUID field; it's actually linked to a table in this old schema called the user table, very, very similar as you would do in Supabase, if not exactly how you would do it in Supabase. Okay, and so that is what we have in the post table.

And so if we go into comments here, we just have a bunch of comments. Okay, so if I click over here, I can edit this table, and I have a bunch of comments. So, I have the ID of the comment, I have the text of the comment, I have the post ID (which post does this comment belong to?), we have the parent comment ID, and that is for threading, right? If I'm replying to another comment instead of replying to a post itself, right? So, if it's not a high-level, a top-level comment, it's a reply to a specific comment, like things that you see on blog sites, on Reddit especially, you're going to be seeing like, you know, comments being replied to comments, you know, being replied to other comments. And so this allows us to track, you know, if we have threading, if we support threading, you can reply to a comment instead of replying to a post directly, which is really, really nice. And here we have the user ID, and this is followed by this "created at," when the comment was created. Okay, and so we also have our foreign keys, right? We have this user ID that's a foreign key in this other table here, and then we also have this post ID, which is a foreign key in that other table that I just talked about, that post table.

Okay, so standard stuff. Now, what we've been talking about so far is exactly how you would do it in Supabase. Okay, because with both of these tools, এনHost and Supabase, you have PostgreSQL under the hood, so it's exactly the same. Now, the main difference with এনHost is that it supports something called GraphQL, and GraphQL is truly a revolutionary way to deal with your data, to query your data, to manipulate your data, to insert new records, update records, delete—all the same operations that you typically do, you know, in a Supabase-type backend, you can do the same with GraphQL. It's just it's a lot more intuitive. Okay, so let me show you a couple of examples. Okay.

And so let's say I want to create a sample query that gets me a list of posts that I have. Okay, and this is obviously something that you'll need to do if you're building that kind of app. You will need to have a query that gets you a list of posts and displays them to the user. Well, that is very, very simple to do. All I need to do is type "query," come over here, and then I can just type "post." Okay, and then for "post," I can define the fields that I want. Okay, so for instance, let's say I want the title here. Okay, so that is my query, right? I'm saying I want all the posts, and I want to display the title over here. And so I'm going to go ahead and execute this query, and when I do that, this is the list of data that I'm getting back. And so this gave me back four posts here, right? We have all the titles for the four posts, and if I go back and open up a database as well, you're going to see that we have four posts here. Okay, very, very simple, and I just got the data that I need.

And so let's say I want to get another field, right? Let's say I want to get the content as well. Well, all I need to do is just add "content" here. Okay, re-execute that, and I'm getting the data here. Now, this is all JSON, right? So, it's going to be super easy to parse this data in your app, right? You can simply, you know, get it as it is and then just get the fields, display the fields that you need, and you're going to see all that in just a little bit once we jump over to our proof-of-concept section of the video where I'll show you a FlutterFlow app that I built that does exactly that. Now, let's go ahead and add another one. Let's say I want to display "created at." Okay, I'm going to go ahead and execute this, and now it's displaying "created at." Okay.

Now, so far, this is very, very simple, and you may be thinking at this point, "Well, James, this is great and all, but where's the, where's the, you know, where's the amazing stuff, right? Where's the keys to the kingdom, right? Where, where's the, the, the main thing with this, right?" Well, let me show you the main thing. Let me show you what makes it super cool. Okay. Now, remember, we have here two tables, and we have comments—that, you know, a post can have multiple comments. So, it becomes a one-to-many relationship, right? So, you have a post on one side, and you have multiple comments on another. And so let's say I want to display all the comments for every article here as well, in case we need that data in our app. Well, this is also easy to do. I can simply come over here, and I can simply say "comments." And guess what? I'm just going to continue listing the fields that I want. So, for comments, let me see, the main field is just "text," so I'm going to put "text." Okay, I'm going to execute this, and guess what? Now we have all the data.

Now, if you wanted to do this with Supabase, you have a couple of options, right? It's not straightforward. You can create a join, but if you're using no-code, you can't really do joins. You need a view, right? So, if you want to have this kind of output, you need to create a view, and typically, you would be creating a separate view for each part of your app because they're going to be displaying radically different data. And here, I don't even need to create the view. I can just simply tell it which, you know, what data I'm looking for, right? It's declarative, right? I'm not, I'm not concerning myself with how I'm going to be getting the data that I want. I don't care about all that. All I'm doing is I'm saying, "Listen, give me this data. I don't care how you get it. I don't care if you need to do a million joins or do whatever you got to do. Just show me this data in this format." And that is exactly what it's doing, right?

So, I can keep going. I can say "text," and I can say "created at," and I even have a little bit of autocomplete here that helps me kind of work with this, right? And so I'm going to go ahead and execute this, and now we have "order complete." And so now for each post, I have a list of comments that I have created here, right? Because if I go back here, I have comments, and each comment has a post ID that links it back. So, for instance, here we have, how many comments? We have six comments, and three of them are for a specific post, and then you have two of them are for another post, and then post, you know, post ID 4, post with ID 4, has just one comment. So, if I go back here, I can see that, you know, here, here's one comment, here's two comments, and this is a post with no comments. So, "Best cities to visit in Portugal," right? There's no comments here. Okay.

And so all of this is nicely formatted with JSON, right? It's all easy to parse, easy to work with, and I have this really, really nice UI here that where I can play with different queries and see the results that I'm getting. Really, really nice. And I can click here and open up a new tab that's going to allow me to, you know, try out some of these other queries. Maybe I want to keep these queries here, and I want to try some, some other queries, you know, without deleting these queries. Now, this mainly is just scratching the top of the surface because you can go a lot further, right? You can filter different posts, you can sort stuff, you can limit stuff. So, you have the same functionality that you have with SQL, right? You can have just distinct elements, but it also gives you a bunch of other things that you don't get with SQL. Okay.

And to show you some of the extra things that you can do with it, right, just to kind of, you know, show you the, the true power of this, what I'm going to do is I'm going to click on Hasura, and I'm going to open up Hasura because underneath all of this, एनHost, there's something called Hasura, which is the heart of it all. That is what links our PostgreSQL database, which is where our data is stored, right over here, with GraphQL. So, as you're sending those GraphQL requests, they are going through Hasura, which translates your GraphQL queries into SQL queries so that you don't need to worry about all that. And just to show you kind of the overall schema, take a look at this diagram over here that I have created, right?

So, we have the user right here. They are interacting with a FlutterFlow app, and this FlutterFlow app is typically going to be interacting with our data over here using an API. And these APIs are going to be sent to এনHost, and that's going to be forwarded to Hasura, and that's going to translate our GraphQL, these really, really intuitive and kind of declarative commands, if you will, requests into SQL. And that SQL is going to run on, on PostgreSQL over here that we have, PostgreSQL here that we have, which is kind of the, the underline where all the data is stored. And then you have this admin flow, which is what I'm showing you right now. This is where I am, you know, working on this এনHost dashboard, and I'm working with all of these things here. Okay.

And so if we go back to এনHost, and we click on Hasura, and we copy this over here, that is something that you need to do because we have an admin secret. And then if I click over here, if I open this up for the first time, it's going to ask me to input that secret. And so what you want to do is you want to just copy it and simply input it. You're going to be seeing a little form with just one input field where you need to put in that secret, and now we are on Hasura. Okay, and so now we have a lot more things that we can do, right? On এনHost, we can do some of the basic things, but on Hasura, we can do some of the, kind of the more advanced stuff. Okay.

And so here, I have a bunch of queries here, right? So, I have "get_all," and this is a little bit more advanced. Okay, so here, I'm getting the post, I'm getting ID, title, "created at," but I'm also getting the user, right? I'm getting the user, and that requires me to join with another table because we have a foreign key, and that's not a problem. I just, I want the user, and which fields do I want for the user? Well, I just want the display name because if I go over here, if I go to our database, and I go to this "auth" schema, and I go into users, well, we have one user. This is James, and we have this display name, and this is James over here. And then I have my comments. Okay, I want to get the comments, but I'm telling it that I only want the top-level comments. Okay, I'm basically saying that where "parent_comment_id" is null. Okay, and if you recall, we have our parent comment ID, and so if it, if it's null, there's no parent, it's a top-level comment. And so I'm saying I only want the top-level comment, and then I also have something interesting. I have something called "children."

And what "children" is, it's an alias to get the recursive comments, basically the comments under the comment, because if you reply to the, the main post, it's a top-level comment, but if you reply to another comment, it becomes a, a, you know, kind of recursive thing, right? You have a, you have a child in there, a child comment that's replied to a comment. Okay, and so we have something called "children." Now, why do we have "children?" Well, if I go into "data" over here, okay, I'm looking at the underlying data, right? Because Hasura basically gets it to work together. It gets these GraphQL requests to work with our underlying data in our PostgreSQL database, right? And so if I go into "comments" over here, right, and I go into "relationships," I have here a relationship called "children," and what I'm saying here is I'm saying that a comment ID can be linked to other comments via this "parent_comment_id."

So, if I click on "add relationship," this is what I would be doing. I would say "children," and then I would say, "Well, I want to reference comments over here," and then what I'm going to say is this is a "relay array relationship" because you may have multiple children under that one comment. And here, I'm going to click here, and I'm going to say "ID," and I'm going to link it to the "parent_comment_id." Okay, and then all I need to do is "create relationship." So, let's say I call it "children2," I'm going to "create relationship," and that's going to create the same relationship that we have here, and right there, very, very quickly, right? Just by adding a relationship, we have threaded comments. Okay, we have support for threaded comments because this right here is fairly complex to do it with Supabase, right? You can do it with Supabase, but it's very, very tricky, and you have to create a new view, of course. But here, you can just do it in the UI, which is amazing, right? So, I'm going to go ahead and remove it because we already have that.

And so that is how you can do it. You can create all kinds of different relationships. This is just, you know, scraping the top of the surface, basically. And of course, here you have permissions as well, right? You can say, "Well, what can an admin do? What can, what can a user do?" You can change this. You can go into "posts," click on "permissions," and change the permissions. You can add a new role. You can do amazing, amazing things. And so what I'm saying is I want just the top-level comments, because if I don't do it, it's going to display all the comments, and so we're going to have duplication because we're going to get the children as child comments, and then we're going to get children as just regular comments. And one last thing that I did mention is we also have something called an "aggregate," right? And this is where we are getting the number of comments for each post, right? And that's going to be useful on the main kind of post page. We're not necessarily going to be displaying the comments themselves; we may only want to display the number of comments in there, right?

And so you can do that really easily, and so here you can say "comments_aggregate." This is "aggregate," and this is a "count." We're calling it "the count." Now, below this query, we also have a bunch of other queries here, so things like creating a new post and deleting a post. Very, very simple. You have something called "insert_post" where you can just specify the data that you want, and that's going to insert it, and that's going to return an ID in case you need that ID of the newly created post in your app. And we also have something called "delete_post," right? So, I can just rename it "delete_post_by_id," and so here, I need to specify the ID, and that's going to go ahead, delete it, but also it's going to return some of the data back. So, if I need to delete something, and then I need to tell the user what just, what, you know, what was just deleted, like, you know, "This post with a was deleted," or, "This post called blah, blah, blah was deleted," I can just say, "Well, give me back the title of the post." Okay, and that's going to delete it but give us back the data of the stuff that was deleted. This is very useful when you have something called an "undo," right? So, you, you did something, the user did something, now they want to undo it. Well, you have this data here, right? So, you can recreate the post back. Very, very useful.

Okay, so this works the exact same way, right? And so if I go up here and I take a look, I can see that I have a bunch of posts, but a post ID 6, "Best cities to visit in Portugal," doesn't have any comments. So, let's go ahead and delete this post. So, I can simply say "6" over here, ID 6, I'm going to select that, and I'm going to run it. Okay, and that should have deleted it, but it gave us back the data. Okay, so if I go back here, I don't see that post anymore because this automatically refreshed. We don't see post with post ID 6. Now, I also do not need to do any of this by hand. I actually can do it using the UI, right? So, if you take a look here, we have "post_id," and if we collapse all, you see this is selected. So, I can just select and do what I want to do using the UI, which is amazing, right?

So, here I have ID, title, and "created at." Well, if I deselect it, it goes away. If I deselect it, all of that goes away. So, now I'm not even displaying the post stuff, right? So, here's my content, here's my "created at," I want, I want the title, I want the user, I also may want, um, you know, something else. I may want the user "avatar_url," and that goes ahead and puts it there. And so now if we run that, guess what? We have, we have the "avatar_url" here, we have "display name." If I don't want the "display name," I can just go over here, remove this, and re-execute, and now I don't have the "display name." So, you do not need to create this by hand. I mean, obviously, you can use things like ChatGPT to, to generate it if you want, but you can just use this UI, which is so intuitive and so amazing, right? I can, you know, I can have this "email_verified," I can do that, I can go ahead and run it, and this "email_verified" is a Boolean, right? So, I can get Booleans, and as you can see, it's false for this user. Okay.

And so I'm getting all the data that I want. I have relationships, I have, you know, child, children of children, I have this kind of, this recursive flow, and all I'm doing is, is kind of, you know, telling it the data that I want, right? I'm, I'm just telling it, "I want this data like this," and I'm getting it exactly how, how I told it, right? In this, you know, easy-to-parse, easy-to-work-with JSON format that is super amazing, super awesome. And you know, I have this really nice kind of UI, I have, you know, all of this here, and so this makes it super easy to work with the data. And the way that you send all of these requests is via an API.

And what's cool about it is that we only have one API endpoint. Okay, so we don't have these multiple API endpoints—one for creating data, one for querying data, one for updating data, one for deleting, one for this, one for that. We only have one endpoint. Okay, this one endpoint I have here is used for any of the requests. So, regardless if I am deleting data, if I'm getting data, if I'm getting data in this format, that format, it doesn't matter. I'm querying data, I want data just, you know, for this user or for that post, or if, if a post is about this, it's about that, you know, it doesn't matter. It's all one endpoint, which makes it super easy and kind of streamlines and simplifies a lot of things, right? It, it truly does streamline a lot of the hassle. Okay, but if you want to have multiple endpoints, you can do that as well, right? You can simply click here on this "REST" tab here, and you can create another REST endpoint.

And so as you can see here, you can create a REST endpoint called "users," and that's going to only execute a specific query that you want. So, in this case, we're just querying "users." So, I can click, click here and come over here. I can just say "query posts," "query posts title," that's it, and I can say "posts." This is "posts," this is a GET request because we're not modifying data, and "get_posts" over here, click "create," and I just created a custom REST endpoint that does something specific. In this example, we're just getting the post with the title, just the post with that one title field. That is all. And so this is an optional step, obviously. I'm going to go ahead and delete it because you do not need to do it. You do not need custom REST endpoints. You can simply use this one and pass any query that you want, as you're going to be seeing in just a couple of moments when I show you our proof-of-concept app that I built to do just that.

Now, Hasura also has a bunch of other things, so things like actions, remote schemas, and events, and all of this is going to be covered in a future kind of deep-dive video focusing on this platform. But right now, I want to focus on just the APIs and just on this data over here. All right, so now that we've talked about এনHost, we've talked about GraphQL, we've jumped into Hasura to have us, to give us more control to create just the queries that we need, let me show you how all of this is tied together and how you can use এনHost as your backend when building production-ready apps.

All right, so here's our app, and this is going to be an app where people can read articles, they can see comments, and all of that. And so on this screen, we have a list of posts that we get from the "post" table. Okay, so we have a query that gets us all this data, and we only execute this once. We only have one query in the entire app because we're able to get the data that we need on all the pages in this app. Okay, so we have the name of the article, we have the person who wrote it, we have the number of comments, we have the, when it was posted, we have all of that information here. If I click on it, I have the actual content of the articles, I have the title here at the top, I have the content, and then I have a threaded comment view. Okay, so we have this, this is a reply, and this is another top-level comment. Okay.

And so now let me go back, and here we are here, and I can click, let's say, on this one, and we have, you know, the, the, the title, the content, two comments, and this is a reply, right? So, somebody asked about, "What about visiting Sweden?" And somebody replied, "Yes, Sweden is also a great choice." And it appears under it because it's a reply, and all of that is handled amazingly, you know, with GraphQL, right? You don't need any fancy views or any fancy stuff. It's really, really easy. And we can also create a new post, right? So, we can write data, right? Because, you know, up to now, we've been kind of reading data, right, querying data. Here, we can create a new post. So, if I click here, that creates me like a new post, you know, "test title," post, James. And if I click on it, I can see that this is the title, this is the content, and there are no comments here. Okay.

And so, so we're able to get all the data that we need with one query. Okay, so let's go back into FlutterFlow, and let me show you exactly how I built this app. So, the first thing that you want to do is you want to configure your API call. Okay, that is the very, very first thing. Remember, we have this over here, right? If you go into your Hasura dashboard here, right? So, from এনHost, if you click here, you know, you're going to be seeing this screen, and you're, you can open up your Hasura dashboard here. And so what you want to do here is you want to get all of this because that is where you're going to be executing, you know, sending your API requests. That is where you're going to be getting your data, right? So, we have this POST request, and we have these two headers, right?

So, if I go into my app, I have this API request, and, and what's nice about it is just one API request. Okay, you can have multiple if you want; that's up to you. Those are optional, but all you really need is just one API request. And we have the name of the call, we have this, we have this over here, and then in the body, we are sending in the query, right? So, we can send the query in real time. This could be, you know, update something, this could be modify something. Here is just a variable, right? So, if I go over here, we see "query" is just a string, and then we're just sending it in this format, right? This way, our system, এনHost, is going to understand everything, right? And so now I can test things out, right? I can do a "response and test," and if I test out the API—and you want to do this, you want to make sure you're testing—you're going to be seeing this data. Okay, right here.

Now, what I like to do is when I'm dealing with APIs, I want to save them as a custom data type. I mean, that is an optional step. If you don't do that, then if you scroll down, you can deal with these JSON paths, but I prefer saving it as a custom data type. If you want to do that as well, then what you want to do is you want to copy all of this here, right? You can just do command A or control A, command C, and you want to come here, and you want to click here, and you want to call it something like "response" because that's all it is. It's a response that encapsulates other data, and you want to paste this here. Okay, and I'm not going to do that because I already did that. So, if you click on "create," it's going to go ahead and create all your data types, right? Starting from this "response," right? So, this "response" has "data," and the reason it has "data" is because if you go over here, right, this is our call, it starts off with "data," right?

So, this is great because you can kind of pick and choose the data that you need, as you're going to be seeing in just a second. And so it has "data," and then if