<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Zero One Group on Medium]]></title>
        <description><![CDATA[Stories by Zero One Group on Medium]]></description>
        <link>https://medium.com/@zeroonegroup?source=rss-bd9b245f3b89------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*YM10daB0imtUN--yGeDxrQ.png</url>
            <title>Stories by Zero One Group on Medium</title>
            <link>https://medium.com/@zeroonegroup?source=rss-bd9b245f3b89------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 22:17:37 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@zeroonegroup/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[How to Architect Your App with BLoC and GoRouter]]></title>
            <link>https://medium.com/@zeroonegroup/how-to-architect-your-app-with-bloc-and-gorouter-f7005007f1fd?source=rss-bd9b245f3b89------2</link>
            <guid isPermaLink="false">https://medium.com/p/f7005007f1fd</guid>
            <dc:creator><![CDATA[Zero One Group]]></dc:creator>
            <pubDate>Mon, 03 Mar 2025 04:52:02 GMT</pubDate>
            <atom:updated>2025-03-03T04:52:02.210Z</atom:updated>
            <content:encoded><![CDATA[<p><em>By </em><a href="https://www.linkedin.com/in/mrkahvi/"><em>Muhammad Rijalul Kahfi</em></a><em>, Senior Product Engineer at Zero One Group</em></p><h3>Background</h3><p>There have been plenty of examples of how to architect your Flutter app using BLoC combined Flutter built-in Navigator package. The implementation is pretty straightforward.</p><p>However, when it comes to using GoRouter along with BLoC, it is becoming a bit less intuitive. The problem is not the packages themselves. It is the fact that the nature of GoRouter is that it is supposed to return a screen widget inside every declaration of a route. While the use of BLoC often supposes the developers to wrap the root widget of the screen with a BlocProvider. Plus you often need to invoke an initial event right after you enter the screen.</p><h3><strong>StatelessWidget as a default Choice</strong></h3><p>Implementing BLoC has nothing to do with whether you use StatefulWidget or StatelessWidget for your screen widget. You can choose what works best for you.</p><p>However, if we look at the examples provided by the official documentation of BLoC, it is a good idea to go with StatelessWidget.</p><p>The idea behind the choice of using a state management package such as BLoC over traditional `setState` is that you will no longer rely on `setState` which is what StatefulWidget has to offer. In this case, states of the UI are fully managed by BLoC. Therefore, in this case, StatelessWidget is the way to go.</p><p>Invoking the `setState` method is expensive and has a huge consequence on the performance of UI as it will rebuild the whole widget tree under the `build` method.</p><h3><strong>When to choose StatefulWidget?</strong></h3><p>There are still many cases where you should choose StatefulWidget over StatelessWidget. This is because there is no clean way to do some sort of jobs using StatelessWidget like these ones:</p><ol><li>You need to work with some kind of widget controller such as scroll controllers, add a listener to it, and so on</li><li>You need to deal with animations.</li><li>You’d like to invoke multiple events at once at the beginning of the widget lifecycle by calling them inside the `initState` method.</li></ol><p>So you can do something like this:</p><pre> @override<br> void initState() {<br>   context.read&lt;UserProfileBloc&gt;().add(FetchUserProfile());<br>   context.read&lt;UserTransactionBloc&gt;().add(FetchUserLastTransactions());<br>   context.read&lt;UserWithdrawBloc&gt;().add(FetchUserLastWithdraws());<br>   super.initState();<br> }</pre><p>This doesn’t mean you cannot do the same in StatelessWidget, but doing such things inside StatefulWidget’s initState gives you the flexibility to fire multiple initial events from different BLoC in a much more readable form, doesn’t it?</p><p>Be careful: Invoking events inside the build method should be avoided as this method can be called multiple times as the state of the parent widget changes.</p><h3><strong>Global Provider vs Scoped Provide</strong></h3><p>There are two ways of declaring BLoC providers for your BLoCs.</p><ol><li>Global Provider</li><li>Scoped Provider</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*4T8XtOE6JeHiiblQ" /><figcaption>Picture 1. Global Provider</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*rSoSEr9uDwckAVbK" /><figcaption>Picture 2. Scoped Provider</figcaption></figure><p>Scoped Provider is when BlocProviders wraps only the root widget of a specific feature requiring access to it. While Global Provider is when a BlocProvider wraps the root widget of your app. Typically this is done by wrapping the BlocProvider onto your Material Widget.</p><p>If you feel like you need the BLoC state to be global, then you need to provide it globally, such as BLoC for authentication, BLoC for in-app notifications, and BLoC that deals with some data that is likely to be accessed globally within your app. Otherwise, it’s better to scope it only to specific features needing access to its state.</p><p>The main difference between these two is memory allocation. that BLocProvider would handle the lifecycle of your BLoC instance. So let’s say you have a ProductDetailBLoC instance for your product detail screen like this.</p><pre>BlocProvider&lt;ProductDetailBloc, ProductDetail&gt;(<br>             create: (context) =&gt; ProductDetailBloc(),<br>             child: YourProductScreen()),</pre><p>In this case, the instance of ProductDetailBloc only lives within YourProductScreen and its subtree. Every time users go back from the product detail screen, the BlocProvider would automatically dispose of the ProductDetailBloC as it’s no longer needed.</p><h3><strong>Memory Allocation Considerations</strong></h3><p>It’s perfectly fine to have your BLoC provided globally, especially if you are not sure where to access it in your app in order to get rid of the ProviderNotFound exception. Not to mention BLoC is lazy by default, meaning that your BLoC will only be instantiated when there is an invocation of its instance using context.read&lt;YourBloc&gt;() or BlocProvider.of&lt;YourBloc&gt;(context).</p><p>However, once instantiated, it will remain live in your app and will not get disposed of until you go out of its scope or you dispose of it by hand using yourBloc.dispose() method. This is the case where going with a scoped provider becomes advantageous. Of course, the impact wouldn’t be that significant until you have dozens or even hundreds of BLoCs in your app being all provided globally.</p><h3><strong>Resource Leak Prevention</strong></h3><p>A Global BlocProvider should become more strongly avoided when you are working with streams. This is no surprise because having it app-wide would lead to resource leaks. Things would get even worse if you are incorporating some real-time resources that charge you as your app goes, such as Firestore DB or AWS Amplify.</p><p>Here is my take on why the use of global BlocProviders is discouraged. Let’s think of this scenario!</p><p>Your app shows a real-time map that always listens to a delivery guy’s location. The UI must change every time a new stream is received from Firestore as soon as the location of the guy is updated.</p><p>Now, here you have your BlocProvider map set globally. Once the user gets on the map, the event to listen to the stream is then initiated and hence, the BLoC is instantiated.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/425/0*H92Xeb7opJnBFqVZ" /><figcaption>Image source: <a href="https://gojek.io/">https://gojek.io</a></figcaption></figure><p>What happens if the user goes out of the map screen? The user might not see anything strange, and the app might keep behaving normally. But what is actually going on is that the app keeps listening to the stream! This will end up draining the phone’s battery, as well as draining the memory. One more important thing, your Firebase cost will increase drastically. This is a really big problem.</p><p>You don’t wanna have this occur in your app. So all you have to do is to dispose of the BLoC as soon as it is no longer needed. This is where BlocProvider handles it for you. Every time users go out of the provider scope, the BLoC and all of its related resources will be disposed of automatically.</p><h3><strong>Putting GoRouter and BLoC all together</strong></h3><p>Basically, implementing Go Router along with BLoC has no difference from the other. Suppose you have three 4 screens: register, login, products list, and product detail. Once logged in, users can see the products list screen and then navigate to the product detail screen.</p><p>You define all the routes in a file, say routes.dart.</p><pre>GoRouter routes() {<br> final GoRouter router = GoRouter(<br>   initialLocation:  &#39;/&#39;,<br>   debugLogDiagnostics: true,<br>   routes: &lt;GoRoute&gt;[<br>     GoRoute(<br>         path: &#39;/&#39;,<br>         name: Routes.main.name,<br>         builder: (BuildContext context, GoRouterState state) =&gt;<br>             const TripsListScreen(),<br>         routes: [<br>           GoRoute(<br>               path: &#39;products&#39;,<br>               name: Routes.products.name,<br>               builder: (BuildContext context, GoRouterState state) =&gt;<br>                   const ProductsListScreen(),<br>               routes: [<br>                 GoRoute(<br>                     path: &#39;detail&#39;,<br>                     name: Routes.productDetail.name,<br>                     builder: (BuildContext context, GoRouterState state) {<br>                       final extras = (state.extra as Extras).extras;<br>                       final Product product = extras[Keys.product] as Product;<br>                       return ProductDetailScreen(<br>                         product: product,<br>                       );<br>                     },),<br>               ]),<br>         ]),<br>     GoRoute(<br>       path: &#39;/login&#39;,<br>       name: Routes.login.name,<br>       builder: (BuildContext context, GoRouterState state) =&gt; LoginScreen(),<br>     ),<br>     GoRoute(<br>       path: &#39;/register&#39;,<br>       name: Routes.register.name,<br>       builder: (BuildContext context, GoRouterState state) =&gt;<br>           RegisterScreen(),<br>     ),<br>   ],<br> );<br><br> return router;<br>}</pre><p>But then, on the products list screen, the app needs to fetch the products right after the users get into the screen. And then, when users navigate to the product detail screen, the app needs to fetch the product detail right after they get into it.</p><p>How do you fire those initial events inside your StatelessWidget?</p><p>The most common practice is to wrap the screen root widget with BlocProvider and create the corresponding BLoC within it.</p><p>However, it would be a better practice to separate the BlocProvider builder from your screen Widget builder. So in this case, you do something like this.</p><pre>class ProductsListProvider extends StatelessWidget {<br> const ProductsListProvider({Key? key}) : super(key: key);<br><br><br> @override<br> Widget build(BuildContext context) =&gt; BlocProvider(<br>       create: (context) =&gt; ProductsListBloc(<br>           productRepository: context.read&lt;ProductRepository&gt;())<br>         ..add(FetchProducts()),<br>       child: ProductsListScreen(),<br>     );<br>}<br><br><br>class ProductsListScreen extends StatelessWidget {<br> const ProductsListScreen({Key? key}) : super(key: key);<br><br><br> @override<br> Widget build(BuildContext context) {<br>   return BlocConsumer&lt;ProductsListBloc, ProductsListState&gt;(<br>     builder: (context, state) {<br>       return ProductsListView();<br>     },<br>   );<br> }<br>}</pre><p>Another way is to totally separate the widget into two separate files grouped in one folder. This way, every time you add a new screen, you create a new folder, say “product_detail” and then create three dart files, like this</p><p>| — product_detail</p><p>Product_detail_provider.dart</p><ul><li>product_detail_screen .dart</li><li>screen.dart</li></ul><p>Description:</p><ol><li>Product_detail_provider.dart which is built from BlocProvider.</li><li>product_detail_screen.dart which consists of your product detail widgets.</li><li>Screen.dart which exports those 2 files.</li></ol><p>Here is how your dart files are going to be.</p><p>File: product_detail_provider.dart</p><pre><br>class ProductsListProvider extends StatelessWidget {<br> const ProductsListProvider({Key? key}) : super(key: key);<br><br><br> @override<br> Widget build(BuildContext context) =&gt; BlocProvider(<br>       create: (context) =&gt; ProductsListBloc(<br>           productRepository: context.read&lt;ProductRepository&gt;())<br>         ..add(FetchProducts()),<br>       child: ProductsListScreen(),<br>     );<br>}</pre><p>File: product_detail_screen.dart</p><pre>class ProductsListScreen extends StatelessWidget {<br> const ProductsListScreen({Key? key}) : super(key: key);<br><br><br> @override<br> Widget build(BuildContext context) {<br>   return BlocConsumer&lt;ProductsListBloc, ProductsListState&gt;(<br>     builder: (context, state) {<br>       return ProductsListView();<br>     },<br>   );<br> }<br>}</pre><p>File: screen.dart</p><pre>export &#39;products_list_provider.dart&#39;;<br>export &#39;products_list_screen.dart&#39;;</pre><p>As you can see in the example above in product_detail_provider.dart, this way allows you to fire multiple initial events of multiple BLoC. Just use MultiBlocProvider instead and call ..add(Event1())..add(Event2()) and so on respectively.</p><h3><strong>BLoC and GoRouter Authentication Flow</strong></h3><p>One of the easiest ways to implement authorization is to put BlocBuilder of AuthenticationBloc at the very top of the widget tree, wrapping the `MaterialApp` widget, as this BloC would be the first state to check.</p><p>The main goal here is to let the app know where to redirect the user based on his/her current authentication state. It can be “unauthenticated”, “authenticated”, “profileNotComplete”, or any other authentication states of your definitions.</p><p>To make it simple, we just define only 2 authentication states:</p><ol><li>Authenticated whereby the initial route would be the home screen.</li><li>Unauthenticated whereby the initial route would be the login screen.</li></ol><p>Here is what we can do for short.</p><pre><br> MultiRepositoryProvider(<br>   providers: [<br>     RepositoryProvider&lt;AuthRepository&gt;(<br>       create: (context) =&gt; AuthRepository(),<br>     ),<br>     // Other BlocProviders here<br>   ],<br>   child: MultiBlocProvider(<br>     providers: [<br>       BlocProvider&lt;AuthenticationBloc&gt;(<br>           create: (context) =&gt;<br>               AuthBloc(authenticationRepository: authRepository)<br>                 ..add(AppStarted())),<br>       // Other BlocProviders here<br>     ],<br>     child: BlocBuilder&lt;AuthenticationBloc, AuthenticationState&gt;(<br>       builder: (context, state) {<br><br><br>         GoRouter routers = routes(state);<br><br><br>         return MaterialApp.router(<br>           routerDelegate: routers.routerDelegate,<br>           routeInformationProvider: routers.routeInformationProvider,<br>           routeInformationParser: routers.routeInformationParser,<br>        // …<br>         );<br>       },<br>     ),<br>   ),<br> );</pre><p>This way, you pass the `AuthenticationState` to the `router()` function so that it can know what the initial route is going to be, whether ‘/’ which is the route for the home screen, or ‘/login’ which is the route for the login screen.</p><p>And then in the `route()` function, we define the initial route based on that `AuthenticationState`.</p><pre>String initialRoute(AuthenticationState state) {<br> if (state is Unauthenticated) {<br>   return &#39;/login&#39;;<br> } else if (state is Authenticated) {<br>   return &#39;/&#39;;<br> }<br><br><br> return &#39;/&#39;;<br>}<br><br><br>GoRouter routes(AuthenticationState state) {<br> final GoRouter router = GoRouter(<br>   initialLocation: initialRoute(state),<br>   debugLogDiagnostics: true,<br>   routes: &lt;GoRoute&gt;[<br>     // ...<br>   ]<br> );<br>}</pre><p>That’s pretty much it!</p><h3>Conclusion</h3><p>There are some key points from what we just talked about when it comes to using BLoC in your app. Firstly, going with StatelessWidget should be a default choice unless you have to deal with some extra states such as adding listeners, playing with animations, mixins, etc. Second, if you are working on a quite large app, it would be better to scope your BLoC Provider unless some BLoCs are supposed to be applications wide such as BLoC authentication, notifications, etc. Global BlocProviders in your app must be taken carefully and it would be strongly discouraged for the BLoC that deals with some real-time resources that charge you as the app goes.</p><p>Third, you can return BlocProvider as a widget that is defined on your GoRouter’s routes. Then you can separate the BlocProvider builder from your screen Widget builder. You can achieve this by either locating those two widgets inside the same dart file or making them separated into two files.</p><p>Of course, these points are subject to discussion. There should be a couple of other approaches on how to architect your Flutter projects with BLoC and Go Router.</p><h3>References</h3><ul><li><a href="https://pub.dev/packages/flutter_bloc">https://pub.dev/packages/flutter_bloc</a></li><li><a href="https://pub.dev/packages/go_router">https://pub.dev/packages/go_router</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f7005007f1fd" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Membandingkan Form yang Kompleks menggunakan Formik dan React Hook Form dengan Chakra UI]]></title>
            <link>https://medium.com/@zeroonegroup/membandingkan-form-yang-kompleks-menggunakan-formik-dan-react-hook-form-dengan-chakra-ui-9885861da6c6?source=rss-bd9b245f3b89------2</link>
            <guid isPermaLink="false">https://medium.com/p/9885861da6c6</guid>
            <dc:creator><![CDATA[Zero One Group]]></dc:creator>
            <pubDate>Mon, 03 Mar 2025 04:51:20 GMT</pubDate>
            <atom:updated>2025-03-03T04:51:20.168Z</atom:updated>
            <content:encoded><![CDATA[<p><em>By Rivaldi Putra, Product Engineer at Zero One Group</em></p><h3>Mengapa kita melakukan riset?</h3><p>Zero One Group (ZOG) adalah sebuah perusahaan di bidang teknologi yang fokus dalam transformasi teknologi. Sebagai Perusahaan yang dipercaya dalam transformasi teknologi, Kami memiliki beragam Klien, dari startup hingga perusahaan manufaktur. Dalam proses pembuatan aplikasi di level enterprise, ada suatu kondisi dimana kami harus membuat form yang sangat kompleks sebagaimana kebutuhan enterprise.</p><p>Untuk proyek-proyek kami, kami selalu terbuka akan teknologi terkini, yang kemungkinan bisa lebih cocok dengan setiap use case yang ada. Dalam proses mengerjakan proyek, kami selalu mencari <em>library</em> yang <em>powerful </em>dan<em> simple </em>— yang bisa membantu kami, <em>developers</em>, untuk mengembangkan sebuah aplikasi seefisien mungkin tanpa merugikan kualitas software. Karena terlibatnya <em>trade-off,</em> pemilihan <em>tools</em> dan <em>library</em> dalam merancang sebuah aplikasi akan berdampak besar dalam beberapa hal, diantaranya sebagai berikut:</p><ul><li><strong>Pengembangan aplikasi lebih cepat</strong></li></ul><p>Anggaplah kita memiliki ide untuk membuat sebuah aplikasi web dengan menggunakan konsep SPA (Single App Aplication). Pertanyaannya adalah, apakah kita akan membuat aplikasi tersebut mulai dari nol menggunakan Javascript? Jawabannya bisa iya dan juga bisa tidak. Namun, untuk mempercepat proses pengembangan, kami sarankan untuk menggunakan pustaka atau kerangka seperti React dan Vue, dimana dengan mudahnya, anda bisa hanya fokus mengembangkan aplikasi tersebut tanpa membuat kodenya dari nol seperti di Javascript.</p><ul><li><strong>Kecepatan <em>delivery</em> sebuah fitur</strong></li></ul><p>Dengan adanya library seperti Chakra UI, mungkin akan sangat mudah dan cepat bagi <em>developers</em> untuk memdeliver fitur-fitur sebuah software (contoh: fitur <em>dark mode) </em>dengan menggunakan <em>custom hook </em>yang di sediakan Chakra UI</p><ul><li><strong>Mempermudah kolaborasi sesama tim</strong></li></ul><p>Dengan adanya library seperti ESLint untuk Javascript, kita bisa menyamakan dan mengkoordinasi gaya penulisan kode sesama team dengan lebih mudah.</p><ul><li><strong>Kemudahan mencari pengembang</strong></li></ul><p>Katakanlah hari ini anda memutuskan untuk menggunakan Clojure untuk proyek anda. Namun khususnya di Indonesia, akan lebih sulit untuk mencari pengembang Clojure di banding mencari pengembang Node.js</p><h3>Membuat Form Dengan React</h3><p>Di ZOG saat ini, kami lebih banyak menggunakan Formik untuk mengakomodir form. Formik adalah sebuah library <em>open source</em> yang ditulis oleh Jared Palmer untuk mengakomodir form di React dan React Native. Namun, sebetulnya tersedia beberapa alternatif form di React selain Formik, antara lain:</p><ul><li>Final Form (<a href="https://github.com/final-form/final-form">https://github.com/final-form/final-form</a>)</li><li>React Form (<a href="https://github.com/TanStack/form">https://github.com/TanStack/form</a>)</li><li>React Redux Form <a href="https://github.com/davidkpiano/react-redux-form">https://github.com/davidkpiano/react-redux-form</a></li><li>React Hook Form (<a href="https://github.com/react-hook-form/react-hook-form">https://github.com/react-hook-form/react-hook-form</a>)</li></ul><p>Dari sisi kami, kami cenderung memilih React Hook Form sebagai bahan riset pembanding untuk Formik karena React Hook Form adalah pustaka kedua yang paling populer selain Formik berdasarkan jumlah <em>stars</em> dan total unduhan yang diperoleh React Hook Form.</p><p>Untuk membandingkan, Disini kami membuat sebuah form yang simple menggunakan React Hook Form dan Formik:</p><ul><li><strong>Form simpel dengan Formik</strong></li></ul><p>Selanjutnya, kami akan menunjukkan bagaimana cara membuat form dengan Formik:</p><p>Pertama-pertama kita butuh untuk menginstall Formik di dalam projek kita cukup Menjalankan perintah</p><pre>npm install formik</pre><p>Langkah selanjutnya kita perlu mengimport Formik. Lalu membungkus form kita dengan komponent Formik kurang lebih tampak seperti ini</p><pre>&lt;Formik <br>      initialValues={{<br>        email: ‘’,<br>      }}<br>      onSubmit={values =&gt; {<br>        // handle form ketika di submit<br>      }}<br>    &gt;<br>      {({ handleSubmit, handleChange, handleBlur, values }) =&gt; (<br>       &lt;Form onSubmit={handleSubmit}&gt;<br>          &lt;input<br>            type=&quot;email&quot;<br>            name=&quot;email&quot;<br>            onChange={handleChange}<br>            onBlur={handleBlur}<br>            value={values.email}<br>          /&gt;<br>          &lt;button type=&quot;submit&quot;&gt;Submit&lt;/button&gt;<br>        &lt;/Form&gt;<br>      )}<br> &lt;/Formik&gt;</pre><p>Komponen Formik menerima beberapa props (argument), diantaranya adalah<strong><em> </em>initialValue</strong> dan <strong>onSubmit</strong><em>.</em></p><p>initialValue adalah sebuah objek yang menerima properti untuk ngeset nilai default input, sedangkan onSubmit menerima sebuah function yang terpanggil pada saat <em>button</em> di submit. Keseluruhan kode bisa dilihat di link di bawah ini</p><p><a href="https://codesandbox.io/s/formik-simple-cw1yib?file=/src/App.js">https://codesandbox.io/s/Formik-simple-cw1yib?file=/src/App.js</a></p><ul><li><strong>Form simpel dengan React Hook Form</strong></li></ul><p>React Hook Form adalah library yang membantu kita memvalidasi formulir di React. Library ini ditulis oleh Beier(Bill) Luo dengan tujuan untuk membuat formulir lebih mudah ditangani di react. Library tersebut adalah library yang minimal tanpa <em>dependency</em> lain, yang berkinerja dengan baik dan mudah digunakan. Dibanding library formulir React lainnya, React Hook Form memaksa para pengembang untuk menulis lebih sedikit baris kode dibanding library formulir lainnya.</p><p>Seperti yang dikatakan sebelumnya, React Hook Form adalah library form React kedua yang populer setelah Formik. Di GitHub, React Hook Form memiliki jumlah <em>stars</em> yang melebihi 28,000 dan dan jumlah unduhan yang melebihi 2,000,000 per minggu. Pada saat artikel ini ditulis, React Hook Form memiliki 0 <em>open issues</em>, 3.174 <em>closed issues</em> dan 5 <em>pull requests.</em> Selanjutnya, kami akan menunjukan cara membuat form simple dengan React Hook Form. Seperti biasa, kami menginstall React Hook Form ke dalam projek kami menggunakan perintah:</p><pre>npm install react-hook-form</pre><p>Setelah terinstall, kami akan mengimpor <em>custom hook</em> dari React Hook Form, yaitu useForm. Kemudian, kami ekstrak register dan handleSubmit dari <em>custom hook tersebut</em>. useForm kodenya kurang lebih tampak seperti ini:</p><pre>import React from &quot;react&quot;;<br>import { useForm } from &quot;react-hook-form&quot;;<br><br>export default function App() {<br>  const { register, handleSubmit } = useForm();<br>  const onSubmit = async data =&gt; { <br>// handle form ketika di submit<br>};<br><br>  return (<br>    &lt;form onSubmit={handleSubmit(onSubmit)}&gt;<br>      &lt;input<br>        {...register(&quot;firstName&quot;, { required: &quot;nama harus di isi&quot; })}<br>      /&gt;<br>      &lt;input type=&quot;submit&quot; /&gt;<br>    &lt;/form&gt;<br>  );<br>}</pre><ul><li><strong>useForm</strong> adalah <em>custom hook</em> yang disediakan React Hook Horm untuk memudahkan kita dalam mengelola formuseForm terdiri dari beberapa function atau hooks yang dapat kita gunakan sesuai kebutuhan, salah satunya hook <em>register</em> dan <em>handleSubmit</em>. Dengan demikian, kita bisa mendaftarkan komponen input kita ke dalam hook register. Sekarang value dari input tersebut akan tersedia dan bisa divalidasi ketika button di submit.</li><li><strong>handleSubmit</strong> menerima sebuah callback yang berfungsi sebagai apa yang terjadi ketika form kita di submit.</li></ul><p>Untuk keseluruhan kode bisa di cek di link di bawah ini</p><p><a href="https://codesandbox.io/s/reack-hook-form-simple-zqyh6l?file=/src/App.js">https://codesandbox.io/s/react-hook-form-simple-zqyh6l?file=/src/App.js</a></p><h3>Membandingkan 2 Pustaka</h3><p>Sampai saat ini, Formik memang lebih populer dibanding React Hook Form berdasarkan stars yang diperoleh di repo GitHub masing-masing library. Tetapi jika dilihat dari sisi jumlah unduhan, React Hook Form mulai mengungguli Formik:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ilZ_h-PIbBXPSpcB" /></figure><p>Dari sisi performa, React Hook Form mengklaim bahwa mereka lebih cepat dibanding pustaka lainnya. Ini karena React Hook Form tidak melakukan <em>re-render component</em>, sedangkan pustaka lain seperti Formik melakukan re-render tersebut.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/0*u9VRmULdcVZPuIqa" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/0*uHxoSK_5l_l9yynk" /></figure><p>Seperti yang telah disebutkan diatas, React Hook Form adalah pustaka tanpa ketergantungan. Inilah yang membuat size React Hook Form lebih kecil dibanding Formik. Hal ini bisa di lihat dari bundle size dari kedua library tersebut:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wyXm5cKmOqOKS0Itv9eeeg.png" /></figure><p>Selengkapnya bisa di cek di link Di bawah ini</p><ul><li><a href="https://bundlephobia.com/package/react-hook-form@7.33.1">React Hook Form</a></li><li><a href="https://bundlephobia.com/package/formik@2.2.9">Formik</a></li></ul><p>Berbeda dengan React Hook Form, penanganan validasi form di Formik relatif akan lebih susah jika tidak ada tambahan library (seperti <strong>Yup</strong>), dikarenakan banyaknya ‘nested if’ di Formik untuk <em>handling errors</em>. Bisa dilihat pada gambar di bawah ini:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*6_GwwTNEfMt9q2lI" /></figure><p>Bedanya di React Hook Form, kita cukup membuat validasi di tiap masing masing input tampak seperti ini:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/972/0*QhWh4eLMcnDzZMuM" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hDJuLPj3-d60hjjf-Hks1g.png" /></figure><h3>Apa yang akan kita buat</h3><p>Seperti yang ditunjukkan diatas, kami telah membuat form yang simple dengan menggunakan kedua library Formik dan React Hook Form, dengan tambahan Chakra UI sebagai UI component (lihat di codesandbox). Dua metode tersebut cukup mudah digunakan bersama Chakra UI. Namun, akan ada sedikit perbedaan jika kita membuat reusable input, karena dibutuhkan<em> forward ref</em> dari React ketika menggunakan React Hook Form.</p><p>Riset kami terhadap kedua library tersebut tidak berhenti sampai disini. Kami akan mencoba membuat form yang lebih kompleks dan mengeksplor bagaimana kami dapat mengimplementasikannya di kedua library tersebut.</p><p>Disini kami akan membuat formulir dengan study kasus untuk menambahkan sebuah keluarga yang terdiri dari beberapa field antara lain ayah, ibu dan anak.</p><p>Formulir tersebut bisa menambah dan menghapus field baik itu parent field atau sub field. Field ayah dan Ibu sebagai parentfield dan anak sebagai subfield dengan demikian study kasus ini bisa mendeksripsikan bagaimana menangani formulir yang kompleks dengan model data array of object.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/593/0*ApeaTuxl4PBR9VOx" /></figure><ul><li><strong>Formik</strong></li></ul><p>Untuk study kasus di atas, di formik kita menggunakan component <strong>FieldArray</strong><em>.</em> Komponen tersebut membantu memanipulasi array dengan memberikan property name yang berfungsi sebagai jalur untuk menyimpan data. Kemudian dengan <strong><em>arrayHelpers </em></strong>dengan mudah bisa memanipulasi data tersebut seperti menambahkan field atau menghapus field.</p><p>Untuk menambah kita bisa menggunakan method <strong><em>arrayHelpers.push </em></strong>kuntuk menghapus field tersebut kita bisa menggunakan <strong><em>arrayHelpers.remove </em></strong>dimana menerima sebuah parameter index berdasarkan field yang mana yang bakal kita hapus</p><pre>&lt;FieldArray name=&quot;families&quot;&gt;<br>   {(arrayHelpers) =&gt; (<br>     &lt;Box bg=&quot;gray.900&quot; borderRadius=&quot;lg&quot; p=&quot;5rem&quot; m=&quot;1rem&quot;&gt;<br>       {values.families &amp;&amp;<br>         values.families.map((family, index) =&gt; (<br>           &lt;Box<br>             key={index}<br>             border=&quot;1px&quot;<br>             borderColor=&quot;gray.200&quot;<br>             borderRadius=&quot;lg&quot;<br>             p=&quot;1rem&quot;<br>             my=&quot;1rem&quot;<br>           &gt;<br>             &lt;Flex color=&quot;white&quot; justifyContent=&quot;center&quot;&gt;<br>               &lt;Fieldinput<br>                 placeholder=&quot;add father&quot;<br>                 type=&quot;text&quot;<br>                 value={family.father}<br>                 name={`families[${index}].father`}<br>                 onChange={handleChange}<br>               /&gt;<br>               &lt;Fieldinput<br>                 type=&quot;text&quot;<br>                 placeholder=&quot;add mother&quot;<br>                 value={family.mother}<br>                 name={`families[${index}].mother`}<br>                 onChange={handleChange}<br>               /&gt;<br>             &lt;/Flex&gt;<br>             &lt;Children<br>               index={index}<br>               values={values}<br>               handleChange={handleChange}<br>             /&gt;<br>             &lt;Button<br>               mt=&quot;1rem&quot;<br>               type=&quot;button&quot;<br>               onClick={() =&gt; arrayHelpers.remove(index)}<br>             &gt;<br>               Delete a family<br>             &lt;/Button&gt;<br>           &lt;/Box&gt;<br>         ))}<br>       &lt;Flex justifyContent=&quot;space-between&quot;&gt;<br>         &lt;Button<br>           type=&quot;button&quot;<br>           onClick={() =&gt;<br>             arrayHelpers.push({<br>               father: &quot;&quot;,<br>               mother: &quot;&quot;,<br>               children: []<br>             })<br>           }<br>         &gt;<br>           Add a family<br>         &lt;/Button&gt;<br>         &lt;Button type=&quot;submit&quot;&gt;Submit&lt;/Button&gt;<br>       &lt;/Flex&gt;<br>     &lt;/Box&gt;<br>   )}<br> &lt;/FieldArray&gt;</pre><p>Di Formik ada sebuah props initialValue yang berfungsi untuk menberikan default value terhadap field input form seperti yang disebutkan sebelumnya. bisa kita lihat di potongan kode di bawah kita bisa memperlakukan children hanya sebatas array berbeda dengan reack hook form yang akan di bahas pada section selanjutnya.</p><pre>&lt;Formik<br> initialValues={{<br>   families: [<br>     {<br>       father: &quot;&quot;,<br>       mother: &quot;&quot;,<br>       children: [&quot;&quot;]<br>     }<br>   ]<br> }}<br> onSubmit={(values) =&gt; {<br>   setTimeout(() =&gt; {<br>     alert(JSON.stringify(values, null, 2));<br>   }, 400);<br> }}<br>&gt;</pre><p>Untuk kode yang lebih lengkap bisa dilihat di link di bawah ini:</p><p><a href="https://codesandbox.io/s/formik-kompleks-v2-vidc0j?file=/src/App.js">https://codesandbox.io/s/Formik-kompleks-v2-vidc0j?file=/src/App.js</a></p><ul><li><strong>React Hook Form</strong></li></ul><p>React Hook Form sendiri menggunakan custom hook <strong><em>useFieldArray</em></strong> yang mereturn sebuah method <strong><em>append</em></strong> dan <strong><em>remove</em></strong> yang berfungsi untuk menambah dan menghapus field dan mereturn <strong><em>field</em></strong> yang berisi objek dari default value . Kemudian <strong><em>useFieldArray </em></strong>itu juga menerima sebuah props <strong><em>name</em></strong>. <strong><em>name</em></strong> disni sebagai atribut name dari field array.</p><pre>const { fields, append, remove } = useFieldArray({<br>   name: &quot;families&quot;<br> });</pre><p>Di React Hook Form untuk memberikan nilai default terhadap field kita bisa menggunakan custom hook <strong><em>useForm </em></strong>dengan props defaultValues. Sebelumnya sempat di sebutkan di atas mengenai bagaimana React Hook Form menghandle children field yaitu harus di buat objek karena React Hook Form mempelakukan field sebagai objek</p><pre>const { register, handleSubmit } = useForm({<br> defaultValues: {<br>   families: [<br>     {<br>       father: &quot;&quot;,<br>       mather: &quot;&quot;,<br>       children: [{ name: &quot;&quot; }]<br>     }<br>   ]<br> }<br>});</pre><p>Untuk contoh implementasi dapat yang lebih lengkap dilihat di link bawah ini <a href="https://codesandbox.io/s/reack-hoook-form-compleks-2jy7f0?file=/src/App.js:781-794">react hook form kompleks</a></p><p>Berdasarkan demo dari kedua library tersebut, untuk mengakomodir form yang kompleks akan sangat mudah dengan menggunakan custom hook yang sudah tersedia seperti <strong>FieldArray</strong><em> </em>dari Formik dan <strong>useFieldArray</strong><em> </em>dari React Hook Form. Dan beberapa Function Helper untuk mengelola <em>array.</em></p><h3>Pelajaran yang didapat</h3><p>Penggunaan dari kedua library tersebut tidak cukup jauh berbeda hanya menggunakan pendekatan yang berbeda dimana formik menggunakan custom component sedangkan React Hook Form memilih menggunakan custom hook.</p><p>Tidak bisa di pungkiri, React Hook Form sudah mulai mengungguli Formik. Kedepannya, mungkin React Hook Form bisa menjadi pilihan yang dapat di pertimbangkan untuk sebuah pustaka form React karena manfaat yang dimilikinya, di antara lain:</p><ul><li>Kecepatan atau performa yang dapat diandalkan</li><li>Ukuran size yang lebih kecil</li><li>Library tanpa dependensi lain</li><li>Validasi simple form relatif mudah tanpa perlu library tambahan</li></ul><h3>Referensi</h3><ul><li><a href="https://formik.org/docs/overview">Formik Documentation</a></li><li><a href="https://react-hook-form.com/api">React Hook Form Documentation</a></li><li><a href="https://www.npmtrends.com/final-form-vs-formik-vs-react-form-vs-react-redux-form-vs-react-hook-form">Final Form vs Formik vs React Form vs React Redux Form vs React Hook Form</a></li><li><a href="https://www.liquidweb.com/kb/formik-react/">What is Formik?</a></li><li><a href="https://blog.logrocket.com/react-hook-form-vs-formik-comparison/">React Hook Form vs. Formik: A technical and performance comparison</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9885861da6c6" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Ionic, React Native, and Flutter in One Nx Monorepo]]></title>
            <link>https://medium.com/@zeroonegroup/ionic-react-native-and-flutter-in-one-nx-monorepo-ff58196a0125?source=rss-bd9b245f3b89------2</link>
            <guid isPermaLink="false">https://medium.com/p/ff58196a0125</guid>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[app-development]]></category>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[ionic]]></category>
            <category><![CDATA[flutter]]></category>
            <dc:creator><![CDATA[Zero One Group]]></dc:creator>
            <pubDate>Tue, 30 Nov 2021 03:19:07 GMT</pubDate>
            <atom:updated>2021-12-01T05:22:37.272Z</atom:updated>
            <content:encoded><![CDATA[<p><em>By </em><a href="https://medium.com/@rohmad_st"><em>Rohmad Sasmito</em></a><em>, Senior Product Engineer at Zero One Group</em></p><p>One of the most common requests we, Zero One Technology (ZOT), get from our clients is to build cost-effective MVPs. We believe that building hybrid mobile apps fits the bill in terms of speed and cost.</p><p>Previously, our approach had been to use Ionic as our go-to mobile hybrid application solution. We have been developing an Ionic-based application for the last five months. As we added more and more features into the application, we found a number of challenges in building the application using Ionic. In particular, these include:</p><ul><li><strong>Limited possibilities for customization.</strong> We can only customize exposed properties<em>. </em>For example, when we want to use a <a href="https://ionicframework.com/docs/api/title">Title component</a>, it is only possible to change some of the basic properties, such as the color. Ionic makes it impossible to modify some properties due to the removal of shadow DOM piercing.</li><li><strong>Inconsistent solution in different stacks.</strong> A particular solution that may work in Ionic Angular, may not necessarily work in Ionic React.</li><li><strong>Lack of community support.</strong> The community support in the official repository is not as active as other comparable projects. A lot of the issues are still waiting for answers.</li></ul><p>Considering the problems mentioned above, we spent some time looking into different hybrid-app solutions. We tried to build the same application with three different hybrid stacks. In this blog post, we will discuss a few alternatives along with their pros and cons.</p><h3>Case Studies with Nx Monorepos</h3><p><a href="https://nx.dev/">Nx</a> has been a huge productivity boost in our development process to build products in a monorepo, and it comes with a lot of advantages. We can easily generate high-quality project skeletons that allow us to be productive immediately. We are happy to say that our experience has been overwhelmingly positive on Nx. For the comparisons to be meaningful for ZOT’s use case, we have embedded each hybrid stack in its own Nx monorepo.</p><h3>Comparison Ionic, React Native, and Flutter</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*tI9jBIhKq5pgV_Ep" /><figcaption>An illustration of an app and its available components</figcaption></figure><p>In this blog, we want to discuss how we build applications in different hybrid stacks in Ionic, React Native, and Flutter. We will discuss the advantages and disadvantages of each solution while assessing whether or not a framework is a good fit for the use case.</p><p>We decided to investigate the comparison of each solution based on a real use case. We have built this over a single monorepo, which you can see <a href="https://github.com/zero-one-group/ionic-react-native-flutter">here</a>. The final product is similar to the image shown in the banner above. We built it as simple as possible and our focus is to know more about the development experience of each stack.</p><h3><strong>Build Component</strong></h3><p>In the following sections, we will compare each solution by explaining how we build app components in each stack. The components we will discuss are <strong><em>Avatar</em></strong>, <strong><em>Tabs</em></strong>, <strong><em>Header</em></strong>, and <strong><em>Card</em></strong>. In <strong>Ionic</strong> and <strong>React Native, </strong>the components are called Components, whereas in <strong>Flutter</strong> they are called Widget as in the native term.</p><h4><strong>Avatar</strong></h4><p>As shown in the image above, Avatar is a circular image with a border. Since it is Javascript in <strong>Ionic</strong>, we would only need about three lines of code. It is clear and simple.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7199ccb587532285d32c805ac4e8095f/href">https://medium.com/media/7199ccb587532285d32c805ac4e8095f/href</a></iframe><p><strong>Ionic</strong> uses Javascript, HTML, and CSS. We can add custom design to the above element by adding a few lines of CSS below We can also use rem<em> </em>in <strong>Ionic</strong>. However, In React Native, although it is Javascript, we cannot use <em>rem</em> for units.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1d18c8b1ef0def84894fc9dcf8c2d13f/href">https://medium.com/media/1d18c8b1ef0def84894fc9dcf8c2d13f/href</a></iframe><p>In <strong>Flutter</strong> we can build Avatar using the block code below. Since we would have to use Dart to develop using <strong>Flutter</strong>, its syntax is the odd one out compared to JS-based stacks. We need to register <em>assets</em> folder into <strong><em>pubspec.yaml</em></strong> file.</p><p>These codes would be reasonably long compared to Ionic or React Native. However, <strong>Flutter</strong> has built <a href="https://flutter.dev/docs/get-started/editor">Plugins</a> for editors like VSCode as a remedy, which improves the development experience considerably.</p><p>Flutter Widget often uses a <em>Container,</em> similar to <em>div</em> in Web. <a href="https://api.flutter.dev/flutter/widgets/Container-class.html">Container</a> has properties such as padding, margin, color, width, and height. Most flutter widgets use <em>decoration</em> property to customize the styles. In this case we used <a href="https://api.flutter.dev/flutter/painting/BoxDecoration-class.html">BoxDecoration</a> as it provides a variety of ways to draw a box.</p><p>The <em>child</em> is an attribute to give a children box. Here, we use <a href="https://api.flutter.dev/flutter/widgets/ClipRRect-class.html">ClipRRect</a>, a widget that clips its child using a rounded rectangle. Inside of ClipRRect we placed an <a href="https://api.flutter.dev/flutter/widgets/Image-class.html">Image</a> to display an image.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/de2e4cf15bb02be5e16739ca99d7c34c/href">https://medium.com/media/de2e4cf15bb02be5e16739ca99d7c34c/href</a></iframe><p>Whereas in <strong>React Native,</strong> we can build an Avatar component using codes like below. <a href="https://reactnative.dev/docs/image"><em>Image</em></a> is a built-in component in React Native to display an image. And inside of Image, we could place an image asset using <em>require</em> into a <em>source</em> attribute<em>.</em></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1e3ece1a316c328a5363b0eb3b485352/href">https://medium.com/media/1e3ece1a316c328a5363b0eb3b485352/href</a></iframe><p>To add design, we could use a <a href="https://reactnative.dev/docs/stylesheet"><em>StyleSheet</em></a><em>. StyleSheet </em>is an abstraction similar to<em> CSS StyleSheets</em>.</p><p>As mentioned above, we are unable to use <em>rem</em> units in <strong>React Native</strong>. For the width and height, we use <em>pixels or percentages</em> instead.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/538d34153e08e17eb95b0a80fc7e7514/href">https://medium.com/media/538d34153e08e17eb95b0a80fc7e7514/href</a></iframe><p><strong>Tabs</strong></p><p>In the following sub-section, we describe the tabs in the example application, which is composed of a row of three buttons.</p><p>To make a Row in <strong>Ionic</strong>, we can use <a href="https://ionicframework.com/docs/api/row"><em>IonRow</em></a>, a built-in component of Ionic. We can then transform each piece of button component into a <a href="https://github.com/zero-one-group/ionic-react-native-flutter/tree/master/apps/profile-ionic/src/app/components/Figure">Figure component</a>.</p><p><strong><em>Figure</em></strong> is our own component that receives parameter <strong><em>count</em></strong> and<strong><em> title</em></strong> both in <em>string</em> type. <a href="https://ionicframework.com/docs/api/grid"><em>IonGrid</em></a> is a powerful mobile-first flexbox system used for building custom layouts. <a href="https://ionicframework.com/docs/api/row">IonRow</a> are horizontal components of the <a href="https://ionicframework.com/docs/api/grid">grid</a> system and contain varying numbers of <a href="https://ionicframework.com/docs/api/col">columns</a>. They ensure the columns are positioned properly.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d55d8ac6bcaed516af8170d9ce2a21ce/href">https://medium.com/media/d55d8ac6bcaed516af8170d9ce2a21ce/href</a></iframe><p>However, when we want to build a component in Flutter, it would look slightly different. Dart and Flutter are type-safe, and Flutter Plugin will let us know whenever the types do not line up. Also, note the use of the <em>const </em>keyword, as we are not using declared variables.</p><p><a href="https://api.flutter.dev/flutter/widgets/Row-class.html">Row</a> in Flutter is a widget that displays its children in a horizontal array.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d60c42a065c2d2395a67d6b3a4e38213/href">https://medium.com/media/d60c42a065c2d2395a67d6b3a4e38213/href</a></iframe><p>In <strong>React Native</strong>, It looks pretty similar to Ionic. It is fairly simple even though React Native requires the use of built-in components. The difference to Ionic is we cannot use <em>div</em>. Instead, we use <a href="https://reactnative.dev/docs/view"><em>View</em></a>, which is a container that supports layout with flexbox, style, some touch handling, and accessibility controls.</p><p>Though it looks like an Ionic component, inside of <em>View</em> we put children that are called <a href="https://github.com/zero-one-group/ionic-react-native-flutter/blob/master/apps/profile-react-native/src/app/components/Figure.tsx">Figure component</a>. The difference is only the background parameter, since we cannot use :<em>nth-child </em>in <strong>React Native</strong> like in <strong>Ionic.</strong></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a6dd6cde7c79382914c745f747967253/href">https://medium.com/media/a6dd6cde7c79382914c745f747967253/href</a></iframe><p><strong>Header</strong></p><p>Header is a light-colored box with a title on the left and a small action button on the right side. In Ionic, it has the codes shown in the image below. There is an <em>IonRow</em> on the outside, and on the children’s property, it has <em>IonCol</em>. Inside it, there is a <em>div</em> with a tag paragraph and <a href="https://ionic.io/ionicons"><em>IonIcon</em></a> to display an icon.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/82030f5cc68407a84f74bf37ac34004b/href">https://medium.com/media/82030f5cc68407a84f74bf37ac34004b/href</a></iframe><p>As mentioned above, we use a <em>Container</em> in <strong>Flutter</strong> as we need to give color, and padding. On the children property, we place a <em>Row </em>to display the title and an action button, which will be laid out horizontally. <a href="https://api.flutter.dev/flutter/widgets/GestureDetector-class.html">GestureDetector</a> is a widget to detect gestures to make the icon clickable.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/70a232b66c2e15d8769165b45a0f2a54/href">https://medium.com/media/70a232b66c2e15d8769165b45a0f2a54/href</a></iframe><p>In <strong>React Native</strong>, to build a header with a title and action in horizontal view, we would use View, and place a couple of Text and Icon like in the image shown below.</p><p>We do not use any libraries to handle icons. Instead we are only importing an <em>svg</em>. because it was not as straightforward to add an icon library. Therefore, we prefer to only import svg, just like what we did when building a React application.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6ceaadb2815400c59bd1398b633215d8/href">https://medium.com/media/6ceaadb2815400c59bd1398b633215d8/href</a></iframe><p><strong>Card</strong></p><p>Card is a box that contains post articles such as avatar, date, username, title, comments, likes, and share button.</p><p>In <strong>Ionic </strong>(<a href="https://github.com/zero-one-group/ionic-react-native-flutter/tree/master/apps/profile-ionic/src/app/components/Post">code</a>), there is an <em>IonLabel</em>, which is a wrapper element that can be used in combination with other built-in components such as <a href="https://ionicframework.com/docs/api/item">ion-item</a>, <a href="https://ionicframework.com/docs/api/input">ion-input</a>, and <a href="https://ionicframework.com/docs/api/toggle">ion-toggle</a>. The position of the label inside of an item can be inlined, fixed, stacked, or floating.</p><p>For <strong>Flutter</strong> (<a href="https://github.com/zero-one-group/ionic-react-native-flutter/blob/master/apps/profile-flutter/lib/home/components/card.dart">code</a>), the codebase may look similar to the Ionic counterpart. You may also notice we are using an <em>Expanded</em> widget. Expanded is a widget that expands a child of a Row, Column, or Flex so that the child fills the available space. Using Row, we split the box into 2 parts in our <strong>Flutter</strong> codebase. On the left side we placed an Avatar Image with defined size, and on the right side we placed date, username, description, comments, likes, and share button. We also used <em>Expanded </em>to<em> </em>fill up the remaining space on the right side of the box.</p><p>As for <strong>React Native</strong> (<a href="https://github.com/zero-one-group/ionic-react-native-flutter/blob/master/apps/profile-react-native/src/app/components/Post.tsx">code</a>), there is nothing new in the codebase. We simply use View, Text, SVG Icon, and other components we have mentioned before.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*_uiR2Ws4boqN0rJp" /><figcaption>Comparison of app in Ionic, Flutter and React Native</figcaption></figure><h3>Support</h3><p>We have explored how to build the same application in three hybrid stacks. The initial setup of developing them was fairly straightforward. However, the hardest part is keeping it simple when we add more and more features to the app, especially when the UI becomes complex. For our use case, it is important not to be confronted with a stack-specific development blocker. For that reason, we very much value the ability to easily find solutions on Stack Overflow and a responsive community on the project’s repository.</p><h4>Ionic</h4><p>When we look at the <a href="https://github.com/ionic-team/ionic-framework/issues">Ionic official repository</a>, we see a lot of open, long-unanswered issues. This indicates that the Ionic community at Github is less responsive. Although we often find answers on Stack Overflow, they are often framework specific.</p><h4>Flutter</h4><p>When we look at the <a href="https://github.com/flutter/flutter/issues">official Flutter forum</a>, we see that many issues are still open like Ionic. However, upon further inspection, it looks like the community is active enough to respond to each issue. Furthermore, this technology is made by Google, which has a big supportive community and staff dedicated to maintaining their open source projects. So if we were to build a mobile application with Flutter, support would be quite low in our list of worries.</p><h4>React Native</h4><p>When we look at the <a href="https://github.com/facebook/react-native/issues">official React Native forum</a>. We see that the community activity is comparable to that of Flutter. And since React Native was built by Facebook, we also would not need to worry much about community support.</p><h3>Final Thoughts</h3><p>The hybrid-app solutions, Ionic, React Native, and Flutter have been growing fast in popularity. These technologies provide us with fast development at a relatively low cost. These solutions also give us the ability to create beautiful, high-performance apps that work everywhere.</p><p><strong>Ionic’s</strong> guiding principle is to use the web platform and embrace open standards wherever possible. When we build an app with Ionic, we will learn and apply the tools and languages of the web, using a framework designed to deliver great performance on mobile, desktop, and especially, the web.</p><p><strong>Flutter</strong>, in contrast, has chosen to go at it alone, creating a self-contained ecosystem that is at odds with the common languages, toolsets, and standards found in the broader hybrid app development world. Thus, if we choose Flutter, we will be learning the Flutter way of doing things. Of course, there are clear benefits to a custom architecture that has one single purpose, as we’ve seen in some of their impressive early demos.</p><p><strong>Ionic</strong> is very popular as it eliminates the learning of a new language factor whereas <strong>Flutter</strong> needs the developers to learn Dart programming language in order to build cross-platform apps. Although, when it comes to building highly graphical apps, Ionic is never the first choice of the app developers; React Native comes into play in this case. Flutter is new compared to Ionic and React Native but is soon getting the recognition it deserves.</p><h3>Consideration Upon Choosing a Framework</h3><p>Choosing the right framework for a company like ZOT can be challenging. However, to simplify the initial stages of building a mobile application, we try to come up with a rule of thumb for choosing a framework depending on the situation.</p><p>We would suggest using <strong>Ionic</strong>, when:</p><ul><li>The development team has little experience in mobile application development. This is because they would not need to learn a new language if they already know HTML, CSS, Javascript and a frontend framework such as React or Angular.</li><li>The business needs to build similar applications for mobile, desktop and web at a low cost and/or with a tight deadline.</li><li>The business requires good web performance.</li></ul><p><strong>Flutter</strong> when the business:</p><ul><li>Requires good mobile-app performance with a lot of interactive features.</li><li>Aims to continually build upon and provide long-term support of the mobile application.</li><li>Requires an optimized application size.</li><li>Is not terribly concerned about web performance.</li></ul><p>We would try to avoid <strong>React Native</strong> for the following reasons;</p><ul><li>Too much dependency with other external libraries.</li><li>Built-in components that are not as customizable.</li><li>Many deprecated dependencies in older versions.</li></ul><h3>Resources</h3><ul><li>“AccessibilityInfo .” <em>React Native</em>, <a href="https://reactnative.dev/docs/accessibilityinfo">https://reactnative.dev/docs/accessibilityinfo</a></li><li>“Dart Api Docs.” <em>Flutter</em>, <a href="https://api.flutter.dev/index.html">https://api.flutter.dev/index.html</a></li><li>“Facebook/React-Native.” <em>GitHub</em>, <a href="https://github.com/facebook/react-native">https://github.com/facebook/react-native</a></li><li>“What Is Flutter, and Why It Seems like the Future in App Development?” <em>DNAMIC</em>, <a href="https://dnamic.ai/blog/what-is-flutter/">https://dnamic.ai/blog/what-is-flutter/</a></li><li>Flutter. “Flutter.” <em>GitHub</em>, <a href="https://github.com/flutter/flutter">https://github.com/flutter/flutter</a></li><li>Ionic. “Ionic Framework.” <em>Ionic </em>, <a href="https://ionicframework.com/docs.">https://ionicframework.com/docs</a></li><li>Ionic-Team.“Ionic-Framework.” <em>GitHub</em>, <a href="https://github.com/ionic-team/ionic-framework">https://github.com/ionic-team/ionic-framework</a></li><li>Matt Netkow. “Ionic vs Flutter: Best Platform for Hybrid App Development.” <em>Ionic </em>, 25 Oct. 2021, <a href="https://ionic.io/resources/articles/ionic-vs-flutter-comparison-guide">https://ionic.io/resources/articles/ionic-vs-flutter-comparison-guide</a></li><li>Sandip Patel . “Ionic, Flutter, and React Native: When to Use Them .” <em>DZone</em>, 21 May 2021, <a href="https://dzone.com/articles/what-are-ionic-flutter-amp-react-native-when-to-us">https://dzone.com/articles/what-are-ionic-flutter-amp-react-native-when-to-us</a></li></ul><p><strong><em>Follow Zero One Group at </em></strong><a href="http://instagram.com/zero_one_group.com"><strong><em>Instagram</em></strong></a><strong><em>, </em></strong><a href="https://twitter.com/zero_one_group"><strong><em>Twitter</em></strong></a><strong><em>, </em></strong><a href="https://www.facebook.com/01.zeroonegroup/"><strong><em>Facebook</em></strong></a><strong><em>, and </em></strong><a href="https://www.linkedin.com/organization-guest/company/zeroonegroup"><strong><em>LinkedIn</em></strong></a><strong><em>. Visit our website at </em></strong><a href="http://www.zero-one-group.com/"><strong><em>www.zero-one-group.com</em></strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ff58196a0125" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Segmentasi Pelanggan: Rangkuman dari Buku Computer Vision]]></title>
            <link>https://blog.zero-one-group.com/segmentasi-pelanggan-rangkuman-dari-buku-computer-vision-dcb1d8af97b9?source=rss-bd9b245f3b89------2</link>
            <guid isPermaLink="false">https://medium.com/p/dcb1d8af97b9</guid>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[algorithms]]></category>
            <category><![CDATA[customer-segmentation]]></category>
            <category><![CDATA[marketing]]></category>
            <dc:creator><![CDATA[Zero One Group]]></dc:creator>
            <pubDate>Wed, 27 Oct 2021 12:58:16 GMT</pubDate>
            <atom:updated>2021-10-27T13:02:00.230Z</atom:updated>
            <content:encoded><![CDATA[<p><em>Oleh </em><a href="https://www.linkedin.com/in/anthony-khong"><em>Anthony Khong</em></a><em>, Pendiri dan SVP Data Analytics di Zero One Group</em></p><p><em>Terjemahan oleh Abid Mukhlisin and Ayu Swasti</em></p><p><a href="https://zero-one-group.com/">Zero One Technology</a> dan Stream Intelligence telah bekerja sama untuk membangun solusi berbasis teknologi untuk salah satu pemain ritel terbesar di Indonesia. Di antara solusi yang dibangun adalah segmentasi pelanggan atau <em>customer segmentation</em>, berdasarkan <em>machine learning</em>. Setiap persona yang dihasilkan dari perkelompokan pelanggan tidak hanya mencerminkan perilaku belanja, namun juga kepribadian yang memperkaya narasi setiap segmen.</p><p>Algoritma yang kami gunakan bernama <em>non-negative matrix factorisation, </em>atau<em> </em>NMF<em>.</em> Pada dasarnya, NMF digunakan sebagai solusi di bidang <em>computer vision, </em>namun telah diterapkan untuk membangun sekelompok persona di berbagai studi. Algoritma tersebut bekerja dengan cara mempelajari sebuah konsep abstrak yang kemudian dirombak dan dikategorikan kembali sebagai sekelompok tema yang berkontras. Penjelasan lebih lanjut mengenai proses tersebut akan disediakan dalam blog ini.</p><p><strong>Mengapa Segmentasi Pelanggan?</strong></p><p>Segmentasi pelanggan adalah proses pembagian pelanggan menjadi beberapa kelompok yang memiliki karakteristik yang sama. Hal tersebut dapat membantu suatu perusahaan untuk mengerti pelanggan mereka lebih baik, dan seterusnya merancang strategi yang sesuai melalui berbagai metodologi termasuk <em>brand positioning </em>atau posisi merek, <em>one-to-one marketing </em>(pemasaran produk kepada pelanggan secara langsung), dan rekomendasi produk yang ditargetkan kepada setiap individu. Kadang, segmentasi bahkan dapat digunakan untuk mengidentifikasikan segmen yang sudah tidak aktif dalam portfolio pelanggan dan juga berguna untuk meluncurkan kampanye akuisisi yang meyakinkan (Groysberg, 2018).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/880/1*QfaBHzvmnMH3aBXxPdBuEQ.png" /><figcaption>Contoh profil persona oleh Salminen et al. (2018)</figcaption></figure><p>Segmentasi pelanggan juga dapat digunakan sebagai landasan untuk <em>customer persona generation</em>, didefinisikan sebagai “orang fiktif yang mewakili pelanggan atau kelompok pengguna yang mendasarinya”. Persona pelanggan menggambarkan suatu segmen menjadi kesatuan dengan visualisasi yang jelas, cerita latar belakang, dan transaksi pelanggan dengan penjual. Manfaat utama dari metode tersebut adalah untuk menyediakan model mental yang realistis dari berbagai jenis pelanggan untuk para pemimpin direksi utama di bisnis tersebut. Namun, penghasilan persona juga dikritik karena kekurangan verifikasi dan tindakannya.</p><p>Dalam situasi ini, kami menyaksikan munculnya perkumpulan data yang kaya seperti statistik keterlibatan aplikasi dan perilaku belanja, ditambah dengan peningkatan ketersediaan data analitik online seperti sumber data media sosial. <em>Automated data-driven customer segmentation</em> dapat digunakan untuk banyak penjual dengan cepat dan platform teknologi yang direalisasikan oleh banyaknya kumpulan data yang kaya. Ini sering kali merupakan hal yang mudah dan langkah pertama untuk memahami pelanggan mereka dengan lebih baik.</p><p><strong>Non-Negative Matrix Factorisation</strong></p><p>Lee dan Seung pertama kali memperkenalkan algoritma NMF pada tahun 1999 untuk mempelajari <em>part-based representations </em>dari sebuah objek, yang secara pada awalnya mengacu pada fitur gambar wajah dan fitur semantik teks.</p><p>Sama seperti teknik matriks factorisation lainnya termasuk <em>principal component analysis </em>(PCA) dan <em>independent components analysis</em> (ICA), algoritma NMF mengurai matriks menjadi dua non-negatif matriks yang lebih kecil, yang bila dikalikan menjadi sebuah matriks yang mendekati matriks aslinya:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*c5p9VfhYNVDNvnu7UdcxJg.jpeg" /><figcaption>Sebuah ilustrasi yang menggambarkan bagaimana algoritma NMF menguraikan pola wajah kanonik dan peta pola wajah individu dari gambar-gambar wajah.</figcaption></figure><p>Mengambil contoh gambar wajah, algoritma NMF menguraikan banyak gambar wajah yang tersedia menjadi peta pola wajah individu dan pola wajah kanonik bersama. Tidak serupa dengan saat mempelajari eigenfaces melalui PCA, NMF hanya mengizinkan komponen aditif non-negatif, sehingga setiap pola wajah kanonik dapat menyerupai bagian wajah yang sebenarnya seperti mata, hidung, mulut, dan dagu. Satu karakteristik penting mengenai peta pola wajah individu adalah peta tersebut tersebar dimana-mana. Berarti, setiap peta individu membuang sebagian besar pola wajah, sehingga setiap wajah merupakan kombinasi dari hanya beberapa pola wajah terpilih.</p><p>Tapi apa yang membuat NMF cocok untuk segmentasi, dan bukan PCA? Untuk menjawab pertanyaan ini, bayangkan anda harus mengelompokkan orang berdasarkan gambar wajah mereka. Algoritma menemukan pola wajah kanonik tertentu, katakanlah, jenis hidung tertentu, dan mengidentifikasi setiap orang dengan hidung itu. Proses ini pada dasarnya mengelompokkan sejumlah orang dan membentuk segmen hidung yang serupa. Dengan mengulangi proses untuk semua pola wajah kanonik, kami memperoleh kumpulan segmen yang berdasarkan fitur wajah bersama. Proses ini tidak sama dengan PCA, khususnya karena PCA mengizinkan peta individu yang negatif dan yang tidak tersebar dimana-mana. Untuk apa artinya memamerkan eigenface tertentu, hanya untuk dikurangi dengan eigenface lainnya?</p><p><strong>Segmentasi Pelanggan menggunakan NMF</strong></p><p>Dua dekade kemudian, <a href="https://link.springer.com/article/10.1007/s13278-018-0531-0">An et al. (2018)</a> menggunakan algoritma NMF untuk mengelompokkan penonton akun YouTube AJ+. Dibanding menggunakan piksel gambar, mereka menggunakan tampilan video tertentu untuk menyusun matriks NMF. Dengan menggunakan enam pola perilaku kanonik, kelompok pemirsa teratas dari setiap pola perilaku menunjukkan segmentasi yang jelas dalam hal lokasi, usia, dan jenis kelamin.</p><p>Dengan studi ini, sangat mudah untuk melihat bagaimana teknik ini dapat diterjemahkan ke dalam segmentasi pelanggan di industri ritel. Daripada menggunakan piksel gambar atau tampilan video tertentu, kami dapat menggunakan perilaku belanja yang biasanya tersedia untuk banyak penjual. Secara khusus, kami dapat menggunakan total pengeluaran dari berbagai produk, kategori, waktu, dan metode pembayaran untuk menyusun matriks NMF kami.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*I51tTHOkK1Uzz_Q8szKFew.jpeg" /><figcaption>Sebuah rangkuman mengenai bagaimana cara untuk melakukan segmentasi berdasarkan perilaku dari data transaksi</figcaption></figure><p>Untuk memahami apa yang dilakukan algoritma di tempat, NMF menggabungkan perilaku belanja yang terjadi dalam waktu bersamaan ke dalam set terpisah untuk membentuk pola belanja kanonik; sangat mirip dengan bagaimana NMF menemukan semacam hidung, mata, dagu, dan sebagainya. Dengan demikian, setiap pelanggan dapat diringkas dengan peta perilaku yang terpisah, yang mewakili kombinasi dari beberapa pola belanja.</p><p><strong>Pola Belanja: Jembatan antara Pelanggan dan Perilaku</strong></p><p>Salah satu cara untuk memikirkan pola belanja kanonik adalah bagaimana mereka dapat menghubungkan setiap pelanggan ke segmen masing-masing dan perilaku belanja. Ada beberapa cara di mana hubungan ini menjadi berguna.</p><p>Misalnya, kita ingin mengkategorikan pelanggan ke dalam segmen tertentu. Kami dapat mencari pola belanja teratas setiap pelanggan (yaitu operasi argmax):</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pqyZV46Rasfv2-Qwlbc7Rw.jpeg" /></figure><p>Contoh lain adalah untuk meringkas pola belanja pelanggan tertentu. Pertama-tama kita mencari, katakanlah, tiga pola belanja teratas dan kemudian mencari perilaku teratas dari setiap segmen..</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*v9ZsxWoWarMtVKVUaOVtCA.jpeg" /></figure><p>Terakhir, untuk mengidentifikasi peluang penjualan silang, kami dapat mengidentifikasi pola belanja yang terkait dari produk dasar. Dari pola belanja tersebut, kami dapat mengidentifikasi produk terkait lainnya dan pelanggan yang secara signifikan menunjukkan pola belanja tersebut:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8XWEAbN3raoEK13fdF39mQ.jpeg" /></figure><p><strong>Kesimpulan</strong></p><p>Tidak pernah semudah ini untuk mengakses data pelanggan dalam jumlah besar di dunia ritel. Beberapa penjual bahkan tanpa sadar duduk di atas harta karun berupa data mentah yang dapat ditangani, dianalisa, dan dibentuk menjadi wawasan yang dapat ditindaklanjuti. Kami telah menunjukkan satu contoh dimana kami telah memberikan wawasan seperti itu kepada klien kami.</p><p>Meskipun kami hanya berfokus pada aplikasi ritel, algoritma NMF telah diterapkan ke berbagai aplikasi dalam dekade terakhir ini. Misalnya, NMF telah digunakan untuk rekomendasi film, penemuan komunitas dan bahkan <em>hyperspectral unmixing</em>. Ini telah terbukti menjadi algoritma penemuan pola yang serbaguna!</p><p>NMF sama sekali bukan <em>state-of-the-art machine learning algorithm</em>. Namun NMF dapat menyelesaikan pekerjaan di tempat yang diperlukan. Di Zero One, kami terus melatih tim kami untuk menyederhanakan solusi kami, sambil mempertahankan ketelitian dan memperhatikan kebutuhan bisnis. Sederhana dan efektif, itulah yang kami suka!</p><p><strong>Sumber Daya</strong></p><ul><li>Almohri, Haidar, Ratna Babu Chinnam, and Mark Colosimo. “Data-Driven Analytics for Benchmarking and Optimizing Retail Store Performance.” <em>arXiv preprint arXiv:1806.05563</em> (2018)</li><li>An, Jisun, et al. “Customer segmentation using online platforms: isolating behavioral and demographic segments for persona creation via aggregated user data.” Social Network Analysis and Mining 8.1 (2018): 54.</li><li>Gillis, Nicolas. “The why and how of nonnegative matrix factorization.” Regularization, optimization, kernels, and support vector machines 12.257 (2014): 257–291.</li><li>Groysberg, Boris, and Annelena Lobb. “California Closets: Organizing the Customer Experience.” (2018).</li><li>Lee, Daniel D., and H. Sebastian Seung. “Learning the parts of objects by non-negative matrix factorization.” Nature 401.6755 (1999): 788–791.</li><li>Salminen, Joni, et al. “Generating cultural personas from social data: a perspective of Middle Eastern users.” 2017 5th International Conference on Future Internet of Things and Cloud Workshops (FiCloudW). IEEE, 2017.</li><li>Salminen, Joni, et al. “Are personas done? Evaluating their usefulness in the age of digital analytics.” Persona Studies 4.2 (2018): 47–65.</li><li>Salminen, Joni, Soon-gyo Jung, and Bernard J. Jansen. “The Future of Data-driven Personas: A Marriage of Online Analytics Numbers and Human Attributes.” 21st International Conference on Enterprise Information Systems, ICEIS 2019. SciTePress, 2019.</li><li>Yang, Jaewon, and Jure Leskovec. “Overlapping community detection at scale: a nonnegative matrix factorization approach.” Proceedings of the sixth ACM international conference on Web search and data mining. 2013.</li><li>Zhang, Sheng, et al. “Learning from incomplete ratings using non-negative matrix factorization.” Proceedings of the 2006 SIAM international conference on data mining. Society for Industrial and Applied Mathematics, 2006.</li></ul><p><strong><em>Ikuti Zero One Group di </em></strong><a href="http://instagram.com/zero_one_group.com"><strong><em>Instagram</em></strong></a><strong><em>, </em></strong><a href="https://twitter.com/zero_one_group"><strong><em>Twitter</em></strong></a><strong><em>, </em></strong><a href="https://www.facebook.com/01.zeroonegroup/"><strong><em>Facebook</em></strong></a><strong><em>, dan </em></strong><a href="https://www.linkedin.com/organization-guest/company/zeroonegroup"><strong><em>LinkedIn</em></strong></a><strong><em>. Kunjungi website kami di </em></strong><a href="http://www.zero-one-group.com/"><strong><em>www.zero-one-group.com</em></strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=dcb1d8af97b9" width="1" height="1" alt=""><hr><p><a href="https://blog.zero-one-group.com/segmentasi-pelanggan-rangkuman-dari-buku-computer-vision-dcb1d8af97b9">Segmentasi Pelanggan: Rangkuman dari Buku Computer Vision</a> was originally published in <a href="https://blog.zero-one-group.com/">Zero One Group</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Metode Brand-First Dalam Konteks Digital Marketing]]></title>
            <link>https://medium.com/@zeroonegroup/metode-brand-first-dalam-konteks-digital-marketing-126cc73acddc?source=rss-bd9b245f3b89------2</link>
            <guid isPermaLink="false">https://medium.com/p/126cc73acddc</guid>
            <category><![CDATA[marketing-strategies]]></category>
            <category><![CDATA[digital-marketing]]></category>
            <category><![CDATA[branding]]></category>
            <category><![CDATA[marketing]]></category>
            <category><![CDATA[brand-strategy]]></category>
            <dc:creator><![CDATA[Zero One Group]]></dc:creator>
            <pubDate>Thu, 21 Oct 2021 03:57:05 GMT</pubDate>
            <atom:updated>2021-10-21T04:04:51.484Z</atom:updated>
            <content:encoded><![CDATA[<p><em>Oleh </em><a href="http://linkedin.com/in/swedianlie"><em>Swedian Lie</em></a><em>, Pendiri Zero One Digital</em></p><p>Zero One Digital memandang <em>branding</em> sebagai suatu pola pikiran. Untuk melatih pola pikiran tersebut, kami seringkali mengajukan pertanyaan “<em>Apa yang dapat kita lakukan supaya tantangan-tantangan yang bisnis hadapi dapat diubah menjadi suatu kesempatan untuk mengembangkan dan meningkatkan brand atau merek dari suatu perusahaan?”</em></p><p>Pertanyaan tersebut terpusat pada DNA sebuah brand, dan mengikuti pola kerja digital marketing yang bersifat terintegrasi dan <em>holistic, </em>atau menyeluruh. Proses kami dimulai dengan perkembangan suatu narasi, yang kemudian diolah sehingga dapat memperkaya setiap titik interaksi dengan pelanggan yang ditawarkan sebuah brand. Peningkatan interaksi dapat dialami dalam bentuk online maupun offline, komersial hingga rekreasi, dan berbagai macam lainnya yang dirancang untuk mewujudkan pengalaman berkesan bagi pelanggan.</p><p>Mari pelajari lebih lanjut mengenai metode <em>brand-first digital marketing </em>kami di Zero One Group.</p><p><strong>Fondasi<em> Brand </em>yang Kuat adalah Cerita yang Menarik</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*48dOwzb5N7HvnKkvGvJJLQ.jpeg" /></figure><p>Pada dasarnya, cerita brand atau <em>brand story</em> dibangun oleh sebuah narasi. Perbedaan antara cerita dan narasi adalah — suatu cerita tidak selalu mempunyai tujuan. Sebagai contoh, seringkali kita mendengar “cerita” dari teman yang akhirnya bersangkut tanpa kesimpulan. Sebaliknya, narasi ditimbulkan untuk menetapkan dan memandu suatu tujuan akhir. Dengan penjelasan tersebut, kita dapat mengerti bahwa narasi yang kuat dapat digunakan untuk membimbing sebuah brand.</p><p>Ketika kita berbicara mengenai kisah <em>brand</em> yang kuat, yang sebenarnya kita bicarakan adalah narasi dari suatu <em>brand</em> itu sendiri. Apa perbedaan antara cerita dan narasi? Sebuah cerita dapat dimulai dari mana saja, tetapi sebuah narasi dirancang dengan asal-usul yang jelas untuk memulai narasi tersebut. Jika dilakukan dengan benar, narasi merek yang kuat adalah peta perjalanan merek Anda menuju kesuksesan. Ini menjadi kompas yang Anda dan tim Anda gunakan sebagai pedoman dalam mengambil keputusan penting untuk masa depan perusahaan Anda.</p><p>Narasi sebuah merek yang kuat tidak hanya akan berguna untuk Anda, tetapi juga untuk target audiens Anda. Dalam konteks dunia digital yang rumit saat ini, Anda perlu menceritakan narasi merek Anda seefisien dan seefektif mungkin untuk menimbulkan dampak, tentunya dengan pemilihan media yang tepat. Inilah saatnya identitas merek yang kuat berperan — menghidupkan setiap narasi dan cerita dari brand Anda. Setiap bagian dari identitas, baik itu logo, suara, kemasan, desain interior, dan sebagainya, akan membawa kreativitas dan imajinasi kepada narasi Anda dan membawa suatu kepribadian yang brand Anda butuhkan untuk mengisahkan cerita kepada audiens Anda. Pada idealnya, identitas brand seharusnya tidak hadir sebelum narasi brand itu sendiri. Aktor terhebat di dunia pun tidak dapat memainkan peran sebelum skenario dan naskah ditulis.</p><p><strong>Menceritakan Narasi Brand Melalui Kampanye yang Unik dan Menarik</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*pDz6L9jy40Yahw8UIIJr6g.jpeg" /></figure><p>Saat membicarakan mengenai peran — narasi brand biasanya berwujud sebagai pernyataan yang berdiri sendiri, sebuah manifesto yang mendorong visi dan misi perusahaan Anda. Namun, tidak ada perusahaan yang dapat berdiri sendiri, tanpa audiens yang perlu diajak bicara dan juga di sasar (juga dikenal sebagai “clients”). Pada waktunya, sebuah brand perlu berbicara dan menghubungkan dirinya dengan audiensnya dengan cara yang unik dan menarik. Dalam konsep <em>digital marketing</em>, kami menyebut momen tersebut sebagai kampanye yang kami rencanakan dengan pola pikiran yang jelas dan strategis; diinformasikan oleh narasi <em>brand</em> Anda. <em>Bagaimana kita bisa menyempurnakan merek dan menciptakan hubungan yang bermakna dengan audiensnya?</em></p><p>Pada dasarnya, banyak kelas pelajaran <em>marketing</em> yang membicarakan mengenai meraih audiens dalam bentuk <em>funnel</em> atau diagram, namun di Zero One Digital, kami lebih suka memikirkan keterlibatan audiens dalam hal lingkaran konsentris dan keterlibatan hubungan — bagaimana kami bisa mengembangkan lapisan keterlibatan dan partisipasi audiens yang lebih dalam yang akan menghasilkan hasil yang lebih berarti? Sama seperti hubungan manusia, setiap segmen audiens akan membutuhkan cara yang unik dan sebuah penyesuaian untuk berkomunikasi dengan mereka, dan kami menyesuaikan kampanye kami untuk mengembangkan momen-momen marketing brand yang tidak hanya berkesan, namun juga bermakna. Sama seperti seorang aktor, saat dibimbing oleh narasi dan identitas yang kuat, sang aktor dapat memainkan peran mereka dan berbicara kepada setiap penonton di ruangan seolah-olah mereka satu-satunya orang yang diajak bicara oleh aktor tersebut.</p><p><strong>Meningkatkan Brand di Setiap <em>Touch-point</em></strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*qow6eVbNEVH0kcyg4qXLMA.jpeg" /></figure><p>Setelah membangun narasi dan identitas brand Anda, dan mengembangkan kampanye pemasaran yang menarik untuk memperkuat hubungan Anda dengan audiens Anda, Anda mungkin berpikir bahwa upaya pemasaran telah selesai — namun tidak. Dengan pendekatan <em>branding-as-a-mindset</em> kami, kami selalu memikirkan tentang masa depan dan bagaimana kami dapat meningkatkan brand Anda untuk kesuksesan yang lebih besar. Dengan beragam teknologi dan ekosistem konsultasi kami di Zero One Group, kami memahami pentingnya <em>brand equity</em> dan bagaimana cara untuk meningkatkannya dengan mempertajam dan memperkuat setiap bagian dari pengalaman merek melalui titik kontak <em>offline</em> dan <em>online</em>.</p><p>Kami mengamati dan menganalisa perjalanan audiens Anda dan mengidentifikasi semua pengalaman unik <em>touch-point</em> yang dapat dihidupkan, menggunakan narasi dan identitas merek Anda sebagai DNA. Baik itu melalui situs web interaktif, aplikasi, <em>offline activities</em>, atau iklan video, semua produk ini adalah perpanjangan dari narasi brand Anda. Memiliki investasi untuk mengembangkan produk-produk ini dan memperkuat titik kontak brand anda adalah bagaimana caranya anda dapat membangun<em> </em>masa depan brand anda dan memastikan kekuatannya untuk berlalu.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hb1K2EbLVQm_UoiLRh7IVQ.jpeg" /></figure><p>Sebagian besar agensi digital tidak melihat <em>digital marketing</em> dengan cara yang mengutamakan brand. Pekerjaan mereka hanya didorong dan berdasarkan angka dan metrik yang mudah dipahami, seperti tayangan, <em>likes</em>, tampilan, hasil klik — daftarnya terus bertambah. Data ini masih penting, namun di Zero One Digital, kami pikir mereka kehilangan gambaran besar jika hanya itu yang mereka fokuskan.</p><p>Kami selalu melihat gambaran besarnya — kisah perusahaan atau bisnis Anda, nilai-nilai unik, visi, dan misi yang mendorong Anda maju, dan kesan yang ingin Anda tinggalkan pada brand Anda. Kami menganggap semua ini sebagai bagian dari pendefinisian <em>brand DNA</em> Anda, dan tugas kami adalah membantu, membimbing dan mendukung Anda dalam menghidupkan kisah maupun cerita Anda.</p><p>Ingin mempelajari lebih lanjut tentang pendekatan <em>branding</em> dan pemasaran kami yang unik? Hubungi kami di digital@zero-one-group.com ikuti kami di Instagram <a href="https://www.instagram.com/01.zeroonegroup/">@01.zeroonedigital</a>.</p><p><strong><em>Follow Zero One Group di </em></strong><a href="http://instagram.com/zero_one_group.com"><strong><em>Instagram</em></strong></a><strong><em>, </em></strong><a href="https://twitter.com/zero_one_group"><strong><em>Twitter</em></strong></a><strong><em>, </em></strong><a href="https://www.facebook.com/01.zeroonegroup/"><strong><em>Facebook</em></strong></a><strong><em>, dan </em></strong><a href="https://www.linkedin.com/organization-guest/company/zeroonegroup"><strong><em>LinkedIn</em></strong></a><strong><em>. Kunjungi website kami di </em></strong><a href="http://www.zero-one-group.com/"><strong><em>www.zero-one-group.com</em></strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=126cc73acddc" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[My Summer as a Software Engineer Intern at Zero One Group]]></title>
            <link>https://blog.zero-one-group.com/my-summer-as-a-software-engineer-intern-at-zero-one-group-39729e4ae4dc?source=rss-bd9b245f3b89------2</link>
            <guid isPermaLink="false">https://medium.com/p/39729e4ae4dc</guid>
            <dc:creator><![CDATA[Zero One Group]]></dc:creator>
            <pubDate>Wed, 13 Oct 2021 03:01:25 GMT</pubDate>
            <atom:updated>2021-10-13T03:01:25.384Z</atom:updated>
            <content:encoded><![CDATA[<p>My name is Arthur Soenarto, and I am a Software Engineer Intern at Zero One Group. Having watched a lot of software engineering videos on Youtube, I wanted to experience it for myself and I wanted to know what it’s like to work in a tech company, and so applied for the open position. The internship taught me many things such as writing professional-level code, data analysis, and using version control within a team setting. Moreover, I contributed to our Bloomberg Philanthropies project! I have enjoyed my internship thoroughly and would like to share my experience to fellow students interested in working with ZOG or tech companies in general.</p><p><strong>Getting Started</strong></p><p>I was assigned to the data analysis team for my project, Bloomberg Global Coal Countdown, which made me quite nervous since it was a project for Bloomberg, a well-renowned company. We were in charge of delivering the data components for the project’s website, which meant a great deal of responsibility.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*bX7EwzdqRUqB7aEQ" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Ozt7OhsFbUXUvfdv" /></figure><p>I was tasked to gather news feed data regarding the global coal industry, which was to be used to create informative visualisations. To collect the data, I developed a scraper using web scraping libraries, Selenium and Beautiful Soup. The raw data was then cleaned and organised using Python data science libraries, namely pandas and numpy. We also used data version control (<a href="http://dvc.org/">dvc.org</a>) throughout the process to ensure that frontend developers were able to access the data in a convenient manner. DVC is also used to ensure that we track and have access to all of the changes in the data, so that we have the ability to roll back to any point in the history effortlessly.</p><p>All my nerves were gone by the end of the project, and I was very satisfied with the outcome. The project made me more proficient in my data analysis and version control skills, and more importantly, made me more comfortable with working in a professional team environment. You can see the results of our work in the following link: <a href="http://bloombergcoalcountdown.com/">http://bloombergcoalcountdown.com</a></p><p><strong>Lessons from the Missing Semester Course</strong></p><p>Throughout the internship, I was recommended to complete the MIT Missing Semester course. This helped me to build up practical computer science (CS) skills that were not necessarily taught as part of my formal education. Of the many important CS skills covered, I found that mastering the command-line, using powerful text editors, and accessing fancy features of version control systems to be the most useful. The course even covers some areas of data science. I highly recommend this course to anyone wanting to improve their programming skills.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*GSxVoi_-xK93HGEA" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*0ONp5P21PSRSU1pS" /></figure><p><strong>My Teammates</strong></p><p>I had 10 teammates but interacted most with three people: Anthony, Alex, and Swedian.</p><p>Anthony is the company’s Co-Founder, and data lead. We usually interact during weekly syncs to discuss progress, personal well being, and any CS/software engineering topics. As a mentor/supervisor, Tony reviews my work through code review sessions. He would give me tips on writing professional code while demonstrating his workflow using tmate. I have learned a lot from him and am inspired by his ability to write code with ease.</p><p>Alex is a Software Engineer whom I work closely with in the data team. We have weekly syncs to discuss projects, and just like with Anthony, anything in general. Syncs take different forms which help to both receive feedback, and to get to know colleagues. As he was a recent graduate and not my direct supervisor, my conversations with him felt more easy.</p><p>Finally, Swedian acts as Project Manager (PM) for our Bloomberg Philanthropies project. As a PM, Swedian would lead weekly sprint planning sessions, standups, and product demos. Our conversations would generally revolve around assigned tasks and progress.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/970/1*YERR11zqH6ZQDE5d78oEkw.png" /><figcaption>Anthony, Alex, Swedian</figcaption></figure><p>If I were to repeat my internship, I would have definitely tried to spend more time with my colleagues, apart from our work-based interactions. I highly recommend all interns to make an effort in getting to know colleagues and build lasting friendships.</p><p><strong>Final Thoughts</strong></p><p>It was really cool to experience working at a tech start-up and it definitely lived up to my expectations. Moreover, this internship showed me how tech companies operate. I got to learn through weekly sprint planning sessions, demos, syncs, and code reviews, I learned a lot and most certainly felt like one of those software engineers you see on YouTube videos.</p><p><strong>Follow Zero One Group at Instagram, Twitter, Facebook, and LinkedIn. Visit our website at </strong><a href="http://www.zero-one-group.com/"><strong>www.zero-one-group.com</strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=39729e4ae4dc" width="1" height="1" alt=""><hr><p><a href="https://blog.zero-one-group.com/my-summer-as-a-software-engineer-intern-at-zero-one-group-39729e4ae4dc">My Summer as a Software Engineer Intern at Zero One Group</a> was originally published in <a href="https://blog.zero-one-group.com/">Zero One Group</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Zero One Group Newsletter #8]]></title>
            <link>https://blog.zero-one-group.com/zero-one-group-newsletter-8-d7b7cf8886a?source=rss-bd9b245f3b89------2</link>
            <guid isPermaLink="false">https://medium.com/p/d7b7cf8886a</guid>
            <category><![CDATA[news-articles]]></category>
            <category><![CDATA[digital]]></category>
            <category><![CDATA[nft]]></category>
            <category><![CDATA[newsletter]]></category>
            <category><![CDATA[news]]></category>
            <dc:creator><![CDATA[Zero One Group]]></dc:creator>
            <pubDate>Fri, 30 Apr 2021 01:47:38 GMT</pubDate>
            <atom:updated>2021-04-30T01:47:38.432Z</atom:updated>
            <content:encoded><![CDATA[<p>By Joanna N., Business Development Associate at Zero One Group</p><p>It’s been about a year since the world was thrown into chaos because of COVID-19. Here we are, March 2021 behind us, and things have calmed down a bit in the pandemic scope. However, that doesn’t mean we don’t have some equally as riveting news recaps to share with you about the past month — let’s dive right in!</p><h3>Big ship, even bigger problems.</h3><p><strong>Don’t put all your eggs in one very large container ship.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/976/1*YSinjr02E0feP9D9snCTXw.jpeg" /><figcaption>Tugboats managed to move the Ever Given 30 degrees in both directions, but it remained stuck | <a href="https://www.bbc.com/news/world-middle-east-56547383">BBC</a></figcaption></figure><p>It took <strong>six days to free the Ever Given,</strong> the container ship that ran aground and clogged one of the world’s most vital shipping arteries. The Suez Canal shoulders over 10% of global trade, including 7% of the world’s oil.</p><p>However, economists say the Ever Given’s disruption of shipping probably won’t have an impact on global trade for more than a few weeks and is <strong>unlikely to derail global growth this year</strong> as more people around the world get COVID-19 vaccines and economies reopen.</p><p>If anything, this event serves as <strong>a warning on how vulnerable our supply chains are </strong>and how the just-in-time inventory techniques that have been so popular have to be rethought.</p><p>Follow-up events:</p><ul><li>An investigation is to be carried out to determine whether technical or human error played a part in the stranding of the ship</li><li>The ripple effect of the stuck ship could amount to insurance claims in the hundreds of millions of dollars, as well as broader losses from the delays in the global supply chain</li><li>Analysts estimate that it could take years to sort out who will pay for the mess and who is to blame</li></ul><h3><strong>NFTs — an art bubble within a tech bubble?</strong></h3><p><strong>What is a non-fungible token anyway?</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7kfsV71xbQa5Iiqt6y5avg.jpeg" /><figcaption>Beeple: A Visionary Digital Artist at the Forefront of NFTs | <a href="https://www.christies.com/features/Monumental-collage-by-Beeple-is-first-purely-digital-artwork-NFT-to-come-to-auction-11510-7.aspx">Christie’s</a></figcaption></figure><p>Non-fungible tokens (NFTs), part of the Ethereum blockchain, <strong>represent the ownership of a unique item</strong>. In the case of digital art, where the digital files can be infinitely reproducible, <strong>NFTs basically give you clout</strong> — the proof of ownership of the work lies with the buyer while the artist can retain copyrights. It’s like owning a fine art print vs. an original Picasso.</p><p>It shouldn’t be hard to see why digital artists are jumping on to the NFT movement: it is a chance for them to <strong>make tens or hundreds of thousands of dollars for their artwork,</strong> while still retaining ownership and royalty rights every time their work is sold to another buyer.</p><p>Follow-up events:</p><ul><li>NFTs are currently being touted as an evolution to fine art collecting, even spilling over to real-world auctions</li><li>This technological disruption challenges the notions of the fine art world and breaks down the gatekeeping that often haunts it</li><li>Surely the motivation for buyers and traders is grounded in getting rich quickly — could this simply be a fad or bubble?</li><li>On top of this, the environmental concerns surrounding blockchain are amplified in this use case, giving rise to even more criticism against NFTs</li></ul><h3><strong>EV Digital Competitiveness Index 2021</strong></h3><p><strong>How the pandemic unlocked the digital economy across all of Indonesia.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*h_f0MvvFIMsnSb34bAqlWA.png" /><figcaption>EV-DCI Score Distribution Map | <a href="https://east.vc/dci/">East Ventures</a></figcaption></figure><p>The East Ventures Digital Competitiveness Index 2021 <strong>assesses Indonesia’s digital economic condition </strong>— both strengths and weaknesses of each region, to provide a viewpoint of the massive opportunities that lie in the country.</p><p><strong>Indonesia’s</strong> <strong>digital competitiveness index score increased by 4.13 points</strong> compared to EV-DCI 2020. The median score of 34 provinces also increased, meaning that digital competitiveness has been even between provinces even though the digital climate and ecosystem are still centred around the provinces in Java.</p><p>Follow-up goals:</p><ul><li>A significant push towards getting MSMEs to embrace digital — e.g. government-backed capital assistance in the form of QR-code based payment systems</li><li>An initiative to make Indonesia an even more attractive destination for global tech giants (e.g. AWS, Google Cloud, Microsoft)</li><li>Hopefully, this rapid momentum will carry forward post-pandemic</li></ul><p>Tune in next month to see what’s cooking in the news sphere!</p><p><strong><em>Follow Zero One Group on </em></strong><a href="http://instagram.com/zero_one_group.com"><strong><em>Instagram</em></strong></a><strong><em>, </em></strong><a href="https://twitter.com/zero_one_group"><strong><em>Twitter</em></strong></a><strong><em>, </em></strong><a href="https://www.facebook.com/01.zeroonegroup/"><strong><em>Facebook</em></strong></a><strong><em>, and </em></strong><a href="https://www.linkedin.com/organization-guest/company/zeroonegroup"><strong><em>LinkedIn</em></strong></a><strong><em>. Visit our website at </em></strong><a href="http://www.zero-one-group.com/"><strong><em>www.zero-one-group.com</em></strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d7b7cf8886a" width="1" height="1" alt=""><hr><p><a href="https://blog.zero-one-group.com/zero-one-group-newsletter-8-d7b7cf8886a">Zero One Group Newsletter #8</a> was originally published in <a href="https://blog.zero-one-group.com/">Zero One Group</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Zero One Group Newsletter #7]]></title>
            <link>https://blog.zero-one-group.com/zero-one-group-newsletter-7-579586798ced?source=rss-bd9b245f3b89------2</link>
            <guid isPermaLink="false">https://medium.com/p/579586798ced</guid>
            <category><![CDATA[myanmar]]></category>
            <category><![CDATA[newsletter]]></category>
            <category><![CDATA[clubhouse]]></category>
            <category><![CDATA[indonesia]]></category>
            <category><![CDATA[microsoft]]></category>
            <dc:creator><![CDATA[Zero One Group]]></dc:creator>
            <pubDate>Wed, 24 Mar 2021 09:40:28 GMT</pubDate>
            <atom:updated>2021-03-24T09:40:28.624Z</atom:updated>
            <content:encoded><![CDATA[<p>By Joanna N., Business Development Associate at Zero One Group</p><p>February flew by real quick. While it was a short month, we witnessed a lot of developments on a global scale — and this newsletter is here to talk about three of them.</p><p>We picked some thought-provoking topics this month, so buckle up and let’s get into it!</p><h3>Clubhouse — a case of “They grow up so fast”</h3><p><strong>The frenzy behind the current hottest app straight out of Silicon Valley.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*1swtOpdHMYUmgrz7ud8Kgw.jpeg" /><figcaption>Clubhouse on the App Store | <a href="https://www.businessinsider.com/what-is-clubhouse-app?r=US&amp;IR=T">Business Insider</a></figcaption></figure><p>Clubhouse, an iOS-exclusive, invitation-only social audio app, has been facing a surge in popularity as of late. <strong>The app has attracted over 10 million users in its 11-month lifespan</strong>, setting off a mad dash among investors, who have valued the company at $1 billion.</p><p>The appeal lies with Clubhouse’s core technological innovation — facilitating the real-time exchange of ideas through live, auditory experiences for any type of audience. This app’s key selling point is also the cause of its own <strong>growing pains</strong>.</p><p>Follow-up events:</p><ul><li><strong>Looming competition from tech giants</strong>: Twitter launched Spaces last month and Facebook is reportedly working on a similar product</li><li>The app’s reputation for <strong>lax moderation has drawn scrutiny</strong> from all sides: Extremists and dissidents have found a home for free-flowing conversations on the app</li><li><strong>Data and privacy concerns</strong>: Issues with aggressive data extraction, audio and metadata being pulled to third-party sites without consent, data allegedly being routed through servers in China</li><li>Co-founder Paul Davidson recently stated that an Android version is a “top feature”, hinting that <strong>an Android app is currently in the works</strong></li></ul><h3><strong>The Role of Big Tech in the 2021 Myanmar Coup</strong></h3><p><strong>Should Big Tech do more to prevent extreme events like this from occurring?</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/770/1*-OVRUZog7U6apF2oOgSNEQ.jpeg" /><figcaption>Barricades have been put up on some streets in Yangon to prevent the passage of security forces. | <a href="https://asia.nikkei.com/Spotlight/Myanmar-Coup/Myanmar-coup-latest-Buddhist-group-breaks-with-authorities">Nikkei</a></figcaption></figure><p>Facebook said it banned all remaining accounts linked to the Myanmar military<strong> </strong>on Thursday, citing the junta’s use of deadly force against anti-coup demonstrators.</p><p><strong>The platform admitted that it failed to do enough</strong> to prevent the incitement of violence in Myanmar back in 2018, a year after a military-backed crackdown forced 750,000 Rohingya Muslims to flee the country.</p><p><strong>The junta has imposed nightly internet blackouts and banned social media platforms</strong>, including Facebook, to bring the protests to a heel.</p><p>Follow-up events:</p><ul><li>A UN report in 2018 had found Facebook to be “slow and ineffective” in tackling hate speech</li><li>Facebook had then also acknowledged that many in Myanmar relied on the platform for information, “more so than in almost any other country”</li><li>Critics have observed that Trump was swiftly kicked off Facebook for inciting violence and an attempted coup, while the Burmese military was allowed to stay on the platform for almost a month after the coup had occurred</li></ul><h3><strong>Microsoft to Establish First Datacenter Region in Indonesia</strong></h3><p><strong>Big news for the country that is lagging behind in tech infrastructure.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/1*HyUg9P3qXzJjO8Q_m3qpgA.jpeg" /></figure><p>Microsoft has announced the establishment of its first data centre region in Indonesia, as part of its Berdayakan Ekonomi Digital Indonesia initiative.</p><p>The details of when and where the datacenter will be built remain hazy, but what is clear is that <strong>Indonesia will join the world’s largest cloud infrastructure </strong>(Azure) with over 60 datacenter regions announced to date.</p><p>Follow-up events:</p><ul><li>The initiative is hailed as the company’s commitment to advancing growth and digital transformation for Indonesia, its developer and startup ecosystem, enterprises, and the public sector</li><li>Microsoft believes its investments will generate up to <strong>$6.3 billion in revenue</strong> for the country and contribute around <strong>60,000 jobs</strong> to the local economy</li><li>The company will work with government and industry stakeholders to skill an additional 3 million people, bringing the total to <strong>24 million Indonesians skilled by the end of 2021</strong></li><li>Will we finally see much-needed digital improvements to Indonesia’s lagging critical industries, such as agriculture?</li></ul><p>And that’s a wrap on our February newsletter! We hope this month’s news bites were as interesting to you as they were to us.</p><p><strong><em>Follow Zero One Group on </em></strong><a href="http://instagram.com/zero_one_group.com"><strong><em>Instagram</em></strong></a><strong><em>, </em></strong><a href="https://twitter.com/zero_one_group"><strong><em>Twitter</em></strong></a><strong><em>, </em></strong><a href="https://www.facebook.com/01.zeroonegroup/"><strong><em>Facebook</em></strong></a><strong><em>, and </em></strong><a href="https://www.linkedin.com/organization-guest/company/zeroonegroup"><strong><em>LinkedIn</em></strong></a><strong><em>. Visit our website at </em></strong><a href="http://www.zero-one-group.com/"><strong><em>www.zero-one-group.com</em></strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=579586798ced" width="1" height="1" alt=""><hr><p><a href="https://blog.zero-one-group.com/zero-one-group-newsletter-7-579586798ced">Zero One Group Newsletter #7</a> was originally published in <a href="https://blog.zero-one-group.com/">Zero One Group</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Zero One Group Newsletter #6]]></title>
            <link>https://blog.zero-one-group.com/zero-one-group-newsletter-6-5a8da6a05d?source=rss-bd9b245f3b89------2</link>
            <guid isPermaLink="false">https://medium.com/p/5a8da6a05d</guid>
            <category><![CDATA[news-articles]]></category>
            <category><![CDATA[news]]></category>
            <category><![CDATA[technews]]></category>
            <category><![CDATA[technology-news]]></category>
            <category><![CDATA[newsletter]]></category>
            <dc:creator><![CDATA[Zero One Group]]></dc:creator>
            <pubDate>Wed, 17 Feb 2021 07:50:55 GMT</pubDate>
            <atom:updated>2021-02-17T07:50:55.175Z</atom:updated>
            <content:encoded><![CDATA[<p>By Joanna N., Business Development Associate at Zero One Group</p><p>January was a wild month in the news sphere, with everything from pandemic to politics making wacky headlines at the start of the year (did any of you have Viking Man storming the Capitol on your 2021 bingo card? No? Me neither).</p><p>On that note, here are three topics we think deserve your attention and discussion at your next (virtual) water cooler chat.</p><h3><strong>Redditors take on Wall Street</strong></h3><p><strong>Sending $GME to the moon.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/890/0*nVnwDtVJliKYEliO" /><figcaption>Diamond hands hold the share price of GameStop high. | <a href="https://www.theguardian.com/business/2021/jan/28/gamestop-how-reddits-amateurs-tripped-wall-streets-short-sellers">The Guardian</a></figcaption></figure><p>A recent trading frenzy has sent the share price of GameStop ($GME) to astronomical levels, reaching a peak of $483 per share. $GME’s 52-week low stands at $2.57 per share.</p><p>Redditors of r/WallStreetBets saw that large investors had bet billions that GameStop’s stock would fall. <strong>These Redditors then decided to penalise Wall Street by banding together to drive the price up.</strong></p><p>As the actions of these retail investors went viral, $GME rapidly rose in price, forcing the large investors to spend billions of dollars to cover their losses. One hedge fund sustained a 53% loss in assets within the last month.</p><p>Follow-up events:</p><ul><li>Robinhood banned the trade of so-called “meme stocks”, citing market volatility and risk — the ensuing backlash could negatively impact their planned IPO</li><li>Calls to investigate all sides have been made, especially in regards to allegations of market manipulation</li><li>The future of Reddit traders, Wall Street, and intermediary platforms remain uncertain</li></ul><h3><strong>What is going on with WhatsApp?</strong></h3><p><strong>Privacy concerns — as usual.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/920/0*slDR52k_cA_F2ESL" /><figcaption>WhatsApp faces another slew of criticism for its actions. | <a href="https://www.theverge.com/2021/1/12/22226792/whatsapp-privacy-policy-response-signal-telegram-controversy-clarification">The Verge</a></figcaption></figure><p>WhatsApp has been in hot water recently over its <a href="https://www.whatsapp.com/legal/updates/privacy-policy">updated privacy policy</a>.</p><p>The core issue lies with users’ concerns that the updated policy will mandate the sharing of sensitive profile information with Facebook, WhatsApp’s parent company.</p><p>Users are required to “agree” to share data with Facebook by February 8 — or lose access to their accounts.</p><p><strong>Turns out the update has nothing to do with consumer chats or profile data</strong>. It has to do with messaging business profiles on the platform.</p><p>Follow-up events:</p><ul><li>Massive fallout, partly thanks to Facebook’s poor track record on privacy and opaque dealings with terms of service agreements</li><li>Users fleeing to alternative platforms, namely Telegram and Signal</li><li>How will Facebook and WhatsApp build trust back and navigate transparency in the aftermath?</li></ul><h3><strong>The Disappearance of Jack Ma</strong></h3><p><strong>And the mysterious circumstances surrounding his comeback.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/862/0*Y9a6Xkk-ut2So5nd" /><figcaption>Experts say the case of Jack Ma is significant both commercially and politically. | <a href="https://www.abc.net.au/news/2021-01-29/china-jack-ma-reappeared-amid-alibaba-ant-group-investigation/13098016">ABC News</a></figcaption></figure><p>Jack Ma had resurfaced in mid-January after rumours of him going missing first broke at the start of the year.</p><p>After nearly three months in which his whereabouts were unknown, Ma appeared in a 48-second clip — of which many likened to a “hostage video”.</p><p>Many have speculated that he decided to lay low after he had publicly criticised the Communist Party and spoke out against regulators, who he perceived to be “stifling innovation”.</p><p><strong>Ma’s speech went viral on social media for being the antithesis of the regime’s rhetoric.</strong></p><p>Follow-up events:</p><ul><li>The IPO of Ant Group, an online finance company spun out of Alibaba, was cancelled two weeks after Ma’s speech was made</li><li>Ma’s current whereabouts, after his brief video appearance, remain unknown</li><li>This event sets up a precedent for individuals and businesses who are looking to expand, or are already present in, China</li></ul><p>That wraps it up for January’s news recap! Keep the discussion going and tune in next month to see our summary of February’s buzzing topics.</p><p><strong><em>Follow Zero One Group on </em></strong><a href="http://instagram.com/zero_one_group.com"><strong><em>Instagram</em></strong></a><strong><em>, </em></strong><a href="https://twitter.com/zero_one_group"><strong><em>Twitter</em></strong></a><strong><em>, </em></strong><a href="https://www.facebook.com/01.zeroonegroup/"><strong><em>Facebook</em></strong></a><strong><em>, and </em></strong><a href="https://www.linkedin.com/organization-guest/company/zeroonegroup"><strong><em>LinkedIn</em></strong></a><strong><em>. Visit our website at </em></strong><a href="http://www.zero-one-group.com/"><strong><em>www.zero-one-group.com</em></strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5a8da6a05d" width="1" height="1" alt=""><hr><p><a href="https://blog.zero-one-group.com/zero-one-group-newsletter-6-5a8da6a05d">Zero One Group Newsletter #6</a> was originally published in <a href="https://blog.zero-one-group.com/">Zero One Group</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Brand-First Approach to Digital Marketing]]></title>
            <link>https://blog.zero-one-group.com/brand-first-approach-to-digital-marketing-c32a2c146f58?source=rss-bd9b245f3b89------2</link>
            <guid isPermaLink="false">https://medium.com/p/c32a2c146f58</guid>
            <category><![CDATA[branding]]></category>
            <category><![CDATA[branding-identity]]></category>
            <category><![CDATA[blog]]></category>
            <category><![CDATA[digital-marketing]]></category>
            <category><![CDATA[marketing]]></category>
            <dc:creator><![CDATA[Zero One Group]]></dc:creator>
            <pubDate>Wed, 27 Jan 2021 07:54:37 GMT</pubDate>
            <atom:updated>2021-01-27T07:54:37.136Z</atom:updated>
            <content:encoded><![CDATA[<h3>A Brand-First Approach to Digital Marketing</h3><p><em>By </em><a href="http://linkedin.com/in/swedianlie"><em>Swedian Lie</em></a><em>, Co-Founder of Zero One Digital</em></p><p>Here at Zero One Digital, we often think of branding as a <strong>mindset</strong>. <em>How do we see the challenges that companies face as an opportunity to build, develop, and elevate their brand?</em></p><p>We believe in an integrated and holistic approach to digital marketing centered around the concept of a <strong>brand DNA</strong>. Our work focuses on <strong>building</strong> the foundations of a strong brand story or narrative, <strong>developing</strong> each element of the narrative into meaningful campaigns, and <strong>elevating</strong> every touchpoint of the brand — from offline to online, retail to culture — into a unique and unforgettable experience for your target audience. Let us share with you our brand-first approach to digital marketing.</p><h4><strong>The Foundation of a Strong Brand is a Strong Story</strong></h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GenGq7HcN8W59y4UICjHUg.jpeg" /></figure><p>When we talk about a strong brand story, what we’re <em>really</em> talking about is a brand <strong><em>narrative</em></strong>. What’s the difference between story and narrative? A story can start from anywhere and it doesn’t have to go anywhere — think of all the hours you’ve spent listening to your drunk best friend’s “stories” — but a narrative is designed with a clear strong origin to start. When done right, <strong>a strong brand narrative is the roadmap to your brand’s journey towards success. </strong>It becomes the compass you and your team use as guidance in making important decisions for your company’s future.</p><p>A strong brand narrative will not only work for you, but also your target audience. In today’s noisy digital landscape, you need to tell your brand narrative as efficiently and effectively as possible in order to make an impact. This is when a strong <strong>brand identity comes into play — bringing your brand narrative to life.</strong> Every part of the identity, be it logos, tone of voice, packaging, interior design, and so forth, will inject creativity and imagination to your narrative and give it the personality it needs to tell your story to your audience. That said, a brand identity should never come before a brand narrative. Even the greatest actor in the world cannot play a role that hasn’t been written yet.</p><h4>Telling the Brand Narrative Through Unique and Engaging Campaigns</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9rtvAXs6zDkZonlFXiorFQ.jpeg" /></figure><p>Speaking of playing a role — a brand narrative usually exists as a standalone statement, a manifesto that drives the vision and mission of your company. However, no company exists in a silo, without an audience it needs to speak to (also known as “clients”). At some point, the brand needs to start speaking for itself and connecting with its audience in unique and engaging ways. In digital marketing, we call these moments <strong>campaigns</strong>, and we plan them out with a very clear and strategic mindset, informed by your brand narrative. <em>How do we flesh out the brand and create meaningful relationships with its audience?</em></p><p>Every marketing class talks about reaching audiences in the shape of a funnel, but at Zero One Digital, we prefer to think about audience engagement in terms of concentric circles and <strong>relationship building — how do we develop deeper layers of engagement that will produce meaningful results?</strong> Just like real relationships, every segment of your audience will require a unique and tailored way of communicating with them, and we customise our campaigns in order to develop not only memorable but meaningful marketing moments. When guided by a strong brand narrative and identity, the actor can play their role and speak to every audience member in the room as if they’re the only person the actor’s talking to.</p><h4><strong>Elevating the Brand at Every Touchpoint</strong></h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sl-RfKXSi79ASHMV_CYJxw.jpeg" /></figure><p>After establishing your brand narrative and identity, and developing engaging marketing campaigns to deepen your relationships with your audience, you might think the marketing effort is done — but <em>we</em> don’t. With our branding-as-a-mindset approach, we’re always thinking about the future and how we can elevate your brand for greater success. Informed by our diverse technology and consulting ecosystem within Zero One Group, we understand the value of <strong>brand equity</strong> and how to increase it by <strong>improving and strengthening every part of the brand experience through both offline and online touchpoints.</strong></p><p>We observe and analyse your audience’s journey and identify all the unique experiential touchpoints that can be brought to life, using your brand narrative and identity as the DNA. Whether that’s through an interactive website, an app, an offline brand activation event, or a video ad, all of these products are <strong>an extension of your brand narrative</strong>. Investing in improving them and elevating your brand touchpoints is how you can invest in your brand’s future and make sure it’s built to last.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jJVTwd_G9yEXPEDCBV5SbA.jpeg" /></figure><p>Most digital agencies don’t see digital marketing in this brand-first way. Their work is driven by and based on easy-to-understand numbers and metrics, such as impressions, likes, views, clicks — the list goes on and on. This data is still important, but at Zero One Digital, we think they’re missing the big picture if that’s the <em>only</em> thing they’re thinking about.</p><p>We’re always looking at the big picture — the story of your company or business, the unique values, vision, and mission that drives you forward, and the legacy you wish to leave behind with your work. We consider all of this as part of defining your brand DNA, and our job is to help guide and support you in bringing your story to life.</p><p>Want to learn more about our unique branding and marketing approach? Drop us an email at <a href="/service/mailto:digital@zero-one-group.com">digital@zero-one-group.com</a> or find us on Instagram at @01.zeroonedigital.</p><p><strong><em>Follow Zero One Group at </em></strong><a href="http://instagram.com/zero_one_group.com"><strong><em>Instagram</em></strong></a><strong><em>, </em></strong><a href="https://twitter.com/zero_one_group"><strong><em>Twitter</em></strong></a><strong><em>, </em></strong><a href="https://www.facebook.com/01.zeroonegroup/"><strong><em>Facebook</em></strong></a><strong><em>, and </em></strong><a href="https://www.linkedin.com/organization-guest/company/zeroonegroup"><strong><em>LinkedIn</em></strong></a><strong><em>. Visit our website at </em></strong><a href="http://www.zero-one-group.com/"><strong><em>www.zero-one-group.com</em></strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c32a2c146f58" width="1" height="1" alt=""><hr><p><a href="https://blog.zero-one-group.com/brand-first-approach-to-digital-marketing-c32a2c146f58">Brand-First Approach to Digital Marketing</a> was originally published in <a href="https://blog.zero-one-group.com/">Zero One Group</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>