This is the beginning of a series of articles describing the work we did for Timy Messenger, a messaging app for groups to communicate and organize themselves. Build with flutter.
In this article I will explain the project structure both for the Flutter app and for the Firebase Cloud Functions.
This app is open source, and in this articles I will be explaining some of the insides and coding we did.
As listed in the project README.md, these are the main features of the app:
- Multiple groups (similar to Teams in Slack).
- Multiple open or private channels within groups.
- Sharing of photos and photo collections.
- React to messages with emoji.
- Push-notifications for message and channel updates.
- Specific channels for events (e.g. containing date, venue).
- Editing of event channels.
- Calendar for all upcoming and passed events aggregated over all groups and channels.
- English and German localization.
- RSVP for events.
The app follows the normal Flutter app structure. The Android and iOS code are located in their respective folders, and the Flutter code is located in the
However, we also have a
The project uses Firestore as database and “backend” and Firebase Storage to store all user’s pictures. It also uses Firebase Cloud Messaging push notifications, triggered by changes in the database (e.g. when a user joins a channel).
Another important Firebase library used is Authentication. We used it to perform email based login. However the app doesn’t have registration process and we registered users manually.
We also implemented a custom logging mechanism that reports to Crashlytics for production builds.
The app architecture is feature based and uses Redux for state management.
The features are split in: Calendar, Channel, Files (attachments), Groups, Messages and Users, Push Notifications and Authentication logic.
The final package structure is as follows:
datacontains all the data repositories for the different types of data we have: Calendar, Channel, Files, Groups, Messages and Users.
domain.reduxcontains all Redux files (Actions, Middlewares and Reducers)
domain.redux, each main app feature also has a subpackage containing its actions, middleware functions and reducer functions.
Example of Redux logic for the Calendar feature
modelcontains the application data model (User class, Channel class, etc.) All classes are BuiltValues, meaning they are immutable and also provide generated builders, equals operations and toString methods.
native_channelscontains the code logic to communicate with the Android and iOS native code. For example, to handle permissions or load thumbnails.
presentationis the heaviest package and it contains all the UI logic split by features.
Example of presentation feature
utilcontains different utilities that don’t fit the rest of the packages, like our custom logger or all date formatting logic.
- Some files remain top level: the main method, the root application Widget, the Routes and the Theme.
Assets and Fonts
The application uses PNGs for all assets and are all contained inside
assets/graphics These assets have been exported from Sketch using the 3x setting.
The app uses Edmondsans and Poppins for fonts and they are located inside the
The project contains tests for all the application logic:
- Data parsing on the repositories.
- Redux logic: Middleware and Reducer functions.
- Some Widget testing.
The project also features an
analysis_options.yaml file which excludes generated code.
firebase folder you will find all the Firebase Cloud Functions and access rules from the app.
The code is split in three parts:
scripts and the root folder files.
functions you find all the Firebase Cloud Functions, which are separated in files for each individual function.
For example, the function that performs an action when a user joins a channel is located in
All functions are exported in the
index.js as well as two Cron jobs.
The Cron jobs, located in the
cron folder, are used to notify users about upcoming events that they have RSVP’d.
scripts you can find a couple of scripts that automate the database creation process. The
group-create.js contains a function that can create a Group and add all existing users to them, this is the script we use to create a testing database each time.
In the root folder you will find
firestore.rules, which specifies some of the access rules to Firestore. Note that those rules are not complete and so it contains unresolved security issues.
Current Project State
The project is presented as it is and not the owners or the maintainers can warranty its functionality.
Currently two important features are missing: The ability to register as User and the ability to create Groups.
To register new users, you will have to do it through the Authentication console in Firebase, and add your users there.
Also, add a new User entry in the
/users/ collection in Firestore.
To create a group, you will have to manually create the data structure in Firebase. You can use the
group-create.js script to automate that process.
Users need to be added to Groups manually too, and that process can be found in the mentioned script.
I hope you enjoyed this first look at the project structure and helps you as inspiration for your next project.
In the second part, I explain the CirclesApp top level Widget which contains the Redux Store configuration, Routes, localization delegates and Theme.
Thanks for reading!