{
    "version": "https://jsonfeed.org/version/1",
    "title": "Alejandro Ulate",
    "home_page_url": "https://codingale.dev",
    "feed_url": "https://codingale.dev/rss/feed.json",
    "description": "Just a blog where I write about stuff",
    "icon": "https://codingale.dev/favicon.ico",
    "author": {
        "name": "Alejandro Ulate"
    },
    "items": [
        {
            "id": "https://codingale.dev/blog/2024-03-06-your-first-flutter-flame-game",
            "content_html": "<p>Content is propietary belonging to kodeco.com</p>",
            "url": "https://codingale.dev/blog/2024-03-06-your-first-flutter-flame-game",
            "title": "Your First Flutter Flame Game",
            "summary": "Creating a game can be a really complex endeavor, especially when you want to support multiple platforms. Luckily, using Flame & Flutter can provide support for multiple platforms and an awesome developer experience in the process.",
            "date_modified": "2024-03-06T00:00:00.000Z",
            "author": {
                "name": "Alejandro Ulate"
            }
        },
        {
            "id": "https://codingale.dev/blog/2024-02-23-flutter-apprentice-book",
            "content_html": "<p>Content is propietary belonging to kodeco.com</p>",
            "url": "https://codingale.dev/blog/2024-02-23-flutter-apprentice-book",
            "title": "Flutter Apprentice",
            "summary": "This book is for developers who are new to Flutter, and also developers that already have some experience with building apps for the iOS and Android platforms, or web apps. I was lucky enough to be a co-author to this book.",
            "date_modified": "2024-02-23T00:00:00.000Z",
            "author": {
                "name": "Alejandro Ulate"
            }
        },
        {
            "id": "https://codingale.dev/blog/2023-10-17-chatgpt-tutorial-for-flutter-getting-started",
            "content_html": "<p>Content is propietary belonging to kodeco.com</p>",
            "url": "https://codingale.dev/blog/2023-10-17-chatgpt-tutorial-for-flutter-getting-started",
            "title": "ChatGPT Tutorial for Flutter: Getting Started",
            "summary": "Learn how to incorporate ChatGPT into your Flutter apps! In this tutorial, see how to leverage machine learning and ChatGPT with a real-world trivia app.",
            "date_modified": "2023-10-17T00:00:00.000Z",
            "author": {
                "name": "Alejandro Ulate"
            }
        },
        {
            "id": "https://codingale.dev/blog/2023-02-22-flutter-accessibility-getting-started",
            "content_html": "<p>Content is propietary belonging to kodeco.com</p>",
            "url": "https://codingale.dev/blog/2023-02-22-flutter-accessibility-getting-started",
            "title": "Flutter Accessibility: Getting Started",
            "summary": "Building a high-quality app is not only about its features and looks but also about how accessible it is to users, including people with disability.",
            "date_modified": "2023-02-22T00:00:00.000Z",
            "author": {
                "name": "Alejandro Ulate"
            }
        },
        {
            "id": "https://codingale.dev/blog/2022-11-25-how-to-encourage-app-updates-flutter",
            "content_html": "<p>One big advantage when creating mobile apps is to offer new content and features to your users. This means that you will have to release new versions of your app with a higher cadence and, in turn, have many versions of your app out there, some even broken. This is a problem for app development and there&#x27;s a great Flutter plugin that helps you solve it: <code>upgrader</code>.</p>\n<p>In this tutorial you&#x27;ll learn about the following:</p>\n<ul>\n<li>Importance of keeping your users in the latest versions of your app.</li>\n<li>Display an alert if your app is not up to date.</li>\n<li>Display custom UI elements if your app is not up to date.</li>\n<li>Enforce minimum app versions.</li>\n<li>Learn the advantages of using AppCast.</li>\n</ul>\n<blockquote>\n<p><strong>Keep in mind:</strong> This tutorial assumes that you are a developer with experience publishing mobile apps to Google Play Store and Apple App Store as well as basic knowledge of Flutter, stateful widgets and package versioning.</p>\n</blockquote>\n<h2>Before you begin</h2>\n<p>You&#x27;ll work on <strong>Days Without Incidents</strong>, a simple incident counter app that supports many counters, styles, and a simple user experience. You can follow the tutorial by downloading the open source <a href=\"https://github.com/CodingAleCR/dayswithoutincidents/tree/v3.0.0%2B11\">code available via GitHub</a>. You should use Flutter, 3.0 or above to follow along.</p>\n<p>When opening the project with your preferred IDE and remember to get the dependencies with <code>flutter pub get</code>.</p>\n<p>Here’s a quick rundown of some important files you should be aware of:</p>\n<ul>\n<li><strong>lib/main.dart</strong>: Standard main file required for Flutter projects.</li>\n<li><strong>lib/core</strong>: Core widgets and utilities shared between two or more features.</li>\n<li><strong>lib/features</strong>: Uses feature grouping to abstract different parts of the UI.</li>\n<li><strong>packages</strong>: Contains the <strong>data</strong> and <strong>domain</strong> layers.</li>\n</ul>\n<p>In an effort to help you understand the essentials, you can also check <a href=\"https://github.com/CodingAleCR/dayswithoutincidents/pull/15/files\">this Pull Request</a>. It has all the changes required to handle app updates and version restrictions on your own.</p>\n<h2>Understanding how <code>upgrader</code> works</h2>\n<p>Nowadays most people use the auto-update feature of the app stores for Android and iOS, this helps to avoid having to update each app on the phone. Yet, there may be instances in which the device has not yet updated the app, or that the user is not auto-updating apps. This can turn into a big deal if you are looking to make releases with consistency (<a href=\"https://www.sealights.io/sprint-velocity/release-early-release-often-when-developers-testers-and-users-collaborate-effectively/\">Release Early, Release Often</a>) because it could cause <b>version fragmentation</b> issues.</p>\n<p>Version fragmentation will happen when there are too many versions of your app in the market. Each one could have different features, device support, screen support, and even API versions. This means that your infrastructure and services should support all these variations. This ends up making operations more expensive for the business.</p>\n<p>The solution? There are three things you can do to cut down the impact of version fragmentation:</p>\n<ol>\n<li>Have a manageable list of versions that you support.</li>\n<li>Enforce a minimum version you are supporting.</li>\n<li>Guide the user through updates if their app is not running the latest version.</li>\n</ol>\n<p>This is where <code>upgrader</code> comes in. It helps you put in place all those mechanisms in your app without too much overhead.</p>\n<p><code>upgrader</code> is a Flutter <a href=\"https://pub.dev/packages/upgrader\">plugin</a> that helps manage the user&#x27;s installed version of your app. It allows you to check if the user has the latest version installed and if not, it guides the user to install it via stores with a dialog or widget.</p>\n<p>The plugin can also enforce a minimum app version, and has built-in support RSS feeds with the AppCast standard used by Sparkle, and . Using the library helps you reduce version fragmentation and avoid potential bugs or broken app versions.</p>\n<p>Enough chit-chat, it&#x27;s time you dive into some code.</p>\n<h2>Displaying alerts if the app is outdated</h2>\n<p>One of the most common use cases for <code>upgrader</code> is to display a dialog when the current installed app is outdated compared to the store listing. Time you try it out, open <strong>lib/features/time_counter/pages/counter_page.dart</strong> and change <code>CountersPage</code>&#x27;s <code>build</code> to the following:</p>\n<pre class=\"language-dart\"><code class=\"language-dart\"><span class=\"token metadata function\">@override</span>\n<span class=\"token class-name\">Widget</span> <span class=\"token function\">build</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">BuildContext</span> context<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">return</span> <span class=\"token class-name\">Scaffold</span><span class=\"token punctuation\">(</span>\n    appBar<span class=\"token punctuation\">:</span> <span class=\"token keyword\">const</span> <span class=\"token class-name\">DWIAppBar</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    body<span class=\"token punctuation\">:</span> <span class=\"token class-name\">UpgradeAlert</span><span class=\"token punctuation\">(</span>\n      child<span class=\"token punctuation\">:</span> <span class=\"token keyword\">const</span> <span class=\"token class-name\">SafeArea</span><span class=\"token punctuation\">(</span>\n        child<span class=\"token punctuation\">:</span> <span class=\"token function\">_Body</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n      <span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n</code></pre>\n<p><code>UpgradeAlert</code> can wrap a widget, this allows you to place it as a wrapper of <code>body</code> and not having to worry about manual checks to the version.</p>\n<blockquote>\n<p><strong>Tip:</strong> Remember to add this import at the top of the file: <code>import &#x27;package:upgrader/upgrader.dart&#x27;;</code>.</p>\n</blockquote>\n<p>If you build and run the app right now you&#x27;ll see the following:</p>\n<p><img src=\"\" alt=\"Image about default dialog implementation\"/></p>\n<p>The plugin also has limited style customization for the dialog with the <code>dialogStyle</code> property in <code>Upgrader</code> which has two different options: <code>UpgradeDialogStyle.cupertino</code> and <code>UpgradeDialogStyle.material</code> (default). Change <code>build</code> again and change the style to be cupertino likeso:</p>\n<pre class=\"language-dart\"><code class=\"language-dart\"><span class=\"token metadata function\">@override</span>\n<span class=\"token class-name\">Widget</span> <span class=\"token function\">build</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">BuildContext</span> context<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">return</span> <span class=\"token class-name\">Scaffold</span><span class=\"token punctuation\">(</span>\n    appBar<span class=\"token punctuation\">:</span> <span class=\"token keyword\">const</span> <span class=\"token class-name\">DWIAppBar</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    body<span class=\"token punctuation\">:</span> <span class=\"token class-name\">UpgradeAlert</span><span class=\"token punctuation\">(</span>\n      upgrader<span class=\"token punctuation\">:</span> <span class=\"token class-name\">Upgrader</span><span class=\"token punctuation\">(</span>dialogStyle<span class=\"token punctuation\">:</span> <span class=\"token class-name\">UpgradeDialogStyle</span><span class=\"token punctuation\">.</span>cupertino<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n      child<span class=\"token punctuation\">:</span> <span class=\"token keyword\">const</span> <span class=\"token class-name\">SafeArea</span><span class=\"token punctuation\">(</span>\n        child<span class=\"token punctuation\">:</span> <span class=\"token function\">_Body</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n      <span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n</code></pre>\n<p>Build and run the app, it should look something like this:</p>\n<p><img src=\"\" alt=\"Image about default Cupertino dialog implementation\"/></p>\n<p>Now go ahead and leave <code>build</code> as it was in the beginning:</p>\n<pre class=\"language-dart\"><code class=\"language-dart\"><span class=\"token metadata function\">@override</span>\n<span class=\"token class-name\">Widget</span> <span class=\"token function\">build</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">BuildContext</span> context<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">return</span> <span class=\"token keyword\">const</span> <span class=\"token class-name\">Scaffold</span><span class=\"token punctuation\">(</span>\n    appBar<span class=\"token punctuation\">:</span> <span class=\"token class-name\">DWIAppBar</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    body<span class=\"token punctuation\">:</span> <span class=\"token class-name\">SafeArea</span><span class=\"token punctuation\">(</span>\n      child<span class=\"token punctuation\">:</span> <span class=\"token function\">_Body</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n</code></pre>\n<p>Another common scenario is having an indicator in the UI to display that the installed version of the app is not up to date. Again, the plugin has a really good implementation for this via <code>UpgradeCard</code>.</p>\n<p>Time to add <code>UpgradeCard</code> and see how it looks. Open <strong>lib/features/time_counter/widgets/counter_list.dart</strong> and change add this code after <strong>line 80</strong>:</p>\n<pre class=\"language-dart\"><code class=\"language-dart\"><span class=\"token class-name\">UpgradeCard</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n</code></pre>\n<p>Build and run the app, this is how it looks like:</p>\n<p><img src=\"\" alt=\"Image about default card implementation\"/></p>\n<p>As you can see, <code>UpgradeCard</code> displays a card styled with Material Design, it uses the same content as <code>UpgradeAlert</code> but it does it inline instead of a dialog. Since in this case the card does not look great, then go ahead and delete the code you just added by deleting <strong>line 81</strong>.</p>\n<h2>Implementing custom upgrade widgets</h2>\n<p>Now, sometimes those two built-in behaviors are not enough in terms of user experience. An example may be to show an <code>IconButton</code> when there&#x27;s an update available for the app. Let&#x27;s give this example a try.</p>\n<p>You will need to create a new widget that will work like <code>UpgradeCard</code> and <code>UpgradeAlert</code>. In fact, if you take a closer look to the library&#x27;s code, you&#x27;ll notice that both extend <code>UpgradeBase</code> which will make things a bit easier.</p>\n<p>Start by creating the file <strong>lib/core/widgets/upgrade_widget.dart</strong> and add the following code:</p>\n<pre class=\"language-dart\"><code class=\"language-dart\"><span class=\"token keyword\">import</span> <span class=\"token string-literal\"><span class=\"token string\">&#x27;dart:developer&#x27;</span></span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">import</span> <span class=\"token string-literal\"><span class=\"token string\">&#x27;package:flutter/material.dart&#x27;</span></span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string-literal\"><span class=\"token string\">&#x27;package:upgrader/upgrader.dart&#x27;</span></span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">/// Defines a builder function that allows you to create a custom widget</span>\n<span class=\"token comment\">/// that is displayed in a similar fashion as [UpgradeCard]</span>\n<span class=\"token keyword\">typedef</span> <span class=\"token class-name\">UpgradeWidgetBuilder</span> <span class=\"token operator\">=</span> <span class=\"token class-name\">Widget</span> <span class=\"token class-name\">Function</span><span class=\"token punctuation\">(</span>\n  <span class=\"token class-name\">BuildContext</span> context<span class=\"token punctuation\">,</span>\n  <span class=\"token class-name\">Upgrader</span> upgrader<span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">/// A widget to display by checking upgrader info available.</span>\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">UpgradeWidget</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">UpgradeBase</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">/// Creates a new [UpgradeWidget].</span>\n  <span class=\"token class-name\">UpgradeWidget</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    <span class=\"token class-name\">Key</span><span class=\"token operator\">?</span> key<span class=\"token punctuation\">,</span>\n    <span class=\"token class-name\">Upgrader</span><span class=\"token operator\">?</span> upgrader<span class=\"token punctuation\">,</span>\n    required <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>builder<span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">:</span> <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span>upgrader <span class=\"token operator\">?</span><span class=\"token operator\">?</span> <span class=\"token class-name\">Upgrader</span><span class=\"token punctuation\">.</span>sharedInstance <span class=\"token operator\">as</span> <span class=\"token class-name\">Upgrader</span><span class=\"token punctuation\">,</span> key<span class=\"token punctuation\">:</span> key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">/// Defines how the widget will be built. Allows the implementation of custom</span>\n  <span class=\"token comment\">/// widgets.</span>\n  <span class=\"token keyword\">final</span> <span class=\"token class-name\">UpgradeWidgetBuilder</span> builder<span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">/// Describes the part of the user interface represented by this widget.</span>\n  <span class=\"token metadata function\">@override</span>\n  <span class=\"token class-name\">Widget</span> <span class=\"token function\">build</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">BuildContext</span> context<span class=\"token punctuation\">,</span> <span class=\"token class-name\">UpgradeBaseState</span> state<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>upgrader<span class=\"token punctuation\">.</span>debugLogging<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string-literal\"><span class=\"token string\">&#x27;UpgradeWidget: build UpgradeWidget&#x27;</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">return</span> <span class=\"token class-name\">FutureBuilder</span><span class=\"token punctuation\">(</span>\n      future<span class=\"token punctuation\">:</span> state<span class=\"token punctuation\">.</span>initialized<span class=\"token punctuation\">,</span>\n      builder<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">BuildContext</span> context<span class=\"token punctuation\">,</span> <span class=\"token class-name\">AsyncSnapshot</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span>bool<span class=\"token punctuation\">&gt;</span></span> processed<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>processed<span class=\"token punctuation\">.</span>connectionState <span class=\"token operator\">==</span> <span class=\"token class-name\">ConnectionState</span><span class=\"token punctuation\">.</span>done <span class=\"token operator\">&amp;&amp;</span>\n            processed<span class=\"token punctuation\">.</span>data <span class=\"token operator\">!=</span> <span class=\"token keyword\">null</span> <span class=\"token operator\">&amp;&amp;</span>\n            processed<span class=\"token punctuation\">.</span>data<span class=\"token operator\">!</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n          <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>upgrader<span class=\"token punctuation\">.</span><span class=\"token function\">shouldDisplayUpgrade</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>upgrader<span class=\"token punctuation\">.</span>debugLogging<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n              <span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string-literal\"><span class=\"token string\">&#x27;UpgradeWidget: will call builder&#x27;</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n            <span class=\"token punctuation\">}</span>\n            <span class=\"token keyword\">return</span> builder<span class=\"token punctuation\">.</span><span class=\"token function\">call</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">,</span> upgrader<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n          <span class=\"token punctuation\">}</span>\n        <span class=\"token punctuation\">}</span>\n\n        <span class=\"token keyword\">return</span> <span class=\"token keyword\">const</span> <span class=\"token class-name\">SizedBox</span><span class=\"token punctuation\">.</span><span class=\"token function\">shrink</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n</code></pre>\n<p>Here&#x27;s a quick overview of the code you just added:</p>\n<ul>\n<li><code>UpgradeWidget</code> is a wrapper widget that implements the same basic behavior that <code>UpgradeCard</code> and <code>UpgradeAlert</code> share. It extends <code>UpgradeBase</code> and does basic checks when the customized <code>build</code> is executed. This widget will allow you to wrap any widget and display information about updating the app if needed.</li>\n<li><code>UpgradeWidget</code> receives an optional <code>Upgrader</code> implementation but also has the default one. This is the way that both <code>UpgradeCard</code> and <code>UpgradeAlert</code> work. Making the custom widget use the same principles allows you to keep interoperability between your custom widget and the library&#x27;s API.</li>\n<li><code>UpgradeWidgetBuilder</code> is an alias for the <code>builder</code> function used to render your content widget. It has <code>Upgrader</code> as a parameter because that will give you access to the information required for building your custom widget. You&#x27;ll see more about this next.</li>\n</ul>\n<p>Now that you have set up a reusable <code>UpgradeWidget</code>, open <strong>lib/core/widgets/dwi_appbar.dart</strong> and copy this code at the bottom of the file:</p>\n<pre class=\"language-dart\"><code class=\"language-dart\"><span class=\"token keyword\">class</span> _UpdateButton <span class=\"token keyword\">extends</span> <span class=\"token class-name\">StatelessWidget</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> <span class=\"token function\">_UpdateButton</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    <span class=\"token class-name\">Key</span><span class=\"token operator\">?</span> key<span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">:</span> <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span>key<span class=\"token punctuation\">:</span> key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token metadata function\">@override</span>\n  <span class=\"token class-name\">Widget</span> <span class=\"token function\">build</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">BuildContext</span> context<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token class-name\">UpgradeWidget</span><span class=\"token punctuation\">(</span>\n      upgrader<span class=\"token punctuation\">:</span> <span class=\"token class-name\">Upgrader</span><span class=\"token punctuation\">(</span>\n        <span class=\"token comment\">//! This is a bit of a hack to allow the alert dialog to be shown</span>\n        <span class=\"token comment\">//! repeatedly.</span>\n        durationUntilAlertAgain<span class=\"token punctuation\">:</span> <span class=\"token keyword\">const</span> <span class=\"token class-name\">Duration</span><span class=\"token punctuation\">(</span>milliseconds<span class=\"token punctuation\">:</span> <span class=\"token number\">500</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        showReleaseNotes<span class=\"token punctuation\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span>\n        showIgnore<span class=\"token punctuation\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span>\n      <span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n      builder<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">,</span> upgrader<span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span><span class=\"token operator\">&gt;</span> <span class=\"token class-name\">CircleAvatar</span><span class=\"token punctuation\">(</span>\n        child<span class=\"token punctuation\">:</span> <span class=\"token class-name\">IconButton</span><span class=\"token punctuation\">(</span>\n          onPressed<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n            upgrader<span class=\"token punctuation\">.</span><span class=\"token function\">checkVersion</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">:</span> context<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n          <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n          icon<span class=\"token punctuation\">:</span> <span class=\"token keyword\">const</span> <span class=\"token class-name\">Icon</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Icons</span><span class=\"token punctuation\">.</span>upload<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n      <span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n</code></pre>\n<p><code>_UpdateButton</code> is a convenience private widget that will allow you to set the behavior for your custom <code>UpgradeWidget</code>. In this case, the idea is to showcase <code>upgrader</code>&#x27;s alert dialog when the <code>IconButton</code> is tapped. This can be accomplished by calling <code>checkVersion</code> and passing the context as a parameter; the plugin will take over when the function is called and a new <code>UpgradeAlert</code> should be displayed.</p>\n<p>For better readability the flags <code>showReleaseNotes</code> and <code>showIgnore</code> are set to <code>false</code> since both elements take too much space in the UI, and since the DWI users are familiar with simple user experience, then you can skip showing them for now.</p>\n<p>One last caveat is that whenever the user taps <strong>Later</strong> in <code>UpgradeAlert</code>, the library stores a timestamp to avoid showing the dialog too often or at undesired times. It will only reshow the dialog once some time has passed (the default is 3 days).</p>\n<p>For DWI you&#x27;ll need to bypass this feature and show the dialog everytime the user taps on the update <code>IconButton</code>. To accommplish this you are overriding the default <code>durationUntilAlertAgain</code> with a <code>Duration</code> of 500 milliseconds. This way, the library will mark the dialog as ready as soon the user closes the dialog.</p>\n<blockquote>\n<p>This is a hacky solution because it wouldn&#x27;t be needed if the library trusted you to display the alert dialog at any point you wanted. Unfortunately, at the time of writing this tutorial, <code>upgrader</code> does not support this kind of behavior out of the box.</p>\n</blockquote>\n<p>Now add <code>_UpdateButton(),</code> to <code>actions</code> in <strong>line 21</strong>. Also make sure you add the corresponding imports for the library at the top of the file:</p>\n<pre class=\"language-dart\"><code class=\"language-dart\"><span class=\"token keyword\">import</span> <span class=\"token string-literal\"><span class=\"token string\">&#x27;package:dwi/core/widgets/widgets.dart&#x27;</span></span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string-literal\"><span class=\"token string\">&#x27;package:upgrader/upgrader.dart&#x27;</span></span><span class=\"token punctuation\">;</span>\n</code></pre>\n<p>Build and run, you should see the following:</p>\n<p><img src=\"\" alt=\"Image about custom widget implementation\"/></p>\n<h2>Enforcing a minimum version in your app</h2>\n<p>Another great feature of <code>upgrader</code> is to enforce a minimum app version simply by adding predefined text to the description in the app stores or by defining the minimum app version inside your <code>Upgrader</code> configuration like so:</p>\n<pre class=\"language-dart\"><code class=\"language-dart\"><span class=\"token class-name\">Upgrader</span><span class=\"token punctuation\">(</span>\n  minAppVersion<span class=\"token punctuation\">:</span> <span class=\"token string-literal\"><span class=\"token string\">&#x27;3.0.0&#x27;</span></span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n</code></pre>\n<p>If you are looking to use app store descriptions then keep in mind the following formats:</p>\n<ul>\n<li>For the Android Play Store, use this format: <code>[Minimum supported app version: 1.2.3]</code></li>\n<li>For the iOS App Store, use this format: <code>[:mav: 1.2.3]</code></li>\n</ul>\n<p>Using that text will define the minimum app version as <em>1.2.3</em>; which means that earlier versions of this app will be forced to update to the latest version available.</p>\n<h2>Controlling your own version listings</h2>\n<p>An important limit of <code>upgrader</code> is that the default behavior of <code>upgrader</code> leverages the current App Store and Play Store listings of your app, this means that:</p>\n<ol>\n<li>If Google or Apple decide to stop displaying the app version or only allowed certain description formats then this would stop working.</li>\n<li>If your app is not distributed via public stores then it will not work as intended out of the box.</li>\n<li>You are not in control of the list of versions that you support and there&#x27;s no history about them.</li>\n</ol>\n<p>To solve this, <code>upgrader</code> has support for working with AppCast which is:</p>\n<blockquote>\n<p>an RSS feed with one channel that has a collection of items that each describe one app version. The appcast will describe each app version and will provide the latest app version to upgrader that indicates when an upgrade should be recommended.</p>\n</blockquote>\n<p>It is based on the <a href=\"https://sparkle-project.org/\">Sparkle framework by Andy Matuschak</a>. You can read the <a href=\"https://sparkle-project.org/documentation/publishing/\">Sparkle documentation here</a>. It is a widely used standard that lists all the versions of your app with an XML format. Here&#x27;s an example of how an appcast file could look like taken from Sparkle&#x27;s documentation:</p>\n<pre class=\"language-xml\"><code class=\"language-xml\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>rss</span> <span class=\"token attr-name\"><span class=\"token namespace\">xmlns:</span>sparkle</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">&quot;</span>http://www.andymatuschak.org/xml-namespaces/sparkle<span class=\"token punctuation\">&quot;</span></span> <span class=\"token attr-name\"><span class=\"token namespace\">xmlns:</span>dc</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">&quot;</span>http://purl.org/dc/elements/1.1/<span class=\"token punctuation\">&quot;</span></span> <span class=\"token attr-name\">version</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">&quot;</span>2.0<span class=\"token punctuation\">&quot;</span></span><span class=\"token punctuation\">&gt;</span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>channel</span><span class=\"token punctuation\">&gt;</span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>title</span><span class=\"token punctuation\">&gt;</span></span>Sparkle Test App Changelog<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>title</span><span class=\"token punctuation\">&gt;</span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span><span class=\"token punctuation\">&gt;</span></span>http://sparkle-project.org/files/sparkletestcast.xml<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>link</span><span class=\"token punctuation\">&gt;</span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>description</span><span class=\"token punctuation\">&gt;</span></span>Most recent changes with links to updates.<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>description</span><span class=\"token punctuation\">&gt;</span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>language</span><span class=\"token punctuation\">&gt;</span></span>en<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>language</span><span class=\"token punctuation\">&gt;</span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>item</span><span class=\"token punctuation\">&gt;</span></span>\n      <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>title</span><span class=\"token punctuation\">&gt;</span></span>Version 2.0<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>title</span><span class=\"token punctuation\">&gt;</span></span>\n      <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span><span class=\"token punctuation\">&gt;</span></span>https://sparkle-project.org<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>link</span><span class=\"token punctuation\">&gt;</span></span>\n      <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token namespace\">sparkle:</span>version</span><span class=\"token punctuation\">&gt;</span></span>2.0<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span><span class=\"token namespace\">sparkle:</span>version</span><span class=\"token punctuation\">&gt;</span></span>\n      <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>description</span><span class=\"token punctuation\">&gt;</span></span>\n      <span class=\"token cdata\">&lt;![CDATA[ &lt;ul&gt; &lt;li&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit.&lt;/li&gt; &lt;li&gt;Suspendisse sed felis ac ante ultrices rhoncus. Etiam quis elit vel nibh placerat facilisis in id leo.&lt;/li&gt; &lt;li&gt;Vestibulum nec tortor odio, nec malesuada libero. Cras vel convallis nunc.&lt;/li&gt; &lt;li&gt;Suspendisse tristique massa eget velit consequat tincidunt. Praesent sodales hendrerit pretium.&lt;/li&gt; &lt;/ul&gt; ]]&gt;</span>\n      <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>description</span><span class=\"token punctuation\">&gt;</span></span>\n      <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>pubDate</span><span class=\"token punctuation\">&gt;</span></span>Sat, 26 Jul 2014 15:20:11 +0000<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>pubDate</span><span class=\"token punctuation\">&gt;</span></span>\n      <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>enclosure</span> <span class=\"token attr-name\">url</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">&quot;</span>https://sparkle-project.org/files/Sparkle%20Test%20App.zip<span class=\"token punctuation\">&quot;</span></span> <span class=\"token attr-name\">length</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">&quot;</span>107758<span class=\"token punctuation\">&quot;</span></span> <span class=\"token attr-name\">type</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">&quot;</span>application/octet-stream<span class=\"token punctuation\">&quot;</span></span> <span class=\"token attr-name\"><span class=\"token namespace\">sparkle:</span>edSignature</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">&quot;</span>7cLALFUHSwvEJWSkV8aMreoBe4fhRa4FncC5NoThKxwThL6FDR7hTiPJh1fo2uagnPogisnQsgFgq6mGkt2RBw==<span class=\"token punctuation\">&quot;</span></span><span class=\"token punctuation\">/&gt;</span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>item</span><span class=\"token punctuation\">&gt;</span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>channel</span><span class=\"token punctuation\">&gt;</span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>rss</span><span class=\"token punctuation\">&gt;</span></span>\n</code></pre>\n<p>This file should be hosted in a server accessible to anyone that uses the app. It also can be autogenerated during the release process, or you can also manually update it after a release is available on the stores.</p>\n<p>Using <code>upgrader</code> with an AppCast is relatively simple as well. Here&#x27;s an example taken from the library&#x27;s documentation:</p>\n<pre class=\"language-dart\"><code class=\"language-dart\"><span class=\"token keyword\">import</span> <span class=\"token string-literal\"><span class=\"token string\">&#x27;package:flutter/material.dart&#x27;</span></span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string-literal\"><span class=\"token string\">&#x27;package:upgrader/upgrader.dart&#x27;</span></span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span><span class=\"token operator\">&gt;</span> <span class=\"token function\">runApp</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token class-name\">MyApp</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">MyApp</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">StatelessWidget</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> <span class=\"token class-name\">MyApp</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    <span class=\"token class-name\">Key</span> key<span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">:</span> <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span>key<span class=\"token punctuation\">:</span> key<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token metadata function\">@override</span>\n  <span class=\"token class-name\">Widget</span> <span class=\"token function\">build</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">BuildContext</span> context<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">final</span> appcastURL <span class=\"token operator\">=</span>\n        <span class=\"token string-literal\"><span class=\"token string\">&#x27;https://raw.githubusercontent.com/larryaasen/upgrader/master/test/testappcast.xml&#x27;</span></span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">final</span> appcastConfig <span class=\"token operator\">=</span> <span class=\"token class-name\">AppcastConfiguration</span><span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">:</span> appcastURL<span class=\"token punctuation\">,</span> supportedOS<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">&#x27;android&#x27;</span></span><span class=\"token punctuation\">,</span> <span class=\"token string-literal\"><span class=\"token string\">&#x27;ios&#x27;</span></span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">return</span> <span class=\"token class-name\">MaterialApp</span><span class=\"token punctuation\">(</span>\n      title<span class=\"token punctuation\">:</span> <span class=\"token string-literal\"><span class=\"token string\">&#x27;Upgrader Example&#x27;</span></span><span class=\"token punctuation\">,</span>\n      home<span class=\"token punctuation\">:</span> <span class=\"token class-name\">Scaffold</span><span class=\"token punctuation\">(</span>\n          appBar<span class=\"token punctuation\">:</span> <span class=\"token class-name\">AppBar</span><span class=\"token punctuation\">(</span>\n            title<span class=\"token punctuation\">:</span> <span class=\"token class-name\">Text</span><span class=\"token punctuation\">(</span><span class=\"token string-literal\"><span class=\"token string\">&#x27;Upgrader Example&#x27;</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n          <span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n          body<span class=\"token punctuation\">:</span> <span class=\"token class-name\">UpgradeAlert</span><span class=\"token punctuation\">(</span>\n            <span class=\"token class-name\">Upgrader</span><span class=\"token punctuation\">(</span>appcastConfig<span class=\"token punctuation\">:</span> appcastConfig<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n            child<span class=\"token punctuation\">:</span> <span class=\"token class-name\">Center</span><span class=\"token punctuation\">(</span>child<span class=\"token punctuation\">:</span> <span class=\"token class-name\">Text</span><span class=\"token punctuation\">(</span><span class=\"token string-literal\"><span class=\"token string\">&#x27;Checking...&#x27;</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n          <span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n</code></pre>\n<p>Great work, now you know exactly how to keep your user&#x27;s running the latest version of your app and also the main gotchas that you might find along the way.</p>\n<h2>What&#x27;s next?</h2>\n<p>Remember that you can view a complete list of all the changes needed in this PR of Days Without Incidents.</p>\n<p>If you are wondering what&#x27;s the best data storage solution for your Flutter app, check out <a href=\"https://blog.logrocket.com/comparing-hive-other-flutter-app-database-options/\">this tutorial by Onuoha Ifeanyi</a> in which a comparison is made between different databases.</p>\n<p>Looking for adaptive app guidance? Damilare Jolayemi has great insights in <a href=\"https://blog.logrocket.com/creating-adaptive-app-flutter/\">this tutorial</a></p>\n<p>I hope you enjoyed this tutorial, if you did, sharing it with others is much appreciated. And if you have any questions or comments, leave them down below and I&#x27;ll be happy to chat.</p>",
            "url": "https://codingale.dev/blog/2022-11-25-how-to-encourage-app-updates-flutter",
            "title": "How to encourage app updates with Flutter",
            "summary": "One big advantage when creating mobile apps is to offer new content and features to your users. This means that you will have to release new versions of your app with a higher cadence and, in turn, have many versions of your app out there, some even broken. This is a problem for app development and there's a great Flutter plugin that helps you solve it: `upgrader`.",
            "date_modified": "2022-11-25T00:00:00.000Z",
            "author": {
                "name": "Alejandro Ulate"
            }
        },
        {
            "id": "https://codingale.dev/blog/2022-06-01-bloc-update-getting-started",
            "content_html": "<p>Content is propietary belonging to kodeco.com</p>",
            "url": "https://codingale.dev/blog/2022-06-01-bloc-update-getting-started",
            "title": "Bloc 8.0 Tutorial for Flutter: Getting Started",
            "summary": "Learn how to build a Wordle clone app in Flutter using one of the most robust state management libraries: Bloc 8.0.",
            "date_modified": "2022-06-01T00:00:00.000Z",
            "author": {
                "name": "Alejandro Ulate"
            }
        },
        {
            "id": "https://codingale.dev/blog/2022-01-26-creating-custom-gestures-in-flutter",
            "content_html": "<p>Content is propietary belonging to kodeco.com</p>",
            "url": "https://codingale.dev/blog/2022-01-26-creating-custom-gestures-in-flutter",
            "title": "Creating Custom Gestures in Flutter",
            "summary": "Learn how to add custom gestures in your Flutter app by working on a fun lock-picking app.",
            "date_modified": "2022-01-26T00:00:00.000Z",
            "author": {
                "name": "Alejandro Ulate"
            }
        },
        {
            "id": "https://codingale.dev/blog/2021-08-04-microinteractions-with-animatedswitcher",
            "content_html": "<p>Content is propietary belonging to kodeco.com</p>",
            "url": "https://codingale.dev/blog/2021-08-04-microinteractions-with-animatedswitcher",
            "title": "Adding Microinteractions With AnimatedSwitcher",
            "summary": "Micro-interactions and animations are key factors in people choosing and continuing to use apps. Thus, adding micro-interactions is important for the success of your app. It hasn't always been easy, but now with AnimatedSwitcher, you can add a lot of interactivity to your app without investing too much effort.",
            "date_modified": "2021-08-04T00:00:00.000Z",
            "author": {
                "name": "Alejandro Ulate"
            }
        },
        {
            "id": "https://codingale.dev/blog/2021-08-03-hola-mundo",
            "content_html": "<p>¡Hola! Desde siempre me ha gustado la escritura, recuerdo que el mundo de las palabras siempre me ha llamado la atención, me ha enamorado y ahora llegó el tiempo de dejarme llevar por las letras y compartir mi conocimiento (y también mi ignorancia) con el mundo entero a través de internet. Éste blog estará lleno de opiniones personales, experiencias vividas y recomendaciones desde mi perspectiva, así que ya sabes, es <strong>completamente subjetivo</strong>.</p>\n<h2>¿De qué se trata el blog?</h2>\n<p>Se trata de un blog multitemático, que aborda temas como tecnología, opinión, programación, entre otros. Mi única intención con este blog es compartir conocimiento, experiencias, puntos de vista y recomendaciones desde mi perspectiva con toda persona interesada en conocerlos.</p>\n<h2>¿Cada cuánto realizaré publicaciones?</h2>\n<p><strong>No tengo planeado una periodicidad</strong> para las publicaciones, pero tengo la intención de publicar al menos un post por mes.</p>\n<h2>¿Inglés o Español?</h2>\n<p>Un poco de <strong>ambos</strong>. Actualmente realizo artículos de aprendizaje para <a href=\"https://www.kodeco.com/u/codingalecr\">kodeco.com</a> y otros foros de contenido los cuáles son siempre en inglés; sin embargo, publicaré posts en español o inglés en mi blog personal (el que lees ahora) simplemente porque me gusta escribir.</p>",
            "url": "https://codingale.dev/blog/2021-08-03-hola-mundo",
            "title": "¡Hola Mundo!",
            "summary": "¡Hola! Desde siempre me ha gustado la escritura, recuerdo que el mundo de las palabras siempre me ha llamado la atención, me ha enamorado y ahora llegó el tiempo de dejarme llevar por las letras.",
            "date_modified": "2021-08-03T00:00:00.000Z",
            "author": {
                "name": "Alejandro Ulate"
            }
        }
    ]
}