Become a Full Stack Developer with Flutter and Serverpod — Build a Notes app

Build a CRUD Notes app with Flutter and Serverpod

Rawaha Muhammad
Flutter Community
7 min readApr 29, 2024

--

Why Flutter + Serverpod?

Flutter is a UI framework which you can use to build beautiful cross-platforms apps. Developers can use Flutter to write code in dart and build apps that they love. This is cool for offline apps or apps that depend on third party API’s. However, if a Flutter developer wants to build a full fledged app which also needs to save some data online, like a notes app, they need to write some server side functionality. Most Flutter Developers who don’t know backend technologies go for a server-less solution like Firebase. Firebase is great… until you have to write logic for complex calculations that are much better handled on a server rather than.. say, a mobile phone.

This is where

comes in, a framework that enables developers familiar with Dart, to write server side code.
It provides out of the box features like caching using Redis, a web server for hosting your web pages and code generation and ORM that enables for faster shipping.
This means that Flutter developers finally have the power to write beautiful apps along with their backend, all in dart.
AI is not going to steal our jobs, full stack Flutter developers will.

To get started, install and setup Flutter, Serverpod and Docker from these links given below:

Install & Setup Flutter:
https://docs.flutter.dev/get-started/install

Install & Setup Serverpod:
https://docs.serverpod.dev/

Install & Setup Docker Desktop:
https://docs.docker.com/get-docker/

Once you have them setup, verify whether they are setup correctly or not.

For Flutter, run flutter --version and check the output to verify everything has installed correctly.

output of flutter — version

do the same for Serverpod by running serverpod version

output of serverpod version

Now, navigate to where you want to create the project and once there run serverpod create [project name]which in our case will be serverpod create notes

output after running “serverpod create notes”

Now open this project in your favorite IDE

open the notes_server directory and go to lib/src/models and create a new model called note.spy.yaml

Inside the file add this:

class: Note
fields:
title: String
description: String

This will create a Note model and the best part is that we will be able to access this model inside our Flutter project as well, thanks to notes_client which is responsible for connecting the dots between the server and the flutter app.

Save the file and open up the terminal, cd into notes_server and run serverpod generate which will generate the model classes for you.

Similarly, if you are going to make a lot of changes you can also run serverpod generate --watch which will watch for changes and generate the files accordingly

Output after running “serverpod generate”

Go to lib/src/generated and you will see a note.dart file there which contains the generated model.

The note.dart file inside lib/src/generated

Now, go to lib/src/endpoints and create a file called notes_endpoint.dart

notes_endpoint.dart in lib/src/endpoints

Create a class called NotesEndpoint that extends Endpoint and create a method called getNotes . This method will return a list of the Note type model that we created. So go ahead and return a list with one sample Note

Endpoints are supposed to return Futures of a serializable object, primitive datatype (like double, int, String, List or Map), or void. So make sure to mark it like that and add the async keyword.

The first parameter of an endpoint should always be a Session object which includes info about the current session and some helper methods.

Let’s test this sample endpoint and then we’re going to interact with the database.

To start the server first run your Docker Desktop and go back to your terminal and run docker compose up --build --detach

output of “docker compose up — build — detach”

After that, run dart bin/main.dart --apply-migrations which will help us apply changes to the db schema and run the server’s main.dart file.

output of “dart bin/main.dart — apply-migrations”

As shown in the output, our server is now running on localhost:8080

Let’s open up the notes_flutter project and try to make an api call to the NotesEndpoint that we created in the notes_server project

In notes_flutter/lib/main.dart edit the _callHello() method.

Replace

final result = await client.example.hello(_textEditingController.text);

with

final result = await client.notes.getNotes();

Then resolve the type errors by replacing it with relevant data types

Change

String? _resultMessage

to

Note? _resultMessage

and then

_resultMessage = result;

to

resultMessage = result.first;

Then scroll down and change

resultMessage: _resultMessage,

to

resultMessage: _resultMessage?.title,

These changes will help us display the title of the first element of the Notes that is returned from the server, which will be “Example Title”

Now run the app

App’s display before pressing the “Send to Server” button

and press the “Send to Server” button, which will then request data from server using the getAllNotes method and then return our list of notes.

The app’s display will change from “No server response yet.” to “Example Title”

App’s display after pressing the “Send to Server” button

It is interesting to note that all of the heavy lifting was done by the client with the generated code. We didn’t parse the json, and we used the same Note class inside the server and the flutter code.

Let’s make changes to the server so we can perform CRUD operations on the database

Go to the note model that we created in notes_server/lib/src/models/note.spy.yaml and edit it to include a table name.

Table name “note” added to the Note model

Run serverpod generate since we made changes to our Note model

After that, run serverpod create-migration which will run some code to generate the database schema as mentioned in our file.

Output of “serverpod — create-migration”

Then run dart run bin/main.dart --role maintenance --apply-migrations to start the server in maintenance mode, apply our created migrations and shut it down once it’s done.

Output of “dart run bin/main.dart — role maintenance — apply-migrations”

Remember to run these commands again if you change anything in your models.

You can view your database at this point. Download postico and connect it to your database using the configurations already provided in notes_server/config directory in development.yaml and passwords.yaml files

After you have installed and setup, you should be able to see your connected db and the note table

Postico db with note table

Let’s go ahead and write code for Create operation

Navigate to notes_endpoint.dart file and create a method called insertNote

insertNote method

We’re using the model’s db variable to insert a row inside the table and then returning the inserted model.

Run serverpod generate

Go to notes_flutter and to lib/main.dart file.

Go to the _callHello method and change the client.notes.getNotes to client.notes.insertNote and change the result.first to result

_callHello method

Run the server by running docker compose up --build --detach and dart bin/main.dart --apply-migrations

Launch the flutter app and press the “Send to Server” button again and you should see the title of the note displayed in green

App display after pressing “Send to Server” button

We can verify the entry by hitting the refresh button on the Postico app

Postico with inserted data

Great, our create operation is working, let’s go back to notes_server and in notes_endpoints.dart write methods for all the other operations

Endpoint methods for CRUD operations

Run serverpod generate and then head to the notes_flutter app.

We are going to create 3 more buttons. First edit the “Send to Server” button to say “Add Note”, then copy and paste the code to create 3 more buttons and let’s make them display “Update”, “Delete”, and “Get Notes”.

“Send to Server” button changed to “Add Note” and copy pasted “Update”, “Delete” and “Get Notes” methods

Now edit the _addNote , _updateNote , _deleteNote and _getAllNotes methods to change their method calls

_addNote method
_updateNote method
_deleteNote method
_getAllNotes method

Remember to also change the Note? _resultMessage variable to String? _resultMessage

You can now run the application, press the buttons to perform CRUD operations, play around with different values and check Postico to make sure your data is being reflected in the database

That’s it! You just learned how to work with

and Flutter to build a CRUD notes app.

At this point, you are deemed worthy of being called a Full stack Flutter Developer, capable of stealing jobs from your average Flutter Devs.

If you liked the tutorial…

Please follow me here and on my socials!

Follow me:

Youtube: https://www.youtube.com/channel/UCD2BEqL0wC7leFKm4i9_aRg
LinkedIn: https://www.linkedin.com/in/rawahamuhammad/
Github: https://github.com/coffiie
Medium:

Follow Runtime Snippets (bite-sized Flutter/Dart tutorials)

Youtube: https://www.youtube.com/channel/UCD2BEqL0wC7leFKm4i9_aRg
LinkedIn: https://www.linkedin.com/company/100042850
Twitter: https://twitter.com/runtimesnippets

--

--