Become a Full Stack Developer with Flutter and Serverpod — Build a Notes app
Build a CRUD Notes app with Flutter and Serverpod
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 Serverpod 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.
do the same for Serverpod by running 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
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
Go to lib/src/generated
and you will see a note.dart
file there which contains the generated model.
Now, go to lib/src/endpoints
and create a file called notes_endpoint.dart
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
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.
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
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”
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.
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.
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.
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
Let’s go ahead and write code for Create operation
Navigate to notes_endpoint.dart
file and create a method called insertNote
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
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
We can verify the entry by hitting the refresh button on the Postico app
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
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”.
Now edit the _addNote
, _updateNote
, _deleteNote
and _getAllNotes
methods to change their method calls
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 Serverpod 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: Rawaha Muhammad
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