Side Project Stories #1 - Journal App

• 3 min read

Recently I began writing a journal again. Not the regular way of writing with a pen and paper and also not writing in one of the many apps out there. No, I've written a little application which asks me a set of questions ever day and I try to answer them as good as I can.

The application is inspired by the Cortex podcast, especially episode 66 and 68, and by Basecamp (My team recently tested Basecamp as a replacement for Trello and the "Automatic Check-in"-Feature caught my eye) In the podcast episodes Myke and Grey go over a list of questions the author of Triggers asks him self every day. The questions all follow the same pattern: "Did I do my best to ...?" (eg.: "Did I do my best to be happy today?")

I really like the concept of those questions. In the past I struggled to write into my journal as I didn't follow a concept or guide. I just have written what went through my head at the moment the notification popped up on my phone. Most entries have been quite boring. I thought, that with predefined questions my entries would have a common theme and I could look back and see how I've evolved over the days and weeks.

As I enjoy creating new apps and concepts I quickly scaffolded a new Laravel application and over 3 evenings I had my first prototype ready. The projects code name is Medivh.

The structure is really simple. As a user I can create multiple journals to keep things organized. Each journal then has many questions and each question can have many answers. Here are some screenshots how the app currently looks like:

Overview of all available Journals of the current user
Overview of all available Journals of the current user
Details view of a Journal. You see all active questions which are currently scheduled
Details view of a Journal. You see all active questions which are currently scheduled
Details view of a question. All previous answers are listed here, the schedule of the question is displayed and you can easily enable/disable the question.
Details view of a question. All previous answers are listed here, the schedule of the question is displayed and you can easily enable/disable the question.

I have no intentions of open sourcing the app but I want to share a bit of code of one of the core features.

A question can be scheduled to send a notification at a specified time and day of week. Luckily David Piesse already wrote a great article on laravel-news.com how you can easily add a Schedulable-Trait to your models. The trait assumes that a model has a timezone and expression. The timezone is currently stored on the User model, therefore I just used the relationship to get the value. The expression however is a tad more complex.

For each question there are 2 important columns which define the schedule: schedule_days and schedule_time_of_day. schedule_days is an array of the selected weekdays (eg.: ["Monday", "Friday"]). schedule_time_of_day contains the time when the notification should be sent (eg.: 09:00).

When the question is created or updated the cron expression is stored in an expression column. The following mutator creates the expression.

public function setExpressionAttribute($value)
{
    $time = Carbon::parse($this->schedule_time_of_day);
    $hour = $time->format('G');
    // Remove leading zeros from the minute string.
    $minute = ltrim($time->format('i'), '0');

    $minute = ($minute == '') ? '0' : $minute;

    // Convert the Array of Weekday Strings to a String of Weekday Numbers
    $dayOfWeek = collect($this->schedule_days)
        ->map(function($dayOfWeek) {
            return date('N', strtotime($dayOfWeek));
        })
        ->implode(',');

    $this->attributes['expression'] = "{$minute} {$hour} * * {$dayOfWeek}";
}

Some examples how the cron expression looks like for different scenarios:

  • Every Friday at 12:00: 0 12 * * 5
  • Every Weekday at 20:00: 0 20 * * 1,2,3,4,5

Together with the Schedulable-trait of the laravel-news.com article it's now really easy to schedule the notifications:

// app/Console/Kernel.php
/**
 * Define the application's command schedule.
 *
 * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
 * @return void
 */
protected function schedule(Schedule $schedule)
{
    $schedule->call(function() {
        Question::get()->filter->isDue()->each->sendNotification();
    })->everyMinute();
}

I've already written around 50 answers in my little app and I still enjoy answering the questions and reading through past answers. During the development I had many feature ideas and I've written them all down but I will first use the app for another 1 to 3 months and then see if I still enjoy using it. Only then I will start adding more features to it.

The message I want to give to you with this article is simple: If you have an idea for an app and you have the tools to build it: just do it!