<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mario Nachbaur</title>
    <description>The latest articles on DEV Community by Mario Nachbaur (@marionauta).</description>
    <link>https://dev.to/marionauta</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F212906%2Fa600fdd5-2324-4357-a09d-e34e0ddb884b.jpeg</url>
      <title>DEV Community: Mario Nachbaur</title>
      <link>https://dev.to/marionauta</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/marionauta"/>
    <language>en</language>
    <item>
      <title>Why your network requests may timeout intermittently in your iOS simulator</title>
      <dc:creator>Mario Nachbaur</dc:creator>
      <pubDate>Fri, 14 Mar 2025 13:47:00 +0000</pubDate>
      <link>https://dev.to/marionauta/why-your-network-requests-may-timeout-intermittently-in-your-ios-simulator-16ak</link>
      <guid>https://dev.to/marionauta/why-your-network-requests-may-timeout-intermittently-in-your-ios-simulator-16ak</guid>
      <description>&lt;p&gt;&lt;a href="https://mario.nachbaur.dev/words/ios-simulator-network-timeouts/" rel="noopener noreferrer"&gt;Published on my blog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; It appears that setting &lt;code&gt;URLSessionConfiguration.multipathServiceType = .handover&lt;/code&gt; messes up with the simulator. Use conditional compilation to only set it on physical devices.&lt;/p&gt;




&lt;p&gt;For some time, we at the iOS team at work were experiencing a quite strange phenomenon with the iOS simulators. Some times, some days, but not always, the iOS simulators refused to connect to our backend APIs, and all the requests did timeout. This meant we had to switch to developing and testing on our physical devices, which is a tad more inconvenient. Restarting the router, disconnecting or connecting to a VPN would help fix the issue, but not always.&lt;/p&gt;

&lt;p&gt;We even thought our backend, or any proxy service in use, had some sort of geographical restriction or protection against bots — remember, only the simulators were affected. But inspecting the raw network requests, the ones made with a physical device and the ones from a simulator were 100% identical, so not sure how they would detect a simulator request.&lt;/p&gt;

&lt;p&gt;After a long debugging session, we noticed we were initiating our &lt;code&gt;URLSession&lt;/code&gt; objects in the following manner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;configuration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;URLSessionConfiguration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;
&lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;multipathServiceType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;handover&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;URLSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the &lt;a href="https://developer.apple.com/documentation/foundation/urlsessionconfiguration/multipathservicetype/handover" rel="noopener noreferrer"&gt;&lt;code&gt;.handover&lt;/code&gt; documentation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A Multipath TCP service that provides seamless handover between Wi-Fi and cellular in order to preserve the connection.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;which sounds amazing, specially for an app like ours designed for people on the go. I seems that that setting was responsible for the timeouts in the iOS simulator. Only in the simulator. So we changed the initialization code to something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="cp"&gt;#if !targetEnvironment(simulator)&lt;/span&gt;
&lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;multipathServiceType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;handover&lt;/span&gt;
&lt;span class="cp"&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;The documentation for &lt;code&gt;.handover&lt;/code&gt; also mentions that you should only use it "for long-lived or persistent connections", so we will also tweak which &lt;code&gt;URLSession&lt;/code&gt;s have that option enabled and which don't.&lt;/p&gt;

</description>
      <category>ios</category>
      <category>mobile</category>
      <category>swift</category>
    </item>
    <item>
      <title>Renaming variables in Swift closure capture lists</title>
      <dc:creator>Mario Nachbaur</dc:creator>
      <pubDate>Thu, 28 Mar 2024 16:00:00 +0000</pubDate>
      <link>https://dev.to/marionauta/renaming-variables-in-swift-closure-capture-lists-cdd</link>
      <guid>https://dev.to/marionauta/renaming-variables-in-swift-closure-capture-lists-cdd</guid>
      <description>&lt;p&gt;&lt;a href="https://mario.nachbaur.dev/words/swift-variable-rename-closure/" rel="noopener noreferrer"&gt;Published on my blog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have written any Swift code, you probably have seen capture lists. Let me show them to you in case you're not sure what they are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Some&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;

  &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;method&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;someNetworkRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;weak&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
      &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="c1"&gt;//     ^ this thing right here&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That thing between the square brackets (&lt;code&gt;[ ]&lt;/code&gt;) is the capture list. It allows us to define the context of the callback. In this case, we capture &lt;code&gt;self&lt;/code&gt; weakly, to avoid memory cycles.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;With the introduction of iOS 17, SwiftUI gained a new &lt;code&gt;View&lt;/code&gt; modifier: &lt;code&gt;onChange(of:action:)&lt;/code&gt; where &lt;code&gt;action&lt;/code&gt; takes two values, the old one and the new one. This allows code such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;@State&lt;/span&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;isCreating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

  &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;some&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;isCreating&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;wasCreating&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;isCreating&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
        &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="n"&gt;wasCreating&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;isCreating&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Finished creating"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This is just a simplified example to show the modifier. Just imagine that instead of a &lt;code&gt;Bool&lt;/code&gt; we are using an enum with many cases.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;On iOS 16 and prior, the modifier only provides the new value, making it difficult to check the current value and the previous one. There is however, a small workaround using capture lists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="nf"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;isCreating&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;isCreating&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;newValue&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
  &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="n"&gt;isCreating&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;newValue&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Finished creating"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using a capture list, we can capture the current value, which is equivalent to the old value. And the callback provides us with &lt;code&gt;newValue&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;The previous code works, but the naming is awkward. &lt;code&gt;isCreating&lt;/code&gt; points to the old value, and &lt;code&gt;newValue&lt;/code&gt; is too generic. We could rename it to &lt;code&gt;newIsCreating&lt;/code&gt;, but still, not the best name.&lt;/p&gt;

&lt;p&gt;Here is when renaming variables inside the capture list shines. Let's look at the example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="nf"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;isCreating&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;wasCreating&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;isCreating&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;isCreating&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
  &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="n"&gt;wasCreating&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;isCreating&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Finished creating"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the capture group, we are declaring a new variable &lt;code&gt;wasCreating&lt;/code&gt; which the value of the captured variable &lt;code&gt;isCreating&lt;/code&gt; (the old value). Then the callback provides us with &lt;code&gt;isCreating&lt;/code&gt; (the new value)&lt;/p&gt;

&lt;h2&gt;
  
  
  Finishing
&lt;/h2&gt;

&lt;p&gt;The examples shown may be obsolete with iOS 17 new modifier, but there are a lot of developers supporting iOS 16 and below. I wrote this article solving the exact problem I faced, but I'm sure there will be many, many situations where renaming a variable would be very helpful.&lt;/p&gt;

</description>
      <category>swift</category>
      <category>swiftui</category>
      <category>ios</category>
    </item>
    <item>
      <title>WebSocket service behind nginx reverse proxy</title>
      <dc:creator>Mario Nachbaur</dc:creator>
      <pubDate>Tue, 24 Jan 2023 18:28:00 +0000</pubDate>
      <link>https://dev.to/marionauta/websocket-service-behind-nginx-reverse-proxy-4ene</link>
      <guid>https://dev.to/marionauta/websocket-service-behind-nginx-reverse-proxy-4ene</guid>
      <description>&lt;p&gt;I have all my backend services behind a nginx reverse proxy. It allows  me to host many services with different URLs on the same machine,  when they're lightweight enough. And it manages SSL  and everything needed for secure connections for me, so I can keep my  code simple.&lt;/p&gt;

&lt;p&gt;The latest service I'm working on relies a lot on WebSockets. Most browsers only allow &lt;code&gt;wss://&lt;/code&gt; (secure web sockets) connections from web pages served with &lt;code&gt;https://&lt;/code&gt;. So I needed to serve the socket with SSL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;For a successful web socket connection, we need to ensure that the &lt;strong&gt;HTTP version is correct&lt;/strong&gt; and &lt;strong&gt;pass some headers&lt;/strong&gt; to the service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/ws&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_http_version&lt;/span&gt; &lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://address:port&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Connection&lt;/span&gt; &lt;span class="nv"&gt;$http_connection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Upgrade&lt;/span&gt; &lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configuration only applies to the &lt;code&gt;/ws&lt;/code&gt; route, because that is where the socket is. We set the HTTP version to &lt;code&gt;1.1&lt;/code&gt; since nginx uses &lt;code&gt;1.0&lt;/code&gt; by default, and forward the &lt;code&gt;Connection&lt;/code&gt; and &lt;code&gt;Upgrade&lt;/code&gt; HTTP headers to the service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping the socket open
&lt;/h2&gt;

&lt;p&gt;The first thing I noticed after setting up the reverse proxy is that my connections were closing after a while. Turns out nginx closes connections that don't send any data within 60 seconds. You can increment this timeout thanks to the &lt;code&gt;proxy_read_timeout&lt;/code&gt; directive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/ws&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;# ...&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_read_timeout&lt;/span&gt; &lt;span class="s"&gt;300s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But I opted to send &lt;code&gt;ping&lt;/code&gt; messages periodically from the client to tell the service that I'm still interested in keeping the connection open. I didn't like the idea of setting the timeout to some large time amount and have a connection open indefinitely.&lt;/p&gt;

</description>
      <category>tooling</category>
      <category>developer</category>
      <category>productivity</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Today, I enter the IndieWeb</title>
      <dc:creator>Mario Nachbaur</dc:creator>
      <pubDate>Sun, 12 Apr 2020 16:38:07 +0000</pubDate>
      <link>https://dev.to/marionauta/today-i-enter-the-indieweb-28d6</link>
      <guid>https://dev.to/marionauta/today-i-enter-the-indieweb-28d6</guid>
      <description>&lt;p&gt;Today I updated my personal &lt;a href="https://mario.nachbaur.dev"&gt;website&lt;/a&gt;. If you ever visited it before, you may think that nothing has changed. And you'd be right, &lt;em&gt;visually&lt;/em&gt; not much has changed since I created it, just some links here and there.&lt;/p&gt;

&lt;p&gt;I know my website may look simple, barebones, or some may say... &lt;em&gt;ugly&lt;/em&gt;, but I like it that way. Also, I'm very proud that it supports light / dark theme based on your system preferences. And more importantly, it has this feature that I'm sure yours doesn't.&lt;/p&gt;

&lt;p&gt;So what's the &lt;a href="https://indieweb.org/"&gt;IndieWeb&lt;/a&gt;? It's a way to use your own website as your entire online presence. You can set it up as your personal business card of sorts, and even &lt;strong&gt;log in into services&lt;/strong&gt; with it, which is just mind blowing.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;h-card&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The first thing you'll probably want to do is set up your profile. How can you do it? You have to add an &lt;code&gt;h-card&lt;/code&gt; to the index page fo your website. Here's mine:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F57r3hcj1xiil0v1ulu32.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F57r3hcj1xiil0v1ulu32.png" alt="My very own h-card" width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As I mentioned earlier, &lt;em&gt;visually&lt;/em&gt; nothing has changed in my website, and that's partly because there's no minimum data requirements to build your &lt;code&gt;h-card&lt;/code&gt;. My website had the exact amount of data I wanted to share.&lt;br&gt;
Since the IndieWeb focuses on &lt;a href="https://indieweb.org/principles"&gt;humans first, machines second&lt;/a&gt;, they are &lt;a href="https://indieweb.org/antipatterns#invisible_metadata"&gt;against hiding content&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;h-card&lt;/code&gt; is about defining metadata about you, and the way you do it is adding classes to DOM elements. There are &lt;a href="http://microformats.org/wiki/h-card#Properties"&gt;a lot of properties&lt;/a&gt; you can use to present yourself. The IndieWeb respects &lt;a href="https://indieweb.org/design"&gt;how you want to publish your content&lt;/a&gt; and that includes you personal information, that's why there's no defined structure to build your &lt;code&gt;h-card&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here are some &lt;code&gt;h-card&lt;/code&gt; examples, of varying complexity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;h-card&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Mario Nachbaur&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
This one's probably the bare minimum







&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;h-card&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;p-name&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Mario Nachbaur&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;p-nickname&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;marionauta&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;I am a full stack software developer that likes
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;p-category&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Rubik Cubes&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;.
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
I use p-category to tell people about my hobbies







&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;h-card&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"p-name u-url u-uid"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;https://mario.nachbaur.dev&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Mario Nachbaur
  &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
You can use multiple properties in a single element





&lt;p&gt;You can go to &lt;a href="https://mario.nachbaur.dev"&gt;my website&lt;/a&gt; and check out how I configured my &lt;code&gt;h-card&lt;/code&gt; &lt;em&gt;(secondary click, view page source)&lt;/em&gt;. The website is very simple and the source it's easy to read.&lt;/p&gt;

&lt;h2&gt;
  
  
  IndieAuth
&lt;/h2&gt;

&lt;p&gt;This part is what wowed me the most. The fact that there are online services that allow you to sign up and log in using your website (remember, your website is your identity) is amazing. And the process to set it up couldn't be easier. Just have links with &lt;code&gt;rel=me&lt;/code&gt; between your profiles in various web services.&lt;/p&gt;

&lt;p&gt;Sadly, there aren't that many services that support it, and I don't think that I'll be using it that much, but the fact that I can do it is incredible. I will consider adding &lt;a href="https://indieweb.org/IndieAuth"&gt;IndieAuth&lt;/a&gt; to the next project I build.&lt;/p&gt;

&lt;h2&gt;
  
  
  The cost vs. the fun
&lt;/h2&gt;

&lt;p&gt;The only requirement to use the IndieWeb is owning a domain name, and host a website. Yes, domain names cost money and the hosting for the website too (unless you use a free service). That said, I think the cost is justified with the concept of the IndieWeb, owning your data, content and so on. The whole idea has The Matrix vibes to it, avoiding &lt;a href="https://indieweb.org/silo"&gt;silos&lt;/a&gt;, that I enjoy.&lt;/p&gt;

&lt;p&gt;If you already own a personal website, you don't loose anything trying it. In fact, you'll gain a couple of hours learning an &lt;a href="http://microformats.org/wiki/h-card"&gt;interesting format&lt;/a&gt;. I promise it's worth it!&lt;/p&gt;




&lt;p&gt;Lastly, thanks to &lt;a href="https://kevq.uk/implementing-the-indieweb-into-my-website/"&gt;Kev&lt;/a&gt; whose post inspired me to enter the IndieWeb, and to &lt;a href="https://randomgeekery.org/2020/04/11/indieweb-h-cards/"&gt;Brian&lt;/a&gt;, who explains really well the &lt;code&gt;h-card&lt;/code&gt; format.&lt;/p&gt;

</description>
      <category>indieweb</category>
      <category>webdev</category>
      <category>html</category>
    </item>
    <item>
      <title>On if let bindings in SwiftUI</title>
      <dc:creator>Mario Nachbaur</dc:creator>
      <pubDate>Sat, 11 Apr 2020 16:59:43 +0000</pubDate>
      <link>https://dev.to/marionauta/on-if-let-bindings-in-swiftui-21gj</link>
      <guid>https://dev.to/marionauta/on-if-let-bindings-in-swiftui-21gj</guid>
      <description>&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: with Xcode 12, we can write &lt;code&gt;if let&lt;/code&gt; bindings without problems. This code is now valid:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'll leave the post up for historical context.&lt;/p&gt;




&lt;p&gt;Recently I was building an app that lists public libraries in my home city. In early stages, the main view was just a list view that displays the library name and address. Something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmqmwhmoa1k6nt51oo1m9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmqmwhmoa1k6nt51oo1m9.png" alt="Screenshot showing a quick prototype for my app" width="749" height="509"&gt;&lt;/a&gt;&lt;/p&gt;
Quick prototype of my app



&lt;p&gt;As you can see, some libraries don't have an address, because of some unrelated reasons. And if the address isn't present, the name should be vertically centred in the row.&lt;/p&gt;

&lt;p&gt;A library not having an address is translated into my data model as an optional String. Here's a simplified version of my &lt;code&gt;Library&lt;/code&gt; model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;Library&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
Neat, eh?





&lt;h2&gt;
  
  
  Initial approach
&lt;/h2&gt;

&lt;p&gt;If a library doesn't have an address, I won't render a &lt;code&gt;Text&lt;/code&gt; component for it, simple as that. And the easiest way for me to do that was using an &lt;code&gt;if let&lt;/code&gt; binding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kt"&gt;VStack&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
This WON'T compile!





&lt;p&gt;As it turns out, SwiftUI doesn't like this. The compiler tells us that &lt;code&gt;Closure containing control flow statement cannot be used with function builder 'ViewBuilder'&lt;/code&gt;. &lt;em&gt;I beg your pardon?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;How else am I supposed to conditionally render views in my app if "control flow statement cannot be used" to build it? After a moment of panic, I tested using a normal &lt;code&gt;if&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kt"&gt;VStack&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
Force unwrapping make kittens cry





&lt;p&gt;And surprisingly that worked... wtf. Needless to say, I wasn't very exited with that solution, since it requires force unwrapping an optional value. I &lt;em&gt;knew&lt;/em&gt; that there was another way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current solution
&lt;/h2&gt;

&lt;p&gt;One of the key features of SwiftUI is that if we add a &lt;code&gt;nil&lt;/code&gt; component to our view, it won't show up, it's just ignored. So, what's the easiest way to convert a conditional string into a conditional &lt;code&gt;Text&lt;/code&gt;? That's right, using &lt;code&gt;map&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here we &lt;code&gt;map&lt;/code&gt; over the possibly &lt;code&gt;nil&lt;/code&gt; address, without needing to force unwrap it, as the closure will only be executed if there was a value in the first place. This, however, seems like a hack. But hey, It works.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kt"&gt;VStack&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
        &lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
Heh, mapping an optional... I can still hear my CS professor talking about monads.





&lt;h2&gt;
  
  
  Let's wait and see
&lt;/h2&gt;

&lt;p&gt;As I was reading some discussions about this issue, I found out that SwiftUI &lt;a href="https://jasonzurita.com/swiftui-if-statement/"&gt;builds views using a struct named &lt;code&gt;ViewBuilder&lt;/code&gt;&lt;/a&gt; — remember the error I was getting before? If we peek its definition (&lt;code&gt;cmd&lt;/code&gt; + &lt;code&gt;shift&lt;/code&gt; + &lt;code&gt;o&lt;/code&gt; in XCode to go to any class definition) we can clearly see that it supports &lt;code&gt;if&lt;/code&gt; statements, but nothing more.&lt;/p&gt;

&lt;p&gt;SwiftUI is not event a year old, and we know Apple only introduces big features once a year. So here's hoping that when the next version of SwiftUI shows up, they add &lt;code&gt;if let&lt;/code&gt; support.&lt;/p&gt;

</description>
      <category>swift</category>
      <category>swiftui</category>
      <category>ios</category>
      <category>macos</category>
    </item>
    <item>
      <title>Avoid notches in your PWA with just CSS</title>
      <dc:creator>Mario Nachbaur</dc:creator>
      <pubDate>Sat, 26 Oct 2019 11:16:50 +0000</pubDate>
      <link>https://dev.to/marionauta/avoid-notches-in-your-pwa-with-just-css-al7</link>
      <guid>https://dev.to/marionauta/avoid-notches-in-your-pwa-with-just-css-al7</guid>
      <description>&lt;p&gt;At work, I'm usually creating native mobile apps, both in Swift and React Native. But for a new project, we decided it was better to implement a &lt;em&gt;progressive web app&lt;/em&gt;. I have experience in HTML, CSS &amp;amp; JavaScript, so I thought there won't be any problems.&lt;/p&gt;

&lt;p&gt;All was going according to plan until we met a new enemy: The iPhone X.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F885ajcm31qugh0h8ro3n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F885ajcm31qugh0h8ro3n.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
Excuse me, I'd like to TAP those buttons!



&lt;h2&gt;
  
  
  Native background
&lt;/h2&gt;

&lt;p&gt;In the native world, we have something called &lt;em&gt;safe area&lt;/em&gt;, a "box" where we can put things inside and be sure they'll be outside of the notch and bottom areas.&lt;/p&gt;

&lt;p&gt;This way it's easy to tell the app to place some component at the top of the screen, but move it a little to the bottom if there's a notch in the way.&lt;/p&gt;

&lt;p&gt;For the PWA, the easiest way to avoid that stupid bottom bar is by adding some &lt;code&gt;padding-bottom&lt;/code&gt;, but that would break all other devices. I thought to add a CSS class conditionally with JavaScript, but that seemed like a hack.&lt;/p&gt;

&lt;h2&gt;
  
  
  CSS Environment Variables
&lt;/h2&gt;

&lt;p&gt;As you may know, we can now define and use custom CSS variables with &lt;code&gt;var(--padding-bottom)&lt;/code&gt;. The same way, browsers can also define their own. They're in the process of standardization, but Apple has created some of their own.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nc"&gt;.navbar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;padding-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;safe-area-inset-bottom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We define the bottom padding for browsers that don't yet support environment variables. If we were to omit the first rule, the second one is broken and nothing applies.&lt;/p&gt;

&lt;p&gt;For browsers that do support them, we want the bottom padding to be equal to &lt;code&gt;safe-area-inset-bottom&lt;/code&gt;, and fall back to &lt;code&gt;0&lt;/code&gt; if the variable isn't set.&lt;/p&gt;

&lt;p&gt;Similarly, there are also variables for the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/env#Values" rel="noopener noreferrer"&gt;top, left and right screen edges&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fve1eiilchvrbtmjrwuxr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fve1eiilchvrbtmjrwuxr.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
Success!



</description>
      <category>css</category>
      <category>html</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
