<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: friendship</title>
    <description>The latest articles on DEV Community by friendship (@friendship_e3d5e249468fc3).</description>
    <link>https://dev.to/friendship_e3d5e249468fc3</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3469234%2Fa7503af9-558d-46ce-8390-af0f334afb31.jpg</url>
      <title>DEV Community: friendship</title>
      <link>https://dev.to/friendship_e3d5e249468fc3</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/friendship_e3d5e249468fc3"/>
    <language>en</language>
    <item>
      <title>Shipaton: Do0ne Build Journal #5 - Social Feature: Discover Goals &amp; Tasks</title>
      <dc:creator>friendship</dc:creator>
      <pubDate>Mon, 15 Sep 2025 15:38:14 +0000</pubDate>
      <link>https://dev.to/friendship_e3d5e249468fc3/shipaton-do0ne-build-journal-5-social-feature-discover-goals-tasks-4mp</link>
      <guid>https://dev.to/friendship_e3d5e249468fc3/shipaton-do0ne-build-journal-5-social-feature-discover-goals-tasks-4mp</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0zexbehdwszl9qpxiq65.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0zexbehdwszl9qpxiq65.jpg" alt="Image Do0ne development at the 24-hour café “The November.”" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Objective&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implement a feature that allows users to view other people’s &lt;strong&gt;Goals&lt;/strong&gt; and &lt;strong&gt;Do0ne&lt;/strong&gt; items.&lt;/li&gt;
&lt;li&gt;Provide a Like feature to cheer for each Goal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Implementation Plan&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a &lt;strong&gt;Discover menu&lt;/strong&gt; to display other users’ Goals and Do0ne lists.&lt;/li&gt;
&lt;li&gt;Add a &lt;strong&gt;field in each Goal&lt;/strong&gt; document to store the number of Likes.&lt;/li&gt;
&lt;li&gt;Create a &lt;strong&gt;Likes subcollection&lt;/strong&gt; under each Goal to track which users pressed Like.&lt;/li&gt;
&lt;li&gt;Restrict Likes to &lt;strong&gt;once per day&lt;/strong&gt; per user.&lt;/li&gt;
&lt;li&gt;Add a &lt;strong&gt;Likers subcollection&lt;/strong&gt; to record each user’s Like history (when and how many times).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If one Goal has 20 Do0ne items and a user has 100 Goals, one full read requires 21 × 100 = 2,100 Firestore Reads.&lt;/li&gt;
&lt;li&gt;If 10 users perform this action, it results in &lt;strong&gt;21,000 Reads&lt;/strong&gt;, which is too costly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run a &lt;strong&gt;Cloud Function&lt;/strong&gt; on a schedule to generate snapshot JSON files containing Goals and Do0ne data.&lt;/li&gt;
&lt;li&gt;FlutterFlow will load these JSON snapshots via &lt;strong&gt;API calls&lt;/strong&gt; instead of reading directly from Firestore.&lt;/li&gt;
&lt;li&gt;This reduces Firestore Reads since users fetch pre-generated JSON instead of live documents.&lt;/li&gt;
&lt;li&gt;Some information still requires real-time updates:&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Like count and whether the current user has Liked&lt;/strong&gt; must be up-to-date.&lt;/li&gt;
&lt;li&gt;Therefore, Firestore is read &lt;strong&gt;only when a Goal is displayed&lt;/strong&gt; to fetch its latest Like data.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foshu07gkyutumxg1hkax.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foshu07gkyutumxg1hkax.jpg" alt="Image JSON snapshot file generated from Goal and Do0ne data" width="800" height="924"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FlutterFlow Implementation&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create an &lt;strong&gt;API call&lt;/strong&gt; to load the snapshot JSON file.&lt;/li&gt;
&lt;li&gt;Bind the API response to a &lt;strong&gt;PageView&lt;/strong&gt;, generating Goal pages dynamically.&lt;/li&gt;
&lt;li&gt;When a PageView page becomes active, fetch the &lt;strong&gt;latest Like data&lt;/strong&gt; from Firestore for that Goal.&lt;/li&gt;
&lt;li&gt;Implement &lt;strong&gt;Like / Unlike functionality&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Actual Implementation&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fetching Goal data only when a PageView becomes active didn’t work reliably, so the entire dataset is now loaded when the &lt;strong&gt;PageView is first created&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;This eliminated the Read-saving advantage, so &lt;strong&gt;pagination&lt;/strong&gt; was introduced when generating snapshots: each JSON file contains only 10 Goals.&lt;/li&gt;
&lt;li&gt;When the user reaches the last PageView page, the app requests the &lt;strong&gt;next snapshot API&lt;/strong&gt; and appends the new pages dynamically.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;View Likes on my Goal from others&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4qhar86lvot9yaifgdmt.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4qhar86lvot9yaifgdmt.PNG" alt="Image View Likes on my Goal from others" width="800" height="1739"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Discover lets you see others’ Goals and Do0ne and cheer them on with Likes&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0vgd563kyyvdxj6uzi7k.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0vgd563kyyvdxj6uzi7k.PNG" alt="Image Discover lets you see others’ Goals and Do0ne and cheer them on with Likes" width="800" height="1739"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>backend</category>
      <category>devjournal</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Shipaton: Do0ne Build Journal #4 - Do0ne Timer Built with a Custom Widget</title>
      <dc:creator>friendship</dc:creator>
      <pubDate>Fri, 12 Sep 2025 10:16:14 +0000</pubDate>
      <link>https://dev.to/friendship_e3d5e249468fc3/shipaton-do0ne-build-journal-4-do0ne-timer-built-with-a-custom-widget-6e3</link>
      <guid>https://dev.to/friendship_e3d5e249468fc3/shipaton-do0ne-build-journal-4-do0ne-timer-built-with-a-custom-widget-6e3</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fntdh971j0t6gxy5u71ec.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fntdh971j0t6gxy5u71ec.jpg" alt="Image working in a cafe shop" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;New Improvement&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While entering and executing Do0ne tasks, I noticed a boost in productivity. Then I came up with an idea to make it even better: providing &lt;strong&gt;visual stimulation to stay focused and finish faster&lt;/strong&gt;. To achieve this, I decided to start a timer whenever a Do0ne task is created, so that its elapsed time could be tracked.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2pczsldkjr1vlderk0b8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2pczsldkjr1vlderk0b8.png" alt="Image Screenshot of the Do0ne timer on screen" width="800" height="1739"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FlutterFlow Timer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;FlutterFlow offers a built-in timer widget that supports both &lt;strong&gt;Count Down&lt;/strong&gt; and &lt;strong&gt;Count Up&lt;/strong&gt; modes. However, the formatting options are limited, and it couldn’t display time in &lt;strong&gt;day units&lt;/strong&gt;, which I wanted. After exploring different options, I decided to use &lt;strong&gt;FlutterFlow’s Custom Widget&lt;/strong&gt; feature.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr9b1he49t7kcg0g8lzdk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr9b1he49t7kcg0g8lzdk.png" alt="Image List of FlutterFlow timer formats" width="600" height="866"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custom Widget&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A Custom Widget in FlutterFlow allows you to embed your own Flutter code into the app as a widget. It’s useful for implementing advanced features or designs that default widgets can’t support.&lt;/p&gt;

&lt;p&gt;After writing the basic timer logic, I encountered a few issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;There were no built-in UI options to &lt;strong&gt;style the timer text&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The timer text was &lt;strong&gt;left-aligned by default&lt;/strong&gt;, and the alignment property provided in the widget settings didn’t work as expected.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I resolved all three issues directly in the Custom Widget code. This allowed me to format the timer output and style it exactly the way I wanted.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I added additional alignment code to the widget’s text and its constituent elements.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;textAlign: TextAlign.center
child: Center(child: text),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;The timer font style can use the color theme defined in FF with the following code.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    final text = Text(
      _elapsed,
      textAlign: TextAlign.center,
      style: FlutterFlowTheme.of(context).bodyMedium.override(
            fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily,
            fontSize: 14.0,
            fontWeight: FontWeight.w400,
            color: textColor,
          ),
      softWrap: false,
    );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Completed Timer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now the elapsed time for each Do0ne task is displayed correctly. I also added &lt;strong&gt;three color variations&lt;/strong&gt; depending on the situation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Within 4 hours: Default color&lt;/li&gt;
&lt;li&gt;Exceeding 12 hours: Warning color&lt;/li&gt;
&lt;li&gt;Exceeding 24 hours: Alert color&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A screenshot of the completed UI is attached below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwp9oges8qjdq289clftb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwp9oges8qjdq289clftb.jpg" alt="Image Timer color changes based on elapsed time" width="800" height="580"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Additional UI Adjustment&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As the number of completed Do0ne tasks increased, the list area started growing too large. I resized the list section to keep the UI clean and easy to read.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qkohssqxho6nb86v770.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qkohssqxho6nb86v770.jpg" alt="Image Log0ne list UI changes - Left (Before), Right (After)" width="800" height="869"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>flutterflow</category>
      <category>shipaton</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>Shipaton: Do0ne Build Journal #4 - Do0ne Timer Built with a Custom Widget</title>
      <dc:creator>friendship</dc:creator>
      <pubDate>Fri, 12 Sep 2025 10:16:14 +0000</pubDate>
      <link>https://dev.to/friendship_e3d5e249468fc3/shipaton-do0ne-build-journal-4-do0ne-timer-built-with-a-custom-widget-1ea8</link>
      <guid>https://dev.to/friendship_e3d5e249468fc3/shipaton-do0ne-build-journal-4-do0ne-timer-built-with-a-custom-widget-1ea8</guid>
      <description>&lt;p&gt;&lt;strong&gt;New Improvement&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While entering and executing Do0ne tasks, I noticed a boost in productivity. Then I came up with an idea to make it even better: providing &lt;strong&gt;visual stimulation to stay focused and finish faster&lt;/strong&gt;. To achieve this, I decided to start a timer whenever a Do0ne task is created, so that its elapsed time could be tracked.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2pczsldkjr1vlderk0b8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2pczsldkjr1vlderk0b8.png" alt="Image Screenshot of the Do0ne timer on screen" width="800" height="1739"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FlutterFlow Timer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;FlutterFlow offers a built-in timer widget that supports both &lt;strong&gt;Count Down&lt;/strong&gt; and &lt;strong&gt;Count Up&lt;/strong&gt; modes. However, the formatting options are limited, and it couldn’t display time in &lt;strong&gt;day units&lt;/strong&gt;, which I wanted. After exploring different options, I decided to use &lt;strong&gt;FlutterFlow’s Custom Widget&lt;/strong&gt; feature.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr9b1he49t7kcg0g8lzdk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr9b1he49t7kcg0g8lzdk.png" alt="Image List of FlutterFlow timer formats" width="600" height="866"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custom Widget&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A Custom Widget in FlutterFlow allows you to embed your own Flutter code into the app as a widget. It’s useful for implementing advanced features or designs that default widgets can’t support.&lt;/p&gt;

&lt;p&gt;After writing the basic timer logic, I encountered a few issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;There were no built-in UI options to &lt;strong&gt;style the timer text&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The timer text was &lt;strong&gt;left-aligned by default&lt;/strong&gt;, and the alignment property provided in the widget settings didn’t work as expected.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I resolved all three issues directly in the Custom Widget code. This allowed me to format the timer output and style it exactly the way I wanted.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I added additional alignment code to the widget’s text and its constituent elements.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;textAlign: TextAlign.center
child: Center(child: text),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;The timer font style can use the color theme defined in FF with the following code.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    final text = Text(
      _elapsed,
      textAlign: TextAlign.center,
      style: FlutterFlowTheme.of(context).bodyMedium.override(
            fontFamily: FlutterFlowTheme.of(context).bodyMediumFamily,
            fontSize: 14.0,
            fontWeight: FontWeight.w400,
            color: textColor,
          ),
      softWrap: false,
    );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Completed Timer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now the elapsed time for each Do0ne task is displayed correctly. I also added &lt;strong&gt;three color variations&lt;/strong&gt; depending on the situation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Within 4 hours: Default color&lt;/li&gt;
&lt;li&gt;Exceeding 12 hours: Warning color&lt;/li&gt;
&lt;li&gt;Exceeding 24 hours: Alert color&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A screenshot of the completed UI is attached below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwp9oges8qjdq289clftb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwp9oges8qjdq289clftb.jpg" alt="Image Timer color changes based on elapsed time" width="800" height="580"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Additional UI Adjustment&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As the number of completed Do0ne tasks increased, the list area started growing too large. I resized the list section to keep the UI clean and easy to read.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qkohssqxho6nb86v770.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qkohssqxho6nb86v770.jpg" alt="Image Log0ne list UI changes - Left (Before), Right (After)" width="800" height="869"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Shipaton: Do0ne Build Journal #3 - Do0ne 1.0, First Stable Version Completed</title>
      <dc:creator>friendship</dc:creator>
      <pubDate>Thu, 11 Sep 2025 07:23:58 +0000</pubDate>
      <link>https://dev.to/friendship_e3d5e249468fc3/shipaton-do0ne-build-journal-3-do0ne-10-first-stable-version-completed-11bh</link>
      <guid>https://dev.to/friendship_e3d5e249468fc3/shipaton-do0ne-build-journal-3-do0ne-10-first-stable-version-completed-11bh</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1l07wazo13g5ebypuawz.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1l07wazo13g5ebypuawz.PNG" alt="Image The stable 1.0 version completed after 11 tasks were finished" width="800" height="1739"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day 3 Work&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Today, I wrapped up bug fixes and UI improvements for Do0ne 1.0 while working from home. With this, the first stable version of Do0ne is now complete, and all core features are functioning as intended.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fixes and Improvements&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Added hint messages for Goal / Do0ne input fields&lt;/strong&gt;&lt;br&gt;
For first-time users, it may not be clear what to type in the input fields. I added hint messages to guide the user when entering a Goal or Do0ne. This will continue to evolve with further updates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Changed task sorting to newest-first&lt;/strong&gt;&lt;br&gt;
Completed Do0ne items were previously shown in chronological order (oldest first). I updated the list to display newest-first. Mistakes like this in data sorting are common in the early stages of app development. 😅&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Fixed negative Goal elapsed days bug&lt;/strong&gt;&lt;br&gt;
A bug caused Goal elapsed days to show negative values. It turned out to be a simple error in setting the reference date parameter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Removed Do0ne elapsed days&lt;/strong&gt;&lt;br&gt;
The elapsed days display for Do0ne items was removed. While using the app, I often come up with ideas to help maintain focus. I decided to try a new approach in the next update, and I’m looking forward to seeing how effective it will be in real use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Added Complete / Delete buttons&lt;/strong&gt;&lt;br&gt;
Added Complete and Delete buttons below the Do0ne input field to improve usability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before moving on to new social features, I focused on polishing the basics and fixing key bugs. While focus during work is important, achieving goals requires steady daily effort.&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;Do0ne&lt;/strong&gt;, I can record and track my progress while completing one essential task each day. This helps me consistently think of and act on the most important item, which is becoming a valuable habit and moving me closer to my goals.&lt;/p&gt;

&lt;p&gt;As of today, a total of &lt;strong&gt;11 Do0ne tasks&lt;/strong&gt; have been completed.&lt;/p&gt;

</description>
      <category>shipaton</category>
      <category>flutterflow</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>Shipaton: Do0ne Build Journal #2 - Using Do0ne in Practice &amp; Custom Loading Screen with Lottie Icons</title>
      <dc:creator>friendship</dc:creator>
      <pubDate>Wed, 10 Sep 2025 05:53:19 +0000</pubDate>
      <link>https://dev.to/friendship_e3d5e249468fc3/shipaton-do0ne-build-journal-2-using-do0ne-in-practice-custom-loading-screen-with-lottie-icons-2oan</link>
      <guid>https://dev.to/friendship_e3d5e249468fc3/shipaton-do0ne-build-journal-2-using-do0ne-in-practice-custom-loading-screen-with-lottie-icons-2oan</guid>
      <description>&lt;p&gt;&lt;strong&gt;Day 2 Begins&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5t2cmthaaowny30uv4ny.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5t2cmthaaowny30uv4ny.jpg" alt="Image Do0ne development at 24-hour café “The November”" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today, I started the second day of work at a 24-hour café with a cup of coffee. I continued the project by actually &lt;strong&gt;using Do0ne&lt;/strong&gt;, the app I built with basic functionality on Day 1.&lt;/p&gt;

&lt;p&gt;For Shipaton, I set the goal as &lt;strong&gt;“Launching the Do0ne app.”&lt;/strong&gt; To reach this goal, I registered and completed the necessary tasks one by one, which also allowed me to validate Do0ne’s workflow from a real user’s perspective.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fykbcm67ekwqgbmd04a00.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fykbcm67ekwqgbmd04a00.PNG" alt="Image Setting my goal at Shipaton as launching Do0ne" width="800" height="1739"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits from Real Usage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Previously, when organizing app development tasks, I used to write down everything, assign priorities, and schedule them by date—a process that often felt cumbersome and tiring.&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;Do0ne&lt;/strong&gt;, the experience was different:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I only needed to register one immediate task at a time, making it much easier to stay focused.&lt;/li&gt;
&lt;li&gt;Having the current task displayed prominently at the center of the screen gave me extra motivation to finish it quickly.&lt;/li&gt;
&lt;li&gt;Since I had chosen this task as the most important one, I could work on it without worrying about all the other pending tasks, which gave me peace of mind.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach felt refreshingly different from conventional to-do apps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpvpuc15qk343wvpbuyua.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpvpuc15qk343wvpbuyua.png" alt="Image Prioritizing the most important development tasks using Do0ne" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FlutterFlow: Custom Loading Screen with Lottie Icons&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Previous Approach&lt;/strong&gt;&lt;br&gt;
FlutterFlow has a default loading indicator, but it only shows an animation on the clicked button itself. This made it hard to tell whether the app was truly loading, and visually it wasn’t very appealing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I Wanted&lt;/strong&gt;&lt;br&gt;
I wanted a &lt;strong&gt;large loading icon centered on the screen&lt;/strong&gt;, styled with a more polished animation that fit the overall design of the app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Downloaded a preferred loading animation from &lt;a href="https://lottiefiles.com/" rel="noopener noreferrer"&gt;LottieFiles&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Created a &lt;strong&gt;Custom Dialog&lt;/strong&gt; in FlutterFlow and inserted the loading component. &lt;/li&gt;
&lt;li&gt;Configured the Action Block to call the Custom Dialog with &lt;strong&gt;Non-Dismissible&lt;/strong&gt; (to prevent it from closing by tapping the screen) and &lt;strong&gt;Non-Blocking&lt;/strong&gt; (to allow subsequent actions to run) options enabled. &lt;/li&gt;
&lt;li&gt;The logic was: display the loading component, run the process, and then close the loading component afterward.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyglroaswktuz0zzgohhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyglroaswktuz0zzgohhd.png" alt="Image FlutterFlow Loading Component with LottieFiles icon" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;On Day 2, I &lt;strong&gt;tested Do0ne in real usage&lt;/strong&gt; and confirmed its core strength: helping me focus on one task at a time. I also implemented a &lt;strong&gt;custom loading screen with Lottie icons&lt;/strong&gt;, which improved the app’s UI beyond the default FlutterFlow loader. By the end of the day, I could clearly see Do0ne evolving into a more practical tool for real use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fun Element&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So far, I’ve completed &lt;strong&gt;7 tasks&lt;/strong&gt;. Compared to predefining dozens or even hundreds of tasks in advance, this approach feels much lighter and more motivating. I’m curious to see how many tasks will have been completed by the time Do0ne is fully launched, and I’m excited to discover just how much I will have accomplished.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F431qts08tv0xz8d5ftiw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F431qts08tv0xz8d5ftiw.jpg" alt="Image Currently completed 7 tasks in Do0ne" width="800" height="679"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Shipaton: Do0ne Build Journal #1 - Project Setup &amp; First Build Complete</title>
      <dc:creator>friendship</dc:creator>
      <pubDate>Tue, 09 Sep 2025 07:15:25 +0000</pubDate>
      <link>https://dev.to/friendship_e3d5e249468fc3/shipaton-do0ne-build-journal-1-project-setup-first-build-complete-i0m</link>
      <guid>https://dev.to/friendship_e3d5e249468fc3/shipaton-do0ne-build-journal-1-project-setup-first-build-complete-i0m</guid>
      <description>&lt;p&gt;&lt;strong&gt;Project Goal&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For Shipaton 2025, the key objective is to build a fully functional app in a very short timeframe. It not only needs to work flawlessly but also look visually appealing. Do0ne is designed to run on as many platforms as possible—not limited to just iOS and Android.&lt;/p&gt;

&lt;p&gt;To achieve this, I selected the following tools and services for development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. FlutterFlow&lt;/strong&gt;&lt;br&gt;
The core development of Do0ne will be done with FlutterFlow (FF).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multi-platform support: Build once, deploy to iOS, Android, Web, and even Desktop.&lt;/li&gt;
&lt;li&gt;Automatic translation: Quickly localize Firestore data and UI text for multiple languages, enabling easy global expansion.&lt;/li&gt;
&lt;li&gt;Easy Firebase integration: Firestore, Authentication, and Storage can be connected seamlessly.&lt;/li&gt;
&lt;li&gt;Built-in support for RevenueCat &amp;amp; OneSignal: In-app purchases and push notifications can be integrated directly with prebuilt actions.&lt;/li&gt;
&lt;li&gt;Rich UI components: Pre-designed templates, widgets, and themes allow for polished designs with minimal effort.&lt;/li&gt;
&lt;li&gt;Custom Action/Widget extensibility: When built-in blocks aren’t enough, developers can extend functionality with custom code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. OneSignal&lt;/strong&gt;&lt;br&gt;
For push notifications and in-app messaging, OneSignal was chosen.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multi-channel communication: Manage push notifications, emails, and SMS all in one place.&lt;/li&gt;
&lt;li&gt;Advanced targeting: Deliver personalized notifications based on user attributes and behavior.&lt;/li&gt;
&lt;li&gt;In-app messaging: Display contextual messages inside the app triggered by events like sign-in or purchase completion.&lt;/li&gt;
&lt;li&gt;Analytics &amp;amp; optimization: Monitor delivery stats in real time and run A/B tests to improve performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. RevenueCat&lt;/strong&gt;&lt;br&gt;
In-app purchases and subscription management are handled by RevenueCat.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cross-platform purchase management: Unifies App Store, Google Play Billing, and Stripe under a single API.&lt;/li&gt;
&lt;li&gt;Product / Offering / Package model:&lt;/li&gt;
&lt;li&gt;Product: A subscription or purchase item registered in the app stores.&lt;/li&gt;
&lt;li&gt;Offering: A collection of products grouped into what users see as a package.&lt;/li&gt;
&lt;li&gt;Package: A specific price and duration combination (e.g., monthly, yearly).&lt;/li&gt;
&lt;li&gt;This structure allows for flexible pricing strategies and promotions.&lt;/li&gt;
&lt;li&gt;No custom backend required: RevenueCat handles receipt validation and syncs subscription states automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Firebase&lt;/strong&gt;&lt;br&gt;
Data and authentication are primarily managed through Firebase, which integrates tightly with FlutterFlow.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Firestore: A real-time database for storing logs, messages, and other user data.&lt;/li&gt;
&lt;li&gt;Authentication: Easy setup for Google, Apple, Kakao, and other social logins.&lt;/li&gt;
&lt;li&gt;Cloud Functions: Write serverless backend logic for APIs and data processing.&lt;/li&gt;
&lt;li&gt;Hosting &amp;amp; Storage: Efficient deployment of static files and image storage.&lt;/li&gt;
&lt;li&gt;Seamless FlutterFlow integration: Firestore collections can be directly bound to UI components, speeding up development.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;br&gt;
On the first day, I successfully connected all the major services and built a working version 1.0 of the app. Below are the screenshots of this initial build. While it currently includes only the core functionality and will need many more features in the future, I’m quite satisfied with the outcome—especially considering it was created in just a single day.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Femlw36zztq2kt7vtajmt.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Femlw36zztq2kt7vtajmt.PNG" alt="Image Do0ne app’s initial launch screen" width="800" height="1739"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2lfw55nvbkk3ac61l8fm.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2lfw55nvbkk3ac61l8fm.PNG" alt="Image Do0ne screen with one goal entered" width="800" height="1739"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2trnefp68lw870yeqf3v.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2trnefp68lw870yeqf3v.PNG" alt="Image Screen for adding an immediate task and viewing completed tasks" width="800" height="1739"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>shipaton</category>
      <category>flutterflow</category>
      <category>onesignal</category>
      <category>revenuecat</category>
    </item>
    <item>
      <title>Shipaton: Do0ne Build Journal #1 - Project Setup &amp; First Build Complete</title>
      <dc:creator>friendship</dc:creator>
      <pubDate>Tue, 09 Sep 2025 06:51:29 +0000</pubDate>
      <link>https://dev.to/friendship_e3d5e249468fc3/shipaton-do0ne-journal-1-project-setup-first-build-complete-309l</link>
      <guid>https://dev.to/friendship_e3d5e249468fc3/shipaton-do0ne-journal-1-project-setup-first-build-complete-309l</guid>
      <description>&lt;p&gt;&lt;strong&gt;Project Goal&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For Shipaton 2025, the key objective is to build a fully functional app in a very short timeframe. It not only needs to work flawlessly but also look visually appealing. Do0ne is designed to run on as many platforms as possible—not limited to just iOS and Android.&lt;/p&gt;

&lt;p&gt;To achieve this, I selected the following tools and services for development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. FlutterFlow&lt;/strong&gt;&lt;br&gt;
The core development of Do0ne will be done with FlutterFlow (FF).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multi-platform support: Build once, deploy to iOS, Android, Web, and even Desktop.&lt;/li&gt;
&lt;li&gt;Automatic translation: Quickly localize Firestore data and UI text for multiple languages, enabling easy global expansion.&lt;/li&gt;
&lt;li&gt;Easy Firebase integration: Firestore, Authentication, and Storage can be connected seamlessly.&lt;/li&gt;
&lt;li&gt;Built-in support for RevenueCat &amp;amp; OneSignal: In-app purchases and push notifications can be integrated directly with prebuilt actions.&lt;/li&gt;
&lt;li&gt;Rich UI components: Pre-designed templates, widgets, and themes allow for polished designs with minimal effort.&lt;/li&gt;
&lt;li&gt;Custom Action/Widget extensibility: When built-in blocks aren’t enough, developers can extend functionality with custom code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. OneSignal&lt;/strong&gt;&lt;br&gt;
For push notifications and in-app messaging, OneSignal was chosen.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multi-channel communication: Manage push notifications, emails, and SMS all in one place.&lt;/li&gt;
&lt;li&gt;Advanced targeting: Deliver personalized notifications based on user attributes and behavior.&lt;/li&gt;
&lt;li&gt;In-app messaging: Display contextual messages inside the app triggered by events like sign-in or purchase completion.&lt;/li&gt;
&lt;li&gt;Analytics &amp;amp; optimization: Monitor delivery stats in real time and run A/B tests to improve performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. RevenueCat&lt;/strong&gt;&lt;br&gt;
In-app purchases and subscription management are handled by RevenueCat.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cross-platform purchase management: Unifies App Store, Google Play Billing, and Stripe under a single API.&lt;/li&gt;
&lt;li&gt;Product / Offering / Package model:&lt;/li&gt;
&lt;li&gt;Product: A subscription or purchase item registered in the app stores.&lt;/li&gt;
&lt;li&gt;Offering: A collection of products grouped into what users see as a package.&lt;/li&gt;
&lt;li&gt;Package: A specific price and duration combination (e.g., monthly, yearly).&lt;/li&gt;
&lt;li&gt;This structure allows for flexible pricing strategies and promotions.&lt;/li&gt;
&lt;li&gt;No custom backend required: RevenueCat handles receipt validation and syncs subscription states automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Firebase&lt;/strong&gt;&lt;br&gt;
Data and authentication are primarily managed through Firebase, which integrates tightly with FlutterFlow.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Firestore: A real-time database for storing logs, messages, and other user data.&lt;/li&gt;
&lt;li&gt;Authentication: Easy setup for Google, Apple, Kakao, and other social logins.&lt;/li&gt;
&lt;li&gt;Cloud Functions: Write serverless backend logic for APIs and data processing.&lt;/li&gt;
&lt;li&gt;Hosting &amp;amp; Storage: Efficient deployment of static files and image storage.&lt;/li&gt;
&lt;li&gt;Seamless FlutterFlow integration: Firestore collections can be directly bound to UI components, speeding up development.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;br&gt;
On the first day, I successfully connected all the major services and built a working version 1.0 of the app. Below are the screenshots of this initial build. While it currently includes only the core functionality and will need many more features in the future, I’m quite satisfied with the outcome—especially considering it was created in just a single day.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Femlw36zztq2kt7vtajmt.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Femlw36zztq2kt7vtajmt.PNG" alt="Image Do0ne app’s initial launch screen" width="800" height="1739"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2lfw55nvbkk3ac61l8fm.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2lfw55nvbkk3ac61l8fm.PNG" alt="Image Do0ne screen with one goal entered" width="800" height="1739"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2trnefp68lw870yeqf3v.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2trnefp68lw870yeqf3v.PNG" alt="Image Screen for adding an immediate task and viewing completed tasks" width="800" height="1739"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>shipaton</category>
      <category>flutterflow</category>
      <category>onesignal</category>
      <category>revenuecat</category>
    </item>
    <item>
      <title>FlutterFlow: My Experience Publishing a Package to pub.dev and Integrating It with FlutterFlow</title>
      <dc:creator>friendship</dc:creator>
      <pubDate>Wed, 03 Sep 2025 07:08:22 +0000</pubDate>
      <link>https://dev.to/friendship_e3d5e249468fc3/flutterflow-my-experience-publishing-a-package-to-pubdev-and-integrating-it-with-flutterflow-23e7</link>
      <guid>https://dev.to/friendship_e3d5e249468fc3/flutterflow-my-experience-publishing-a-package-to-pubdev-and-integrating-it-with-flutterflow-23e7</guid>
      <description>&lt;p&gt;&lt;strong&gt;Work Objectives&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It was necessary to determine whether users had enabled the custom keyboard implemented as a keyboard extension in Log0ne.&lt;/li&gt;
&lt;li&gt;I thought this feature would be repeatedly needed in similar types of apps I plan to build in the future.&lt;/li&gt;
&lt;li&gt;I decided to publish a keyboard extension checker directly on pub.dev and integrate it for use.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frbadg73gvc29ozexidb6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frbadg73gvc29ozexidb6.png" alt=" " width="800" height="526"&gt;&lt;/a&gt;&lt;a href="https://pub.dev/packages/keyboard_extension_checker" rel="noopener noreferrer"&gt;https://pub.dev/packages/keyboard_extension_checker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F43j9rp9d8xc8jko9zacn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F43j9rp9d8xc8jko9zacn.png" alt=" " width="800" height="1028"&gt;&lt;/a&gt;&lt;br&gt;
After that, I added the published package to the FlutterFlow dependencies and used it in an Action.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F23pcu9p0nzvdn3u1g6xk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F23pcu9p0nzvdn3u1g6xk.png" alt=" " width="800" height="362"&gt;&lt;/a&gt;&lt;br&gt;
I remember there used to be a menu in the Action editor where you could set package dependencies.&lt;br&gt;
After the update, this has been moved to &lt;strong&gt;App Settings&lt;/strong&gt; → &lt;strong&gt;Project Dependencies&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Through this process, I was able to confirm that creating and publishing a package on pub.dev can not only solve my immediate needs but also provide a reusable solution for future projects.&lt;/p&gt;

&lt;p&gt;Integrating the package into FlutterFlow worked smoothly, and I now feel more confident about building similar features in upcoming apps.&lt;/p&gt;

&lt;p&gt;What started as a simple requirement for Log0ne turned into a valuable experience that will save time and effort down the road.&lt;/p&gt;

</description>
      <category>flutterflow</category>
      <category>pubdev</category>
      <category>ios</category>
    </item>
    <item>
      <title>Log0ne: Dev Journal - My Daily Development Journey</title>
      <dc:creator>friendship</dc:creator>
      <pubDate>Tue, 02 Sep 2025 23:24:10 +0000</pubDate>
      <link>https://dev.to/friendship_e3d5e249468fc3/log0ne-dev-journal-my-daily-development-journey-3meo</link>
      <guid>https://dev.to/friendship_e3d5e249468fc3/log0ne-dev-journal-my-daily-development-journey-3meo</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsw42qoub2zviz3982j2t.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsw42qoub2zviz3982j2t.PNG" alt=" " width="800" height="1739"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu03ut5e7psg3qedm5qpd.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu03ut5e7psg3qedm5qpd.PNG" alt=" " width="800" height="1739"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why a Daily Dev Journal Matters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As developers, we solve countless problems and try new approaches every day. But without writing things down, it’s hard to remember exactly what we did or how we felt about it.&lt;/p&gt;

&lt;p&gt;I often struggled with this myself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I couldn’t clearly recall what I had worked on during a project.&lt;/li&gt;
&lt;li&gt;Checklists or code comments felt unpleasant to revisit, so I avoided writing them.&lt;/li&gt;
&lt;li&gt;I wanted to keep a development journal, but without the habit, it was difficult to sustain.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the end, much of my day-to-day experience was lost, leaving little to reflect on later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problems Without Logging&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When I didn’t keep a development journal, I ran into common issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lost solutions: Fixes I had already found slipped from memory, leading me to repeat the same mistakes.&lt;/li&gt;
&lt;li&gt;Unclear progress: After days or weeks, I couldn’t easily summarize what I had actually accomplished.&lt;/li&gt;
&lt;li&gt;No trace of growth: Lessons learned and insights faded, making it harder to see personal progress.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How Log0ne Changed Things&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Using Log0ne brought small but impactful changes to my workflow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I now have a clear record of what I worked on and what I tried each day.&lt;/li&gt;
&lt;li&gt;Unlike checklists, these notes became records I actually want to revisit.&lt;/li&gt;
&lt;li&gt;By writing consistently, I naturally built a habit of journaling as part of development.&lt;/li&gt;
&lt;li&gt;Over time, the logs formed a timeline of my development journey.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Different from To-Do Apps&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At first, I wondered: “Why use this if I already have Todoist or Notion?”&lt;/p&gt;

&lt;p&gt;The difference became clear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To-do apps = plan forward (what I will do).&lt;/li&gt;
&lt;li&gt;Dev Journal = reflect backward (what I actually did).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To-do apps manage the future; a Dev Journal captures the past. That difference makes a big impact on growth.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Benefits I’ve Gained&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By keeping daily logs in Log0ne, I’ve noticed several advantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clarity – At the end of the day, I know exactly what I accomplished.&lt;/li&gt;
&lt;li&gt;Fewer repeated mistakes – Past entries remind me of what I’ve already tried.&lt;/li&gt;
&lt;li&gt;Better retrospectives – Weekly and monthly reflections became more effective.&lt;/li&gt;
&lt;li&gt;Peace of mind – Offloading ideas and thoughts gave me more focus.&lt;/li&gt;
&lt;li&gt;Habit formation – Writing logs turned into a natural part of my daily routine.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Closing Thoughts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Log0ne isn’t a complex tool, but it became a simple and powerful way to keep track of my daily development journey.&lt;/p&gt;

&lt;p&gt;For me, it turned forgotten experiences into records worth revisiting. Instead of bare checklists, I now have logs that capture both the work and the lessons. Over time, these small entries became visible traces of my growth as a developer.&lt;/p&gt;

&lt;p&gt;Writing a daily development journal no longer feels like a chore—it has become a natural habit.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>FlutterFlow: Handling App Lifecycle to Run Actions on Foreground Transition</title>
      <dc:creator>friendship</dc:creator>
      <pubDate>Mon, 01 Sep 2025 06:30:52 +0000</pubDate>
      <link>https://dev.to/friendship_e3d5e249468fc3/flutterflow-handling-app-lifecycle-to-run-actions-on-foreground-transition-23e3</link>
      <guid>https://dev.to/friendship_e3d5e249468fc3/flutterflow-handling-app-lifecycle-to-run-actions-on-foreground-transition-23e3</guid>
      <description>&lt;p&gt;In FlutterFlow, pages do not provide a built-in Foreground Listener event.&lt;/p&gt;

&lt;p&gt;Problem: Logs entered through the custom Log0ne keyboard need to be saved into the app’s internal data. However, since a keyboard extension cannot directly access the app’s data, we used &lt;strong&gt;UserDefaults&lt;/strong&gt; to share the entered logs between the keyboard extension and the app. When the user launches or switches back to the Log0ne app, the logs from the keyboard extension are saved into the app’s data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a custom widget called &lt;strong&gt;ForegroundListener&lt;/strong&gt;.
The widget takes an action as a parameter, which will be executed when the app returns to the foreground.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class ForegroundListener extends StatefulWidget {
  const ForegroundListener({
    super.key,
    this.width,
    this.height,
    this.onForeground,
  });

  final double? width;
  final double? height;
  final Future Function()? onForeground;

  @override
  State&amp;lt;ForegroundListener&amp;gt; createState() =&amp;gt; _ForegroundListenerState();
}

class _ForegroundListenerState extends State&amp;lt;ForegroundListener&amp;gt;
    with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      widget.onForeground?.call();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: widget.width,
      height: widget.height,
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ztiedvxm0rbegzoo6kw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ztiedvxm0rbegzoo6kw.png" alt=" " width="678" height="1096"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Place the custom widget on any page where you want to detect foreground transitions and run an action. In the property panel, set its size to &lt;strong&gt;0&lt;/strong&gt; so it remains invisible, and pass the desired &lt;strong&gt;action&lt;/strong&gt; as a parameter to be executed when the app returns to the foreground.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fykbywgg1w2s8xbiznqbt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fykbywgg1w2s8xbiznqbt.png" alt=" " width="608" height="546"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This way, logs entered through Log0ne’s custom keyboard extension can now be properly processed within the app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvu30ckui7tw3no1giwkq.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvu30ckui7tw3no1giwkq.PNG" alt=" " width="800" height="1739"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>flutterflow</category>
      <category>ios</category>
      <category>log0ne</category>
    </item>
    <item>
      <title>FlutterFlow: My Experience Launching an iOS App with FlutterFlow</title>
      <dc:creator>friendship</dc:creator>
      <pubDate>Sat, 30 Aug 2025 10:38:30 +0000</pubDate>
      <link>https://dev.to/friendship_e3d5e249468fc3/flutterflow-my-experience-launching-an-ios-app-with-flutterflow-3e4k</link>
      <guid>https://dev.to/friendship_e3d5e249468fc3/flutterflow-my-experience-launching-an-ios-app-with-flutterflow-3e4k</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flvjbu5cks0h7bgu88vbv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flvjbu5cks0h7bgu88vbv.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;App Introduction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Log0ne&lt;/strong&gt;: Your Personal Note Assistant&lt;br&gt;
Most note apps feel too heavy, while journals are overwhelming. Log0ne fills the gap with micro-logging — fast, one-line logs that capture life as it happens.&lt;/p&gt;

&lt;p&gt;It helps you build a living timeline of fleeting thoughts and emotions, one log at a time. (Currently available on iOS)&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://apps.apple.com/us/app/log0ne-your-personal-note/id6744836057" rel="noopener noreferrer"&gt;Download on the App Store&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;App Design&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The UI was built using shadcn library integrated into FlutterFlow.&lt;br&gt;
It helped maintain consistent components and handle dark mode easily.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Issues I encountered and how I solved them&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Keyboard Extension&lt;/strong&gt;&lt;br&gt;
Implemented a custom iOS keyboard extension.&lt;br&gt;
Logs typed via the custom keyboard had to be processed once the app became active.&lt;br&gt;
To solve this, I created a custom ForegroundListener widget&lt;br&gt;
that detects when the app is active and fetches the stored data from the keyboard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Detecting Custom Keyboard Activation&lt;/strong&gt;&lt;br&gt;
I needed to detect if the custom keyboard was enabled.&lt;br&gt;
Since there wasn’t a direct solution, I built and published&lt;br&gt;
&lt;a href="https://pub.dev/packages/keyboard_extension_checker" rel="noopener noreferrer"&gt;keyboard_extension_checker&lt;/a&gt; on pub.dev,&lt;br&gt;
then integrated it with FlutterFlow. It was a fun approach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. CloudKit Realtime Sync&lt;/strong&gt;&lt;br&gt;
Implemented realtime saving and synchronization of Log data across devices using CloudKit.&lt;br&gt;
The sync logic runs as an Action Block triggered at the moment of log creation or update, ensuring instant and consistent data sync.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. RevenueCat for Subscriptions&lt;/strong&gt;&lt;br&gt;
Built a subscription-based billing system using RevenueCat.&lt;br&gt;
At first, the concept of registering items in RevenueCat was a bit confusing, but once resolved, the integration with FlutterFlow turned out to be straightforward.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. OneSignal Push Notifications&lt;/strong&gt;&lt;br&gt;
Added in-app push notification functionality using OneSignal.&lt;br&gt;
This documentation was especially helpful during setup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;FlutterFlow is a convenient and powerful tool.&lt;br&gt;
Especially from a design perspective, it allowed me to easily create beautiful screens.&lt;br&gt;
Some features couldn’t be handled solely with Action Blocks,&lt;br&gt;
but with Custom Actions and Widgets, I was able to implement everything I needed.&lt;br&gt;
In the end, I was able to build an app that I’m fully satisfied with.&lt;/p&gt;

</description>
      <category>flutterflow</category>
      <category>flutter</category>
      <category>ios</category>
    </item>
  </channel>
</rss>
