<?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 Lucas Goldner on Medium]]></title>
        <description><![CDATA[Stories by Lucas Goldner on Medium]]></description>
        <link>https://medium.com/@lucas.goldner?source=rss-8a635e5c004------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*vyTkmWCxCW6azLoUeZvukA.png</url>
            <title>Stories by Lucas Goldner on Medium</title>
            <link>https://medium.com/@lucas.goldner?source=rss-8a635e5c004------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 17 May 2026 10:12:45 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@lucas.goldner/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[Flutter Element Embedding — Unleashing the Power of Integrating Flutter Apps into Websites…]]></title>
            <link>https://medium.com/@lucas.goldner/flutter-element-embedding-unleashing-the-power-of-integrating-flutter-apps-into-websites-e91c84c13f2d?source=rss-8a635e5c004------2</link>
            <guid isPermaLink="false">https://medium.com/p/e91c84c13f2d</guid>
            <category><![CDATA[flutter-web]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[dart]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Lucas Goldner]]></dc:creator>
            <pubDate>Tue, 23 Apr 2024 22:41:36 GMT</pubDate>
            <atom:updated>2024-04-23T22:41:36.058Z</atom:updated>
            <content:encoded><![CDATA[<h3>Flutter Element Embedding — Unleashing the Power of Integrating Flutter Apps into Websites, including React-powered ones!</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-oLzuuI9rN3B_IYIEfOmng.jpeg" /></figure><p>When I first learned about Element Embedding at FlutterForward 2023, its potential immediately captivated me.</p><p>Imagine showcasing a vertical slice of your app directly on your homepage, allowing users to interact with it and truly experience its functionality. But that’s just the start. You can also embed multiple smaller apps within your documentation to demonstrate their behavior in real-time</p><p>Capabilities of Flutter Element Embedding:</p><ul><li>Embedd flutter web-compatible apps into any website</li><li>Using JS Interop, it is possible to share the state of the app and the website and modify it from each other</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vRR2nB9UiajNaUwEgoi0yQ.png" /><figcaption>The actual Flutter app is rendered on the home page of the webpage. <a href="https://flutter-show-docs.vercel.app/">https://flutter-show-docs.vercel.app/</a></figcaption></figure><h3>How Can You Implement Flutter Element Embedding?</h3><p>Achieving this is relatively straightforward. First, I’ll demonstrate how to embed Flutter elements on a simple HTML website for demonstration purposes. If you’re interested in viewing the entire source code, you can refer to the repository provided below:</p><p><a href="https://github.com/lucas-goldner/Element-Embedding-Presentation/tree/Flutterconnection-2024/example_website/red_counter_homepage">Element-Embedding-Presentation/example_website/red_counter_homepage at Flutterconnection-2024 · lucas-goldner/Element-Embedding-Presentation</a></p><p>But we will be starting from scratch:</p><pre>&lt;!DOCTYPE html&gt;<br>&lt;html lang=&quot;en&quot;&gt;<br>  &lt;head&gt;<br>    &lt;meta charset=&quot;UTF-8&quot; /&gt;<br>    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;<br>    &lt;title&gt;Embedded Flutter Website&lt;/title&gt;<br>    &lt;link rel=&quot;stylesheet&quot; href=&quot;./styles.css&quot; /&gt;<br>  &lt;/head&gt;<br>  &lt;body&gt;<br>    &lt;header&gt;<br>      &lt;h1&gt;See the Flutter app below!&lt;/h1&gt;<br>    &lt;/header&gt;<br>    &lt;div&gt;<br>      &lt;main&gt;<br>        &lt;section&gt;<br>          &lt;div id=&quot;flutter_host&quot; style=&quot;height: 812px; width: 375px&quot;&gt;<br>            Loading...<br>          &lt;/div&gt;<br>        &lt;/section&gt;<br>      &lt;/main&gt;<br>    &lt;/div&gt;<br>  &lt;/body&gt;<br>&lt;/html&gt;</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*EO7AR9aIwnPVbfrChT9EyQ.png" /><figcaption>Starting page</figcaption></figure><p>1. We need a web build of our Flutter app. So, let us run the build command:</p><pre>$ flutter build web</pre><p>2. Once complete, you must add the following two scripts to your website. Both scripts can be found in the build directory of your Flutter web app. When properly configured, flutter.js manages the loading of the web app and Flutter&#39;s service worker.</p><pre>&lt;script src=&quot;./your_built_flutter_app/flutter.js&quot; defer&gt;&lt;/script&gt;</pre><p>This snippet, which loads the Flutter app by reading main.dart.js, is also essential. There are numerous parameters available to customize and configure the engine initialization. For more detailed information on these parameters, please visit <a href="https://docs.flutter.dev/platform-integration/web/initialization">Flutter Web Initialization Documentation</a>.</p><p>The most crucial parameters to consider are the assets and the hostElement, as these dictate where the Flutter app will be embedded on the website.</p><pre>    &lt;script&gt;<br>      window.addEventListener(&quot;load&quot;, function (ev) {<br>        const basePath = &quot;./your_built_flutter_app/&quot;;<br><br>        _flutter.loader.loadEntrypoint({<br>          entrypointUrl: basePath + &quot;main.dart.js&quot;,<br>          onEntrypointLoaded: async function (engineInitializer) {<br>            let appRunner = await engineInitializer.initializeEngine({<br>              assetBase: basePath,<br>              hostElement: document.querySelector(&quot;#flutter_host&quot;),<br>            });<br>            await appRunner.runApp();<br>          },<br>        });<br>      });<br>    &lt;/script&gt;</pre><p>Adding both of those results to this updated website:</p><pre>&lt;!DOCTYPE html&gt;<br>&lt;html lang=&quot;en&quot;&gt;<br>  &lt;head&gt;<br>    &lt;meta charset=&quot;UTF-8&quot; /&gt;<br>    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;<br>    &lt;title&gt;Embedded Flutter Website&lt;/title&gt;<br>    &lt;link rel=&quot;stylesheet&quot; href=&quot;./styles.css&quot; /&gt;<br>    &lt;script src=&quot;./flutter_app/flutter.js&quot; defer&gt;&lt;/script&gt;<br>    &lt;script&gt;<br>      window.addEventListener(&quot;load&quot;, function (ev) {<br>        const basePath = &quot;./flutter_app/&quot;;<br><br>        _flutter.loader.loadEntrypoint({<br>          entrypointUrl: basePath + &quot;main.dart.js&quot;,<br>          onEntrypointLoaded: async function (engineInitializer) {<br>            let appRunner = await engineInitializer.initializeEngine({<br>              assetBase: basePath,<br>              hostElement: document.querySelector(&quot;#flutter_host&quot;),<br>            });<br>            await appRunner.runApp();<br>          },<br>        });<br>      });<br>    &lt;/script&gt;<br>  &lt;/head&gt;<br>  &lt;body&gt;<br>    &lt;header&gt;<br>      &lt;h1&gt;See the Flutter app below!&lt;/h1&gt;<br>    &lt;/header&gt;<br>    &lt;div&gt;<br>      &lt;main&gt;<br>        &lt;section&gt;<br>          &lt;div id=&quot;flutter_host&quot; style=&quot;height: 812px; width: 375px&quot;&gt;<br>            Loading...<br>          &lt;/div&gt;<br>        &lt;/section&gt;<br>      &lt;/main&gt;<br>    &lt;/div&gt;<br>  &lt;/body&gt;<br>&lt;/html&gt;</pre><p><strong>And that is it 🎇! Enjoy the result below:</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hXERG11KKJGWC_hR4iphOA.gif" /></figure><h3>But I use React. How can I integrate it there?</h3><p>I encountered some issues when trying to apply the steps I had learned. Fortunately, I managed to figure it out with the help of a <a href="https://github.com/flutter/flutter/issues/123940">user’s guide</a>. I will explain the process in the following step</p><p>1. Run this command in your Flutter app to create a web version:</p><pre>$ flutter build web --profile --dart-define=Dart2jsOptimization=O0</pre><p>This command will not generate a minified JavaScript version because some adjustments need to be made in the build output. As a result, the client will have to download a larger bundle.</p><p>2. Copy the web folder from /build/web/ to the public folder in your React app. In this project, I have renamed the folder to Flutter. All our Flutter files are now hosted at YOUR_HOST/flutter/.</p><p>Navigate to public/flutter/main.dart.js. In the next step, replace the t1 path with your folder name.</p><pre>// what you will need to find<br>    getAssetUrl$1(asset) {<br>      var t1, fallbackBaseUrl, t2;<br>      if (A.Uri_parse(asset).get$hasScheme())<br>        return A._Uri__uriEncode(B.List_5Q7, asset, B.C_Utf8Codec, false);<br>      t1 = this._assetBase;<br>    }<br><br>// replaced<br>    getAssetUrl$1(asset) {<br>      var t1;<br>      if (A.Uri_parse(asset, 0, null).get$hasScheme())<br>        return A._Uri__uriEncode(B.List_5Q7, asset, B.C_Utf8Codec, false);<br>      t1 = &quot;/flutter/&quot;;<br>    }</pre><p>3. Edit flutter.js</p><pre>// Search for this<br>function getBaseURI() {<br>  const base = document.querySelector(&quot;base&quot;);<br>  return (base &amp;&amp; base.getAttribute(&quot;href&quot;)) || &quot;&quot;;<br>}<br><br>// Use the same path as before<br>function getBaseURI() {<br>  return &quot;/flutter/&quot;;<br>}</pre><p>4. Create a flutter_init.js file inside your public folder of the react app and paste the following content into it:</p><pre>window._stateSet = function () {};<br>window.addEventListener(&quot;load&quot;, function (ev) {<br>  let target = document.querySelector(&quot;#flutter_target&quot;);<br>  _flutter.loader.loadEntrypoint({<br>    onEntrypointLoaded: async function (engineInitializer) {<br>      let appRunner = await engineInitializer.initializeEngine({<br>        hostElement: target,<br>      });<br>      await appRunner.runApp();<br>    },<br>  });<br>});</pre><p>5. Install react-helmet-async so we can run our flutter_init script</p><pre>$ yarn add react-helmet-async</pre><p>6. The setup is done now. You need to wrap your React App with a HelmetProvider and provide a helmetContext (can be empty).</p><pre>import React from &#39;react&#39;<br>import ReactDOM from &#39;react-dom/client&#39;<br>import App from &#39;./App&#39;<br>import { HelmetProvider } from &quot;react-helmet-async&quot;<br>import &#39;./index.css&#39;<br><br>const helmetContext = {};<br><br>ReactDOM.createRoot(document.getElementById(&#39;root&#39;) as HTMLElement).render(<br>    &lt;React.StrictMode&gt;<br>        &lt;HelmetProvider context={helmetContext}&gt;<br>            &lt;App /&gt;<br>        &lt;/HelmetProvider&gt;<br>    &lt;/React.StrictMode&gt;,<br>)</pre><p>7. Now that that is resolved, add a Helmet component and our flutter_init.js + flutter.js. This will load the Flutter app, and that was it!</p><pre>import { Helmet } from &quot;react-helmet-async&quot;;<br><br>function App() {<br>  return (<br>    &lt;&gt;<br>      &lt;Helmet&gt;<br>        &lt;script src=&quot;/flutter/flutter.js&quot; defer&gt;&lt;/script&gt;<br>        &lt;script src=&quot;/flutter_init.js&quot; defer&gt;&lt;/script&gt;<br>      &lt;/Helmet&gt;<br>      &lt;div<br>        style={{ aspectRatio: 9 / 19.5 }}<br>        id=&quot;flutter_target&quot;<br>        className=&quot;h-full&quot;<br>      &gt;&lt;/div&gt;<br>    &lt;/&gt;<br>  );<br>}</pre><p>That was it! Now, your Flutter app should be displayed in React as well!</p><p>—</p><p>The process can be cumbersome, so I also wrote a small script to simplify it, as some steps need to be repeated with each build. Feel free to copy and adjust this script for your purposes.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b5ed27a36a060caff8f25065235ee528/href">https://medium.com/media/b5ed27a36a060caff8f25065235ee528/href</a></iframe><h3>Now, let’s make the interaction between the website and the app more dynamic by allowing them to manipulate each other</h3><p>The next goal is to enhance the website by adding elements that can read and display the app&#39;s state. In our example, I&#39;ve added a text field designed to show the current number from the app and an &quot;Increase&quot; button to modify this number. Here’s a reference to how it looks:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Abr_Yh2Ur8Go-_fgVHVXxw.png" /></figure><p>To implement this interaction, it is essential to facilitate communication with JavaScript. This can be achieved using JavaScript Interoperability (Js Interop), which allows the Flutter app and the website to interact seamlessly.</p><p>1. First, add the js package</p><pre>$ flutter build web</pre><p>2. This step will vary depending on your app and its specific requirements. For instance, within your Flutter app, you should export all functions and states that you want to be accessible via JavaScript. Here is an example of how you might configure this:</p><p><a href="https://github.com/lucas-goldner/Element-Embedding-Presentation/blob/Flutterconnection-2024/example_website/red_counter_app/lib/main.dart">Element-Embedding-Presentation/example_website/red_counter_app/lib/main.dart at Flutterconnection-2024 · lucas-goldner/Element-Embedding-Presentation</a></p><p>In this scenario, we use the @js.JSExport() annotation for the state, which needs to be assigned using the js_util library&#39;s setProperty function. This setup maps the state to a string, making it accessible from the JavaScript side. Additionally, the callMethod function allows you to invoke JavaScript functions from Flutter. It also supports passing additional values in its array, providing further flexibility for interaction between the Flutter app and the website.</p><pre>@js.JSExport()<br>class _MyHomePageState extends State&lt;MyHomePage&gt; {<br>  final _streamController = StreamController&lt;void&gt;.broadcast();<br>  int _counterScreenCount = 0;<br><br>  @override<br>  void initState() {<br>    super.initState();<br>    final export = js_util.createDartExport(this);<br>    js_util.setProperty(js_util.globalThis, &#39;_appState&#39;, export);<br>    js_util.callMethod&lt;void&gt;(js_util.globalThis, &#39;_stateSet&#39;, []);<br>  }<br>....<br>}</pre><p>For any function or variable you want to make accessible from JavaScript, you need to mark it with the same decorator, like so:</p><pre>  @js.JSExport()<br>  void addHandler(void Function() handler) {<br>    _streamController.stream.listen((event) {<br>      handler();<br>    });<br>  }<br><br>  @js.JSExport()<br>  int get count =&gt; _counterScreenCount;</pre><p>The reason for using a stream controller in a straightforward app like Flutter is to facilitate sending “updates” to the website’s text field, which we plan to add. This method ensures that any changes in the app can be dynamically reflected on the website, enhancing interactivity and user experience.</p><p>3. Now that everything is configured on the Dart side, it’s time to move forward. Next, we’ll bind our exported functions and states to variables. To keep the logic organized, I’ve created a new main.js file where I manage these assignments:</p><pre>// Sets up a channel to JS-interop with Flutter<br>(function () {<br>  &quot;use strict&quot;;<br>  // This function will be called from Flutter when it prepares the JS-interop.<br>  window._stateSet = function () {<br>    window._stateSet = function () {<br>      console.log(&quot;Calls _stateSet once!&quot;);<br>    };<br><br>    // The state of the flutter app, see `class _MyAppState` in lib/main.dart.<br>    let appState = window._appState;<br><br>    let valueField = document.querySelector(&quot;#value&quot;);<br>    let updateState = function () {<br>      valueField.value = appState.count;<br>    };<br><br>    // Register a callback to update the HTML field from Flutter.<br>    appState.addHandler(updateState);<br><br>    // Render the first value (0).<br>    updateState();<br><br>    let incrementButton = document.querySelector(&quot;#increase-btn&quot;);<br>    incrementButton.addEventListener(&quot;click&quot;, (event) =&gt; {<br>      appState.increment();<br>    });<br>  };<br>})();</pre><p>And in our index.html, I load with this script:</p><pre>&lt;script src=&quot;./main.js&quot; defer&gt;&lt;/script&gt;</pre><p>So, the final result of our code becomes:</p><pre>&lt;!DOCTYPE html&gt;<br>&lt;html lang=&quot;en&quot;&gt;<br>  &lt;head&gt;<br>    &lt;meta charset=&quot;UTF-8&quot; /&gt;<br>    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;<br>    &lt;title&gt;Interactive Red Counter - Revolutionary Counting App&lt;/title&gt;<br>    &lt;link rel=&quot;stylesheet&quot; href=&quot;./styles.css&quot; /&gt;<br>    &lt;script src=&quot;./flutter_app/flutter.js&quot; defer&gt;&lt;/script&gt;<br>    &lt;script src=&quot;./main.js&quot; defer&gt;&lt;/script&gt;<br><br>    &lt;script&gt;<br>      window.addEventListener(&quot;load&quot;, function (ev) {<br>        const basePath = &quot;./flutter_app/&quot;;<br><br>        _flutter.loader.loadEntrypoint({<br>          entrypointUrl: basePath + &quot;main.dart.js&quot;,<br>          onEntrypointLoaded: async function (engineInitializer) {<br>            let appRunner = await engineInitializer.initializeEngine({<br>              assetBase: basePath,<br>              hostElement: document.querySelector(&quot;#flutter_host&quot;),<br>            });<br>            await appRunner.runApp();<br>          },<br>        });<br>      });<br>    &lt;/script&gt;<br>  &lt;/head&gt;<br>  &lt;body&gt;<br>    &lt;header&gt;<br>      &lt;h1&gt;See the Flutter app below!&lt;/h1&gt;<br>    &lt;/header&gt;<br>    &lt;div class=&quot;main-content&quot;&gt;<br>      &lt;main&gt;<br>        &lt;section class=&quot;interactive-iphone-display&quot;&gt;<br>          &lt;div id=&quot;flutter_host&quot; style=&quot;height: 812px; width: 375px&quot;&gt;<br>            Loading...<br>          &lt;/div&gt;<br><br>          &lt;div class=&quot;counter-controls&quot;&gt;<br>            &lt;button id=&quot;increase-btn&quot;&gt;Increase&lt;/button&gt;<br>            &lt;div class=&quot;current-number&quot;&gt;<br>              &lt;label for=&quot;current-number-field&quot;&gt;Current Number:&lt;/label&gt;<br>              &lt;input<br>                id=&quot;value&quot;<br>                type=&quot;text&quot;<br>                id=&quot;current-number-field&quot;<br>                value=&quot;0&quot;<br>              /&gt;<br>            &lt;/div&gt;<br>          &lt;/div&gt;<br>        &lt;/section&gt;<br><br>        &lt;section class=&quot;features&quot;&gt;<br>          &lt;h2&gt;Features&lt;/h2&gt;<br>          &lt;ul&gt;<br>            &lt;li&gt;Stunning Red Color Scheme&lt;/li&gt;<br>            &lt;li&gt;Intuitive and Simple Counter Interface&lt;/li&gt;<br>            &lt;li&gt;Revolutionary One-Tap Counting Technology&lt;/li&gt;<br>          &lt;/ul&gt;<br>        &lt;/section&gt;<br><br>        &lt;section class=&quot;download&quot;&gt;<br>          &lt;h2&gt;Download Now&lt;/h2&gt;<br>          &lt;p&gt;Join the counting revolution today. Available on all platforms.&lt;/p&gt;<br>        &lt;/section&gt;<br>      &lt;/main&gt;<br>      &lt;footer&gt;<br>        &lt;p&gt;&amp;copy; 2023 Red Counter. All Rights Reserved.&lt;/p&gt;<br>      &lt;/footer&gt;<br>    &lt;/div&gt;<br>  &lt;/body&gt;<br>&lt;/html&gt;</pre><p>Let us try it out🔥</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/826/1*J4ZMGFlpJh1S0vUHOl-l2g.gif" /></figure><p>Now that we have established direct communication, you can change the app’s state using the website and vice versa. This opens up a wealth of new possibilities for interaction and functionality. If you have any impressive examples or innovative uses, please share them with me on X.</p><p>The code is available here if you want to look something up:</p><p><a href="https://github.com/lucas-goldner/Element-Embedding-Presentation/tree/Flutterconnection-2024/example_website/red_counter_homepage">Element-Embedding-Presentation/example_website/red_counter_homepage at Flutterconnection-2024 · lucas-goldner/Element-Embedding-Presentation</a></p><h3>Other frameworks?</h3><ul><li>For react, refer to this example I have made: <a href="https://github.com/lucas-goldner/flutter_react_element_embedding">https://github.com/lucas-goldner/flutter_react_element_embedding</a></li><li>Angular has a fantastic example: <a href="https://github.com/flutter/samples/tree/main/web_embedding/ng-flutter">https://github.com/flutter/samples/tree/main/web_embedding/ng-flutter</a></li><li>Jaspr, the framework for creating websites in a Flutter-like way, has also support for it:<br><a href="https://docs.page/schultek/jaspr/eco/flutter_embedding">https://docs.page/schultek/jaspr/eco/flutter_embedding</a></li></ul><p>…And that was it. Please let me know if you have any questions. I am happy to help 😄</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e91c84c13f2d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How I Survived My First BIG Tech Presentation — Fluttercon 2023]]></title>
            <link>https://medium.com/@lucas.goldner/how-i-survived-my-first-big-tech-presentation-fluttercon-2023-f6c1c10f0263?source=rss-8a635e5c004------2</link>
            <guid isPermaLink="false">https://medium.com/p/f6c1c10f0263</guid>
            <category><![CDATA[talks]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[dart]]></category>
            <dc:creator><![CDATA[Lucas Goldner]]></dc:creator>
            <pubDate>Sun, 03 Sep 2023 13:28:59 GMT</pubDate>
            <atom:updated>2023-09-03T13:28:59.249Z</atom:updated>
            <content:encoded><![CDATA[<h3>How I Survived My First BIG Tech Presentation — Fluttercon 2023</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/799/0*SRoW-hXz89ds6TFj" /><figcaption>Fluttercon 2023 Banner</figcaption></figure><p>Before I start going through the emotional rollercoaster that this journey has been, it would make sense to give a bit of context about myself.</p><p>I am Lucas Goldner, 22, studying Media Informatics at HdM in Stuttgart, Germany. I have been coding for around 2–3 years and using Flutter specifically for a year. Before this event, I had never given a talk at a big conference. I have given a talk before at a local meetup in Stuttgart, but that was much smaller. So, with only one talk given and one year of Flutter experience:</p><p>You might wonder, how did I end up here?</p><h3>Application Phase</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/0*h2_APDwS8_NYcayt.png" /><figcaption>Flutter Forward Event</figcaption></figure><p>It all started at <strong>FlutterForward</strong> this year when they discussed the <a href="https://pub.dev/packages/ffigen">FFIGen</a> library. Since my talk was about FFIGen, I won’t go into full detail about FFIGen. Still, to summarize, it took the work I made a month earlier and allowed it to be done automatically 😢. It is a fantastic tool, but I was shocked to hear this was so easily possible.</p><p>Out of curiosity, I researched the topic and tried it myself. The result was that it worked, and it took me way less time to build the feature than before.</p><p>I was stunned to see that nobody was talking about this, and by that time, I had heard of the Fluttercon event. The call for speakers has already started, but I was not initially sure if I should apply there. As I have said, I have only done one small tech talk at a local meetup in Stuttgart with a much smaller audience. This event would be different since people are paying to attend this event and coming from all over the world.</p><p>I then talked to a good friend about this topic, who suggested I try applying at least. The worst case would be that I get declined, and in the best case, I would get a fantastic opportunity. So, in the end, I did that:</p><h3>Lucas Goldner 💙 on Twitter: &quot;Just finished my submission for the Fluttercon in Berlin this year. If I really get the opportunity to talk there, that would be huuuggeeee. The topic itself is interesting, and I have a nice story to follow, so it could be a fantastic talk. pic.twitter.com/PAkzuY61rs / Twitter&quot;</h3><p>Just finished my submission for the Fluttercon in Berlin this year. If I really get the opportunity to talk there, that would be huuuggeeee. The topic itself is interesting, and I have a nice story to follow, so it could be a fantastic talk. pic.twitter.com/PAkzuY61rs</p><p>Two months passed, and the event was getting closer and closer. I started forgetting about the event and focusing on work and other stuff until suddenly, on a Sunday, I received an email that made me fall out of my chair and made me write this tweet:</p><h3>Lucas Goldner 💙 on Twitter: &quot;Wait WHAT? O_O UHMMMMMM COOL ??? OK, I GUESS I AM REALLY GOING TO DO IT. Really excited for this opportunity pic.twitter.com/9YIZE7eiw8 / Twitter&quot;</h3><p>Wait WHAT? O_O UHMMMMMM COOL ??? OK, I GUESS I AM REALLY GOING TO DO IT. Really excited for this opportunity pic.twitter.com/9YIZE7eiw8</p><p>I cannot describe my feelings there, but there was excitement. So, in the weeks leading up to this event, I had to make sure I delivered a speech that people would remember (positively 😅).</p><h3>Preparation Phase</h3><p>When I received that email, I had already done my presentation, and others who had seen it also thought it would be a “good” talk. But good was not enough. During a meetup, I talked again to the same friend about the presentation. This was the night that would make my presentation fundamentally change.</p><p>I don’t remember exactly how I thought of this, but the idea was to remake the entire presentation in <strong>Flutter</strong>. I think my issue was that to demonstrate everything, I had to switch around many windows and could not show the feature I built itself, so I wanted to integrate that into my presentation. And that&#39;s where the hustle phase began:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2F1iTH1WIUjM0VATSw%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2F1iTH1WIUjM0VATSw%2Fgiphy.gif&amp;image=https%3A%2F%2Fi.giphy.com%2Fmedia%2F1iTH1WIUjM0VATSw%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="244" frameborder="0" scrolling="no"><a href="https://medium.com/media/89213780732eeaff0af7bfeec22daf30/href">https://medium.com/media/89213780732eeaff0af7bfeec22daf30/href</a></iframe><p>It took me around one month to build all slides, which is also where I hit a big problem 😟. To make it short, I wanted to get the AirPods data through the <strong>CMHeadphoneMotionManager</strong> class that Apple provides.</p><p>That works if you run it on iOS. Still, as soon as you try to run the same code on macOS, you will receive an error saying that <strong>Coremotion</strong> is only available on iOS, which means that I could not access the <strong>CMHeadphoneMotionManager</strong>. That was a big blocker for me since that would mean that everything I have done to that point would have been useless 😧.</p><h3>Lucas Goldner 💙 on Twitter: &quot;Coremotion is not available on macOS at all 😨 uhm...damn...So now I need to find another way to do this cool thing I was planning for my presentation. Really unfortunate, I don&#39;t see any reason why the framework should&#39;t be available. I guess nobody would use it but still damn.. / Twitter&quot;</h3><p>Coremotion is not available on macOS at all 😨 uhm...damn...So now I need to find another way to do this cool thing I was planning for my presentation. Really unfortunate, I don&#39;t see any reason why the framework should&#39;t be available. I guess nobody would use it but still damn..</p><p>What I tried then were the following options:</p><ul><li>Run the app as an iOS app on my Mac since the M1 chips allow me to do that and get the data from there somehow<br>-&gt; Resulted in the app just not picking up any data at all</li><li>Research ways of making a macOS app with an iOS companion app? that can communicate, but that would have made it more complex.</li></ul><p>At that point, I thought that my presentation wouldn’t be able to be as good as I imagined, but here comes my friend<em> </em>again with a great solution:</p><blockquote>“Why don’t you directly transfer the data from your phone to your Mac?” <br>(Not a direct quote)</blockquote><p><strong>That was brilliant💡!</strong></p><p>So I did precisely that. I build a separate iOS app that gets the data from the AirPods, connects to a WebSocket server, and keeps transmitting it. Since I already made the Flutter Airpods package <a href="https://pub.dev/packages/flutter_airpods">https://pub.dev/packages/flutter_airpods</a>, the implementation was quickly achievable.</p><p>Then I needed a WebSocket server, but since I had a project at university where I used WebSockets servers a lot, this also was an easy task.</p><p>So, the last thing left was the presentation to connect the server and keep processing the incoming data. Everything worked out in the end. I built the presentation precisely the way I imagined it 👌.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FxmxGoENM1V81q%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FxmxGoENM1V81q%2Fgiphy.gif&amp;image=https%3A%2F%2Fi.giphy.com%2Fmedia%2FxmxGoENM1V81q%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="326" frameborder="0" scrolling="no"><a href="https://medium.com/media/39e4d4c6c6319e12234d72d2393b2278/href">https://medium.com/media/39e4d4c6c6319e12234d72d2393b2278/href</a></iframe><p>Now, I just had to practice the talk over and over and over and over so that I did not mess that part up. I looked up some good practices for public speaking and ways of integrating the audience. On purpose, I avoided watching tech talks since I wanted to keep my style of presenting and not be influenced. One exception to that rule was the talk from <a href="https://medium.com/u/10c1e6d8c265">Pooja Bhaumik</a> at Flutter Vikings 2022:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FuVxBGzRZY-k%3Flist%3DPL4dBIh1xps-EWXK28Qn9kiLK9-eXyqKLX&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DuVxBGzRZY-k&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FuVxBGzRZY-k%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/aae602afe377a73ef8db58dce7b0b6f9/href">https://medium.com/media/aae602afe377a73ef8db58dce7b0b6f9/href</a></iframe><p>Since I followed her for some time on Twitter and wanted to see how a good tech talk is supposed to look like and I think I could not have picked a better talk. If you have not watched it, I recommend doing so, since she also showcases her Snapchat Filters live on stage. So that was kind of similar to my presentation style.</p><h3>Event time ⏲</h3><p>Wednesday, 5th of July, 12:10 at the Johnson room is where my presentation would take place.</p><p>The day before when I was practicing I ran into some issues connection my AirPods, so I was bit worried about connecting them during my presentation. I changed the presentation so that I would connect them beforehand, so that they will definitely be available and transfer the data correctly.</p><p>One thing that put <strong>a lot of pressure</strong> on me before my presentation was, that during the keynote in the morning it was mentioned that 300+ submissions were sent and 90 of those including mine was selected 😰. When I heard that I was shocked that firstly so many people applied (which is reasonable of course) and also then out all of those mine was selected?!?</p><p>From this point forward I actually have no memories, since I just presented my talk and I guess many other speakers also feel like that 😆.</p><p>Luckily <em>Raphael</em> recorded me here, so I can show those awesome clips here, which took most time developing. (Thx again 😆)</p><h3>Raphael De Lio on Twitter: &quot;@LucasGoldner showing us how he integrated AirPods with #Flutter to use its sensors to track his head and also push ups! @FlutterconEU #paneladev @sseraphini #bolhadev pic.twitter.com/mGx2IAM3tx / Twitter&quot;</h3><p>@LucasGoldner showing us how he integrated AirPods with #Flutter to use its sensors to track his head and also push ups! @FlutterconEU #paneladev @sseraphini #bolhadev pic.twitter.com/mGx2IAM3tx</p><p>As I said I have no recollection of what I said or did at the talk, but I got a lot of compliments at the end of the talk from various people and many remember me now as that “AirPods/Pushup Guy” so I think thats a good thing.</p><p>The only mistake that I did during the talk, which I noticed afterwards is that I kept my AirPods in my ears after the pushup for the rest of the presentation, but I guess nobody noticed 😆.</p><h3>What can we learn out of this?</h3><p>Rather than procrastinating like me in the beginning, just go for it! <br>I know it can be scary at first, but what do you have to lose?<br>Submitting a talk won’t hurt, you can still decline if you prefer not to do it, but if you come this far I think continuing will be totally worth it.</p><p>Thanks again a lot to my friend, that helped me a lot on this journey!</p><p>Honestly one week after all of that I cannot process that all of this happened and turned out like that. I learned a lot about myself and think that I grew a lot from this experience.</p><p>This event and talking to so many amazing people also has motivated me to further improve and I promise my next talk will be even better 💪.</p><p><strong>I hope </strong>that with this crazy story that I shared I could motivate people to also try to make a tech talk themselves. I do not have as much as experience in giving talks as other people, but if you are searching for any kind of help or want someone to give some guidance, feel free to contact me on Twitter (or X as its called now).</p><h3>Check the final result here:</h3><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fplayer.vimeo.com%2Fvideo%2F847709466%3Fapp_id%3D122963&amp;dntp=1&amp;display_name=Vimeo&amp;url=https%3A%2F%2Fplayer.vimeo.com%2Fvideo%2F847709466&amp;image=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F1701100129-66e0f6c395629b7ac0ab06310edd1f0c7d767d003bee62c84d924a6c87ef2839-d_1280&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=vimeo" width="1920" height="1080" frameborder="0" scrolling="no"><a href="https://medium.com/media/7d8f9664232e66f5e3aab5cbb0934f20/href">https://medium.com/media/7d8f9664232e66f5e3aab5cbb0934f20/href</a></iframe><p><a href="https://www.droidcon.com/2023/08/07/comparing-ways-of-accessing-native-functionality/">Comparing ways of accessing native functionality</a></p><p>And here the source code: <br><a href="https://github.com/lucas-goldner/fluttercon_2023_presentation">https://github.com/lucas-goldner/fluttercon_2023_presentation</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f6c1c10f0263" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Presentations made easy in Flutter — FlutterShow⚡]]></title>
            <link>https://medium.com/@lucas.goldner/presentations-made-easy-in-flutter-fluttershow-79ab316253b5?source=rss-8a635e5c004------2</link>
            <guid isPermaLink="false">https://medium.com/p/79ab316253b5</guid>
            <category><![CDATA[public-speaking]]></category>
            <category><![CDATA[dart]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[presentations]]></category>
            <dc:creator><![CDATA[Lucas Goldner]]></dc:creator>
            <pubDate>Sun, 30 Jul 2023 16:57:16 GMT</pubDate>
            <atom:updated>2023-07-30T16:57:16.044Z</atom:updated>
            <content:encoded><![CDATA[<h3>Presentations made easy in Flutter -FlutterShow⚡</h3><h3>Introduction</h3><p>Flutter is known for being a fantastic framework for cross-platform apps. Over the last few years, a prominent community has formed around it, leading to many events where passionate people deliver talks on their favorite framework. Now imagine this for a second, what if the presentations about <strong>Flutter</strong> were also made in <strong>Flutter</strong>?</p><p><strong>How I came up with this idea: </strong>This year at <a href="https://fluttercon.dev/">Fluttercon 2023</a>, I gave my first talk at a big conference, so I wanted to give it my best and make the presentation<strong> </strong>memorable. During a practice run, I thought about how annoying it was to switch between windows and how cool it would be to present my implemented feature directly on stage to make it more engaging to watch. This led me to create the presentation in Flutter on my MacBook to access the native APIs now from inside the presentation and display it. (If you are intrigued, <a href="https://twitter.com/raphaeldelio/status/1676536391797207040?s=46&amp;t=OAbBsZDKzkzBBmZOn9iZig">here</a> is the result)</p><p>Indeed, I am not the first person to come up with this idea, as there have been some solutions and speakers before that had the same idea, but I could not find any preexisting solution by googling, so I did it myself. This led to the creation of <strong>FlutterShow</strong>⚡. It is a framework I created from the finished presentation while making it easier to work with for other speakers.</p><p><a href="https://github.com/lucas-goldner/FlutterShow/blob/main/docs/images/fluttershow.png">FlutterShow/docs/images/fluttershow.png at main · lucas-goldner/FlutterShow</a></p><h3>Creating the presentation</h3><ul><li>Clone/fork the repo and run the steps detailed in the <strong>Project Setup</strong> section.</li><li>Now run your presentation, and you should see the following:</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jn9xbTH3ogRj17Eu2shebQ.png" /><figcaption>A clean-looking title slide 😎</figcaption></figure><p>Now that we are ready to go, let’s create our first slide in only <strong>two</strong> steps:</p><ol><li>Make a new folder in the <em>slides</em> directory and create a new widget:</li></ol><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/839eb6a8867626d58cb48f922c50f41a/href">https://medium.com/media/839eb6a8867626d58cb48f922c50f41a/href</a></iframe><p>2. Now navigate to <em>lib/presentation/config/pages_of_presentation.dart </em>and add a new enum member using our newly created <strong>CreditsSlide</strong> widget. <strong>Remember</strong>, the enum order actually matters, so if you add it at the beginning, it will show as the first slide as well.</p><p>Reload the presentation, and voilá here is our result:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*V2U_VUbaHbemw5N8gKBGzQ.png" /><figcaption>Congrats, a credits slide appeared 🎉</figcaption></figure><p>Done. Thx for reading this article, and leave some claps!</p><h3>… Can it be animated?</h3><p><strong>Yes</strong>, indeed, most components of <strong>FlutterShow</strong>⚡ can be animated automatically. For this, I implemented a small animation API. The <em>presentationController </em>that holds our presentation state has a property called <em>animationIndex. </em>We can make use of that in only <strong>two</strong> steps as well!</p><ol><li>Return to <em>lib/presentation/config/pages_of_presentation.dart </em>and set <em>animationSteps </em>to 5. By doing that the presentation knows that it has 5 “steps” to cycle through on that slide. We set it to 5 because we have a subtitle on that page + 3 bullet points that we want to appear on each click. The last click will make its transition to the next slide.</li><li>Now we need to return to the credits slide we implemented and provide one parameter: <em>animationIndex: controller.animationIndex</em></li></ol><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/05987b862ea51562584fd60ae52b3754/href">https://medium.com/media/05987b862ea51562584fd60ae52b3754/href</a></iframe><p>And we are done again 😄!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*otV_lImhpvGlKcRkQYO3Gg.gif" /></figure><p>Animation without much effort would be a dream, right?<br><strong>FlutterShow</strong>⚡ has got you covered 🤙🏼 Now you have learned how to create a slide and animate it. From here on, you can create your entire presentation.</p><p>If you want to find out how to change the way the bullet points animate from a fade to an animation in which they slide into the screen, then I would recommend heading to: <br><a href="https://flutter-show-docs.vercel.app/docs/quick-start#theres-more">https://flutter-show-docs.vercel.app/docs/quick-start#theres-more</a></p><h3>Closing words</h3><p>As you can see <strong>FlutterShow</strong>⚡ makes creating presentations easy and fast, the latter being very important for speakers since many tend to do their presentations last minute, from what I observed 😅.</p><p>Anyway, with <strong>FlutterShow</strong>⚡ I hope I was able to build a good ecosystem for presentations. The packages that <strong>FlutterShow</strong>⚡ depends on are also available outside of this framework. If you prefer one of the other solutions, you can still use my prebuilt widgets to make your process easier. Check out the <strong>documentation</strong> to read more about all components: <a href="https://flutter-show-docs.vercel.app/docs/intro">https://flutter-show-docs.vercel.app/docs/intro</a></p><p><strong>FlutterShow</strong>⚡ is my first big open-source project, and I will continuously be working on it to make the toolkit for future talks and other speakers, so that is why feedback is vital to me so that I can improve the framework. Currently, we have FlutterShow Keynote, which recreates all of Keynote’s slides in Flutter. I already have many other features in mind, but I plan to implement all of Google Slides Slides as another option in the future. If you have any idea or found something that can be improved, raise an issue:</p><p><a href="https://github.com/lucas-goldner/FlutterShow">GitHub - lucas-goldner/FlutterShow: Unleash your creativity with presentations like never before! FlutterShow is an easy-to-use framework built in Flutter for crafting engaging and interactive presentations.</a></p><p>(And leave a ⭐️)</p><p>Please let me know if you plan to create a presentation using FlutterShow!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=79ab316253b5" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>