Quick start
This quick-start guide will teach you how to build a simple backend for a blog and expose a set of declarative APIs to power your frontend experience. In the blog, every author is a user that publishes many posts. The relationship between user and post can be described as follows:
One user can have many posts and a post can belong to only one user
Let's get started!
Create a new application
Directly after authenticating, you'll be prompted to create a new application. Click "Create new application" and choose a name for your blog.

Create a new model
Our blog’s schema is going to need a post model, where each Post
record represents a blog post. In order to create the post model click on the “+” icon to the right of the ‘Models’ and give your model a name, say Post
, since we’re building a model for our blog posts.

You'll notice that every model in Gadget comes with a set of non-configurable system fields: ID, State, Created At, Updated At. These fields cannot be added or removed from a model and allow Gadget to track the a record's lifecycle for you. Let’s teach Gadget that our blog posts have additional attributes. We can do this by adding fields. Click on “Add field” and name the new field you created ‘Title’. This field will store all of our blog post’s titles. Set the field type to String.
Finally, let’s add a couple of validations to this field. Make the field required by adding a Required
validation. Let’s also add a string length validation to ensure that none of our writers put up ridiculously long titles. Once finished, your field should look like this:

Let’s define another field to hold the body of each blog post and call it Content. For the field type, choosing RichText will allow authors to include media files in their blog posts. Let’s also make this field required. Your field should look like this once finished:

Add a relationship
In Gadget relationships between models are created using fields (like BelongsTo) that enable you to model your data with models that are otherwise unrelated to each other in a normalized fashion. Like foreign keys in SQL, one model receives and stores the ID in it's own data to set up the relationship.
Let’s create a relationship between our Post model and the default User model provided by Gadget which powers authentication and permissions.
To build this relationship, go to the User
model and add a new field called Posts
. This field will store a post object on your user model. Select a Has Many relationship type from the field type dropdown and point it at the Post model we created earlier. In Gadget, relationships are modeled as fields so we'll need to create the inverse side of this relationship on the Post model. Let's call this field User
. Your field should look like this once completed:

Adding a publishing workflow to our blog
Now we have a way to create users and blog posts, let's add some logic that allows us to only show potential readers posts that are published by adding a new Published
state. Click the behavior icon in the left navigation menu to check out the state chart for the Post
model.

Gadget represents a model's behaviors in an editable state chart. Your state chart should look like this:

To build our publishing workflow, we'll add two new substates inside the created state. These states will be called 'Unpublished' and 'Published' which represent the initial state of a blog post upon creation ('Unpublished') and the action to transitions a record into a Published state. For the purposes of this guide, we won't define an action to unpublish a post, though that would be a useful feature to add later.
First, let's add the Unpublished
state to the state chart. Select the created state and press the add state button.

In the action panel on the right, change the name from New State
to Unpublished
. Note the circle with a black dot in it above the Unpublished
state. This indicates that this is the initial state of the record, as soon as it's created.

Next, let's add a sibling state called Published. To do this, click on the -> button on Unpublished
.

Once that is done, we can add an action that will transition our record from Unpublished
to Published
. Click on the arrow between two new states and change the name of the action to Publish
.

That's it for the state chart. Let's move on to defining the behavior of our API.
Interaction with the generated API
Your schema is now ready to start being used! To do this we'll send queries to the automatically generated GraphQL API that Gadget creates for all apps.
The automatically generated API in Gadget allows nested mutations. We'll be leveraging that to create a user and their blog posts at the same time.
1mutation {2 createUser(3 user: {4 email: "[email protected]"5 password: "fake-password"6 posts: [7 {8 create: {9 title: "My first blog post"10 content: { markdown: "How cool is _this_?" }11 }12 }13 ]14 }15 ) {16 success17 errors {18 __typename19 message20 code21 }2223 user {24 id25 email26 posts {27 edges {28 node {29 id30 title31 content {32 truncatedHTML # rich text fields in Gadget support options on how to present the stored data33 html34 markdown35 }36 }37 }38 }39 }40 }41}
You can view your data in the User
and Post
data viewers by clicking on the database icon (pictured below) to see the new records we've created!


And to publish the blog post we just created above, you can run the GraphQL mutation below. Make sure to use the correct post ID!
1mutation PublishPost($id: GadgetID!) {2 publishPost(id: $id) {3 success4 errors {5 message6 }7 post {8 id9 title10 content {11 markdown12 }13 }14 }15}
{"id": 1}
Congratulations! You've just built a simple backend for a blog with a generated GraphQL API. If you'd like to learn more about Gadget you can check out the other guides available in the sidebar!