<?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: Olawale Bashiru</title>
    <description>The latest articles on DEV Community by Olawale Bashiru (@olawalethefirst).</description>
    <link>https://dev.to/olawalethefirst</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%2F682788%2F319e53bf-f622-4ecb-92ff-30b05b2c59f9.JPEG</url>
      <title>DEV Community: Olawale Bashiru</title>
      <link>https://dev.to/olawalethefirst</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/olawalethefirst"/>
    <language>en</language>
    <item>
      <title>How I Bridged AWS Face Liveness to Expo with a Native Module</title>
      <dc:creator>Olawale Bashiru</dc:creator>
      <pubDate>Thu, 04 Jun 2026 16:29:16 +0000</pubDate>
      <link>https://dev.to/olawalethefirst/how-i-bridged-aws-face-liveness-to-expo-with-a-native-module-2o49</link>
      <guid>https://dev.to/olawalethefirst/how-i-bridged-aws-face-liveness-to-expo-with-a-native-module-2o49</guid>
      <description>&lt;p&gt;AWS Face Liveness has native SDKs for iOS and Android.&lt;/p&gt;

&lt;p&gt;That works well if you are building fully native apps.&lt;/p&gt;

&lt;p&gt;But if your team is building with Expo, the integration path is not as simple as installing a JavaScript package.&lt;/p&gt;

&lt;p&gt;You still have to think about native iOS setup, native Android setup, camera permissions, Amplify configuration, credential handling, build configuration, and the bridge between JavaScript and native code.&lt;/p&gt;

&lt;p&gt;That gap is what led me to build &lt;code&gt;expo-face-liveness-for-aws-amplify&lt;/code&gt;, an Expo module that integrates AWS Amplify Face Liveness into Android and iOS Expo projects.&lt;/p&gt;

&lt;p&gt;The business case was clear too: financial and identity-sensitive products often need to verify that a real person is completing sensitive flows like onboarding, KYC, account recovery, fraud prevention, or high-risk actions.&lt;/p&gt;

&lt;p&gt;Face liveness does not replace every other security measure. It adds another layer of confidence that the product backend can use as part of its final decision.&lt;/p&gt;

&lt;p&gt;This article breaks down how I approached the problem, what AWS Face Liveness needs architecturally, how the module is designed, the tradeoffs I made, and what I learned from the first release.&lt;/p&gt;

&lt;p&gt;Here is the module running on both platforms:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;iOS&lt;/th&gt;
&lt;th&gt;Android&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F03arghjy72oninl6x22l.gif" alt="AWS Face Liveness running on iOS" width="296" height="640"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnvozmgz894v06bcekskc.gif" alt="AWS Face Liveness running on Android" width="288" height="640"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Why this problem exists
&lt;/h2&gt;

&lt;p&gt;For fully native mobile apps, the integration path is more direct.&lt;/p&gt;

&lt;p&gt;You install the native SDK, configure the platform-specific requirements, and render the UI component provided by the SDK.&lt;/p&gt;

&lt;p&gt;For Expo teams, the story is different.&lt;/p&gt;

&lt;p&gt;A React Native or Expo app may share most of its product code across platforms, but native SDKs still require platform-specific setup.&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;iOS configuration&lt;/li&gt;
&lt;li&gt;Android configuration&lt;/li&gt;
&lt;li&gt;camera permissions&lt;/li&gt;
&lt;li&gt;native dependencies&lt;/li&gt;
&lt;li&gt;version compatibility&lt;/li&gt;
&lt;li&gt;build configuration&lt;/li&gt;
&lt;li&gt;credential handling&lt;/li&gt;
&lt;li&gt;JavaScript-to-native events&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before abstracting this into a package, the painful part was not only getting the detector to render once.&lt;/p&gt;

&lt;p&gt;The painful part was knowing that every product with the same requirement would have to repeat the same native setup decisions: how to configure iOS, how to wire Android, how to handle camera permissions, how to make Amplify credentials available, how to expose native completion events, and how to keep the backend as the source of truth.&lt;/p&gt;

&lt;p&gt;That repetition was the real signal.&lt;/p&gt;

&lt;p&gt;Once the same liveness requirement appeared across multiple products, including one I was leading and another a colleague reached out about, the problem stopped being “how do I make this work here?” and became “how do I make this easier to reuse anywhere an Expo app needs it?”&lt;/p&gt;

&lt;h2&gt;
  
  
  What AWS Face Liveness needs to work
&lt;/h2&gt;

&lt;p&gt;Before building the module, I needed to understand what the SDK actually requires.&lt;/p&gt;

&lt;p&gt;AWS Face Liveness is not just a screen you open in the app. It depends on a few moving parts working together.&lt;/p&gt;

&lt;p&gt;The first part is authorization.&lt;/p&gt;

&lt;p&gt;The liveness detector needs the app to be configured in a way that allows the SDK to communicate with AWS during the capture flow. In the standard Amplify setup, this is usually handled through Amplify Auth and Cognito-backed resources.&lt;/p&gt;

&lt;p&gt;The second part is the liveness session.&lt;/p&gt;

&lt;p&gt;A session is created by the backend before the client starts the liveness flow. That session acts like a reference shared between the backend, the client app, the AWS service, and the Face Liveness SDK.&lt;/p&gt;

&lt;p&gt;At a high level, the flow looks like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Backend creates a Face Liveness session&lt;br&gt;
App receives the session ID and region&lt;br&gt;
App renders the Face Liveness detector&lt;br&gt;
Native SDK performs the liveness flow&lt;br&gt;
App receives a completion event&lt;br&gt;
Backend verifies the final result&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The important design principle is this:&lt;/p&gt;

&lt;p&gt;The mobile app participates in the flow, but it should not own the trust boundary.&lt;/p&gt;

&lt;p&gt;The backend should create the session and verify the final result. The client should only receive what it needs to start the liveness experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I chose runtime credentials
&lt;/h2&gt;

&lt;p&gt;One of the most important design decisions was how the module should receive AWS credentials.&lt;/p&gt;

&lt;p&gt;The standard Amplify/Cognito-oriented path works well when an application already uses Amplify Auth and Cognito-backed configuration.&lt;/p&gt;

&lt;p&gt;In that setup, the app is usually initialized with generated Amplify client configuration, such as &lt;code&gt;amplify_outputs.json&lt;/code&gt; or &lt;code&gt;amplifyconfiguration.json&lt;/code&gt;, depending on the platform, SDK version, and setup path.&lt;/p&gt;

&lt;p&gt;That configuration tells the Amplify client libraries which backend Auth resources to use, including details such as the AWS region, User Pool, User Pool Client, and Identity Pool.&lt;/p&gt;

&lt;p&gt;The native app also needs the relevant Amplify Auth plugin setup so the SDK can resolve AWS credentials for service calls.&lt;/p&gt;

&lt;p&gt;That is a good fit for apps already built around Amplify and Cognito.&lt;/p&gt;

&lt;p&gt;For a reusable Expo module, though, I did not want to force every consuming app into that structure.&lt;/p&gt;

&lt;p&gt;Some apps may already use Cognito. Some may use a different authentication system. Some may want their backend to own the full credential flow. Some may need to support multiple environments or products where credentials are resolved dynamically instead of being tied only to a generated Amplify client configuration file.&lt;/p&gt;

&lt;p&gt;If the module assumed one Amplify/Cognito setup, it would become less reusable.&lt;/p&gt;

&lt;p&gt;So I chose a runtime credentials path.&lt;/p&gt;

&lt;p&gt;Instead of coupling the package to a specific Amplify Auth configuration file or Cognito setup, the host app can fetch temporary credentials from its backend and pass them into the module before rendering the detector.&lt;/p&gt;

&lt;p&gt;In this package, that happens through &lt;code&gt;setAuthCredentials&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Internally, the native layer provides those credentials to the AWS Face Liveness SDK through a custom credentials provider.&lt;/p&gt;

&lt;p&gt;This keeps the boundary clear: the host app owns its backend and authentication model, the backend issues temporary scoped credentials, and the module focuses on the native Face Liveness integration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Module architecture
&lt;/h2&gt;

&lt;p&gt;The module is designed around a simple idea:&lt;/p&gt;

&lt;p&gt;Keep the host application responsible for trust, and keep the package responsible for the native liveness experience.&lt;/p&gt;

&lt;p&gt;To make that work, the package is split into a few layers.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Backend&lt;/td&gt;
&lt;td&gt;Creates the liveness session, issues temporary credentials, and verifies the result&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JavaScript API&lt;/td&gt;
&lt;td&gt;Exposes methods for setting and clearing credentials, and a detector view for the app to render&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Credential store&lt;/td&gt;
&lt;td&gt;Holds temporary credentials until they are needed by the native SDK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom credentials provider&lt;/td&gt;
&lt;td&gt;Reads from the credential store and provides credentials to AWS Amplify&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Expo config plugin&lt;/td&gt;
&lt;td&gt;Prepares native project configuration during prebuild&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iOS native layer&lt;/td&gt;
&lt;td&gt;Renders the AWS Face Liveness detector on iOS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Android native layer&lt;/td&gt;
&lt;td&gt;Renders the AWS Face Liveness detector on Android&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Event bridge&lt;/td&gt;
&lt;td&gt;Sends completion and error events from native code back to JavaScript&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The credential store and custom credentials provider are separate on purpose.&lt;/p&gt;

&lt;p&gt;The store is responsible for holding the latest credentials passed from JavaScript. The provider is responsible for giving those credentials to the native AWS SDK when it asks for them.&lt;/p&gt;

&lt;p&gt;This structure keeps the package focused.&lt;/p&gt;

&lt;p&gt;It does not try to own the backend. It does not decide how the consuming app authenticates users. It only provides the bridge needed for an Expo app to use the native Face Liveness experience on iOS and Android.&lt;/p&gt;

&lt;h2&gt;
  
  
  Public API design
&lt;/h2&gt;

&lt;p&gt;I wanted the JavaScript-facing API to stay small, explicit, and easy to reason about.&lt;/p&gt;

&lt;p&gt;The package exposes a few core pieces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;setAuthCredentials&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;clearAuthCredentials&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FaceLivenessDetectorView&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;onAnalysisComplete&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;onError&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The intended flow is simple:&lt;/p&gt;

&lt;p&gt;Set credentials. Render the detector. Listen for completion. Verify the result on the backend.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;setAuthCredentials&lt;/code&gt; gives the native layer the temporary credentials needed to run the liveness flow.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;clearAuthCredentials&lt;/code&gt; lets the host app intentionally remove credentials when they are no longer needed.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;FaceLivenessDetectorView&lt;/code&gt; is the native UI entry point in the React Native tree.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;onAnalysisComplete&lt;/code&gt; tells the app when the capture flow has completed.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;onError&lt;/code&gt; gives the app a way to handle failures from the native layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Config plugin design
&lt;/h2&gt;

&lt;p&gt;For Expo projects, a package is not complete if developers still have to manually patch native files every time they run prebuild.&lt;/p&gt;

&lt;p&gt;That is why the config plugin is an important part of the package.&lt;/p&gt;

&lt;p&gt;The plugin helps prepare the native project configuration needed by the module, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;camera permissions&lt;/li&gt;
&lt;li&gt;Android desugaring&lt;/li&gt;
&lt;li&gt;Android Compose compiler setup&lt;/li&gt;
&lt;li&gt;native configuration required by the underlying implementation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If every consuming project has to manually rediscover the same native setup steps after prebuild, the abstraction is incomplete.&lt;/p&gt;

&lt;p&gt;The config plugin moves those repeatable setup details closer to the package, so the consuming app can focus on the product flow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security and trust boundary
&lt;/h2&gt;

&lt;p&gt;One of the easiest mistakes in mobile integrations is placing too much trust in the client.&lt;/p&gt;

&lt;p&gt;For this package, I wanted the boundary to stay clear: the mobile app can start and display the liveness flow, but the backend should create the session, issue temporary credentials, and verify the final result.&lt;/p&gt;

&lt;p&gt;Long-lived AWS credentials should not be bundled into the mobile app. Anything shipped inside a mobile app should be treated as visible eventually.&lt;/p&gt;

&lt;p&gt;That separation keeps the mobile client as a participant in the experience, while the backend remains responsible for trust decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key decisions and tradeoffs
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Decision&lt;/th&gt;
&lt;th&gt;Why it mattered&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Build as an Expo module&lt;/td&gt;
&lt;td&gt;The target users are Expo teams that need native SDK integration without abandoning their Expo workflow.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Support iOS and Android&lt;/td&gt;
&lt;td&gt;AWS Face Liveness is distributed through native mobile experiences, so both platforms needed first-class support.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use runtime temporary credentials&lt;/td&gt;
&lt;td&gt;It keeps the module reusable across apps with different backend and auth setups.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keep result verification on the backend&lt;/td&gt;
&lt;td&gt;The backend should remain the source of truth for sensitive verification decisions.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Add a config plugin&lt;/td&gt;
&lt;td&gt;It reduces repeated native setup work across consuming Expo projects.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Add unsupported web entry points&lt;/td&gt;
&lt;td&gt;Unsupported platforms should fail clearly instead of silently behaving in unexpected ways.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Start with a focused API&lt;/td&gt;
&lt;td&gt;A smaller API is easier to document, test, reason about, and improve based on real feedback.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;There are also important limitations.&lt;/p&gt;

&lt;p&gt;The package does not work in Expo Go because it includes native iOS and Android code. It requires a custom development client or a native/EAS build.&lt;/p&gt;

&lt;p&gt;Web is also not supported. The package is focused on the native mobile Face Liveness experience.&lt;/p&gt;

&lt;p&gt;The consuming app still needs a backend flow. The package does not create liveness sessions or verify final results by itself. That responsibility should remain on the backend.&lt;/p&gt;

&lt;p&gt;Not every customization option from the underlying native SDKs is exposed yet. The first release focuses on the core liveness flow.&lt;/p&gt;

&lt;p&gt;Finally, native SDK compatibility still matters. Since the package depends on native AWS Amplify SDKs, future changes in Expo, React Native, Android, iOS, or AWS dependencies may require compatibility work.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use the package
&lt;/h2&gt;

&lt;p&gt;To try the package, install it from npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;expo-face-liveness-for-aws-amplify
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the config plugin to your Expo config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"expo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"plugins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"expo-face-liveness-for-aws-amplify"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At a high level, the app flow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;FaceLivenessDetectorView&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;setAuthCredentials&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;expo-face-liveness-for-aws-amplify&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;setAuthCredentials&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;accessKeyId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;secretAccessKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;sessionToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;expiration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FaceLivenessDetectorView&lt;/span&gt;
  &lt;span class="nx"&gt;sessionId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;sessionId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;us-east-1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;onAnalysisComplete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Ask your backend to verify the result.&lt;/span&gt;
  &lt;span class="p"&gt;}}&lt;/span&gt;
  &lt;span class="nx"&gt;onError&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Handle native SDK or configuration errors.&lt;/span&gt;
  &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;expiration&lt;/code&gt; should match the format expected by the package API for temporary credential expiration. In your implementation, document whether this should be an ISO string, timestamp, or JavaScript &lt;code&gt;Date&lt;/code&gt; value so users do not have to guess.&lt;/p&gt;

&lt;p&gt;For full setup instructions, backend requirements, and troubleshooting, see the GitHub documentation.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/olawalethefirst/expo-face-liveness-for-aws-amplify" rel="noopener noreferrer"&gt;https://github.com/olawalethefirst/expo-face-liveness-for-aws-amplify&lt;/a&gt;&lt;br&gt;
npm: &lt;a href="https://www.npmjs.com/package/expo-face-liveness-for-aws-amplify" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/expo-face-liveness-for-aws-amplify&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Gotchas to know before using it
&lt;/h2&gt;

&lt;p&gt;There are a few important things to know before trying the package.&lt;/p&gt;

&lt;p&gt;First, it will not work in Expo Go. The package includes native iOS and Android code, so you need a custom development client or a native/EAS build.&lt;/p&gt;

&lt;p&gt;Second, the app still needs a backend. The package does not create Face Liveness sessions or verify the final result. It only handles the native mobile liveness experience.&lt;/p&gt;

&lt;p&gt;Third, credentials must be available before the detector is rendered. In this package, that means calling &lt;code&gt;setAuthCredentials&lt;/code&gt; before mounting &lt;code&gt;FaceLivenessDetectorView&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Fourth, native SDK compatibility still matters. Since the package depends on the underlying AWS Amplify native SDKs, changes across Expo, React Native, iOS, Android, or AWS dependencies may require compatibility updates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons learned
&lt;/h2&gt;

&lt;p&gt;A few lessons stood out while building this.&lt;/p&gt;

&lt;p&gt;First, native SDK integration is rarely just about rendering a native view. Build configuration, permissions, credentials, platform differences, and backend responsibilities all matter.&lt;/p&gt;

&lt;p&gt;Second, reusable infrastructure often starts from repeated product pain. A one-off solution may be enough the first time. When the same requirement appears across multiple products, abstraction becomes more valuable.&lt;/p&gt;

&lt;p&gt;Third, identity-sensitive flows need clear trust boundaries. The mobile app can provide the experience, but the backend should own session creation, credential issuance, and result verification.&lt;/p&gt;

&lt;h2&gt;
  
  
  Roadmap
&lt;/h2&gt;

&lt;p&gt;The first release focuses on the core Face Liveness flow for Expo projects on iOS and Android.&lt;/p&gt;

&lt;p&gt;Next, I want to improve the package around the areas that make real integrations easier: clearer backend examples, better example app coverage, broader Expo SDK compatibility testing, CI checks for native builds, and clearer documentation around native SDK customization boundaries.&lt;/p&gt;

&lt;p&gt;The goal is to keep the roadmap practical and shaped by real usage feedback, not to make the package own every part of the liveness experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This package started from a product integration problem.&lt;/p&gt;

&lt;p&gt;At first, the goal was to help a team move forward without rewriting an application. But as the same need appeared across more products, the problem became bigger than one implementation.&lt;/p&gt;

&lt;p&gt;That is what led me to build &lt;code&gt;expo-face-liveness-for-aws-amplify&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For me, the most valuable part was not only getting the native SDKs to work. It was designing the boundary between business need, backend trust, native implementation, and developer experience.&lt;/p&gt;

&lt;p&gt;That is the kind of engineering I enjoy most: turning repeated product needs into infrastructure other teams can build on.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>mobile</category>
      <category>reactnative</category>
      <category>security</category>
    </item>
    <item>
      <title>Hey guys, breakpoint-overlay crossed a 100 GitHub stars milestone! Read about it if you've not yet.</title>
      <dc:creator>Olawale Bashiru</dc:creator>
      <pubDate>Mon, 24 Nov 2025 19:49:37 +0000</pubDate>
      <link>https://dev.to/olawalethefirst/hey-guys-breakpoint-overlay-crossed-a-100-github-stars-milestone-read-about-it-if-youve-not-yet-1m8f</link>
      <guid>https://dev.to/olawalethefirst/hey-guys-breakpoint-overlay-crossed-a-100-github-stars-milestone-read-about-it-if-youve-not-yet-1m8f</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/olawalethefirst/how-i-built-a-tiny-tool-that-makes-responsive-design-feel-effortless-4caj" class="crayons-story__hidden-navigation-link"&gt;How I Built a Tiny Tool That Makes Responsive Design Feel Effortless&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/olawalethefirst" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F682788%2F319e53bf-f622-4ecb-92ff-30b05b2c59f9.JPEG" alt="olawalethefirst profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/olawalethefirst" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Olawale Bashiru
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Olawale Bashiru
                
              
              &lt;div id="story-author-preview-content-3015581" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/olawalethefirst" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F682788%2F319e53bf-f622-4ecb-92ff-30b05b2c59f9.JPEG" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Olawale Bashiru&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/olawalethefirst/how-i-built-a-tiny-tool-that-makes-responsive-design-feel-effortless-4caj" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Nov 12 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/olawalethefirst/how-i-built-a-tiny-tool-that-makes-responsive-design-feel-effortless-4caj" id="article-link-3015581"&gt;
          How I Built a Tiny Tool That Makes Responsive Design Feel Effortless
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/frontend"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;frontend&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/css"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;css&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opensource"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opensource&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/olawalethefirst/how-i-built-a-tiny-tool-that-makes-responsive-design-feel-effortless-4caj" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;109&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/olawalethefirst/how-i-built-a-tiny-tool-that-makes-responsive-design-feel-effortless-4caj#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              35&lt;span class="hidden s:inline"&gt; comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>css</category>
      <category>opensource</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Olawale Bashiru</dc:creator>
      <pubDate>Sat, 22 Nov 2025 13:20:32 +0000</pubDate>
      <link>https://dev.to/olawalethefirst/-1kj5</link>
      <guid>https://dev.to/olawalethefirst/-1kj5</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/olawalethefirst" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F682788%2F319e53bf-f622-4ecb-92ff-30b05b2c59f9.JPEG" alt="olawalethefirst"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/olawalethefirst/how-i-built-a-tiny-tool-that-makes-responsive-design-feel-effortless-4caj" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How I Built a Tiny Tool That Makes Responsive Design Feel Effortless&lt;/h2&gt;
      &lt;h3&gt;Olawale Bashiru ・ Nov 12&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#frontend&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#css&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>css</category>
      <category>opensource</category>
    </item>
    <item>
      <title>This is such an insightful POV</title>
      <dc:creator>Olawale Bashiru</dc:creator>
      <pubDate>Sat, 15 Nov 2025 12:14:11 +0000</pubDate>
      <link>https://dev.to/olawalethefirst/this-is-such-an-insightful-pov-28ib</link>
      <guid>https://dev.to/olawalethefirst/this-is-such-an-insightful-pov-28ib</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/sylwia-lask/jquery-will-outlive-half-of-todays-javascript-frameworks-heres-why-2mmd" class="crayons-story__hidden-navigation-link"&gt;jQuery Will Outlive Half of Today’s JavaScript Frameworks - Here's Why&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/sylwia-lask" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3535771%2Fe22860d5-274b-43c9-819b-56b162e5bd5a.jpeg" alt="sylwia-lask profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/sylwia-lask" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Sylwia Laskowska
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Sylwia Laskowska
                
              
              &lt;div id="story-author-preview-content-2987261" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/sylwia-lask" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3535771%2Fe22860d5-274b-43c9-819b-56b162e5bd5a.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Sylwia Laskowska&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/sylwia-lask/jquery-will-outlive-half-of-todays-javascript-frameworks-heres-why-2mmd" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Nov 5 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/sylwia-lask/jquery-will-outlive-half-of-todays-javascript-frameworks-heres-why-2mmd" id="article-link-2987261"&gt;
          jQuery Will Outlive Half of Today’s JavaScript Frameworks - Here's Why
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag crayons-tag--filled  " href="/t/discuss"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;discuss&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/sylwia-lask/jquery-will-outlive-half-of-todays-javascript-frameworks-heres-why-2mmd" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;135&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/sylwia-lask/jquery-will-outlive-half-of-todays-javascript-frameworks-heres-why-2mmd#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              115&lt;span class="hidden s:inline"&gt; comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>discuss</category>
    </item>
    <item>
      <title>52 GitHub stars and 12 daily npm downloads feel very satisfying. The feedback so far indicates that front-end developers find this tool I worked on important.
If you've not read this publication yet, please do. I explained "why" I chose to work on this</title>
      <dc:creator>Olawale Bashiru</dc:creator>
      <pubDate>Sat, 15 Nov 2025 12:01:26 +0000</pubDate>
      <link>https://dev.to/olawalethefirst/52-github-stars-and-12-daily-npm-downloads-feel-very-satisfying-the-feedback-so-far-indicates-that-50bf</link>
      <guid>https://dev.to/olawalethefirst/52-github-stars-and-12-daily-npm-downloads-feel-very-satisfying-the-feedback-so-far-indicates-that-50bf</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/olawalethefirst/how-i-built-a-tiny-tool-that-makes-responsive-design-feel-effortless-4caj" class="crayons-story__hidden-navigation-link"&gt;How I Built a Tiny Tool That Makes Responsive Design Feel Effortless&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/olawalethefirst" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F682788%2F319e53bf-f622-4ecb-92ff-30b05b2c59f9.JPEG" alt="olawalethefirst profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/olawalethefirst" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Olawale Bashiru
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Olawale Bashiru
                
              
              &lt;div id="story-author-preview-content-3015581" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/olawalethefirst" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F682788%2F319e53bf-f622-4ecb-92ff-30b05b2c59f9.JPEG" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Olawale Bashiru&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/olawalethefirst/how-i-built-a-tiny-tool-that-makes-responsive-design-feel-effortless-4caj" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Nov 12 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/olawalethefirst/how-i-built-a-tiny-tool-that-makes-responsive-design-feel-effortless-4caj" id="article-link-3015581"&gt;
          How I Built a Tiny Tool That Makes Responsive Design Feel Effortless
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/frontend"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;frontend&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/css"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;css&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opensource"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opensource&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/olawalethefirst/how-i-built-a-tiny-tool-that-makes-responsive-design-feel-effortless-4caj" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;109&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/olawalethefirst/how-i-built-a-tiny-tool-that-makes-responsive-design-feel-effortless-4caj#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              35&lt;span class="hidden s:inline"&gt; comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>css</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Hey guys, just in case you missed this: I documented my experience building an open-source solution to improving the experience of front-end developers. Please check it out!</title>
      <dc:creator>Olawale Bashiru</dc:creator>
      <pubDate>Fri, 14 Nov 2025 08:10:34 +0000</pubDate>
      <link>https://dev.to/olawalethefirst/hey-guys-just-in-case-you-missed-this-i-documented-my-experience-building-an-open-source-solution-3l13</link>
      <guid>https://dev.to/olawalethefirst/hey-guys-just-in-case-you-missed-this-i-documented-my-experience-building-an-open-source-solution-3l13</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/olawalethefirst/how-i-built-a-tiny-tool-that-makes-responsive-design-feel-effortless-4caj" class="crayons-story__hidden-navigation-link"&gt;How I Built a Tiny Tool That Makes Responsive Design Feel Effortless&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/olawalethefirst" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F682788%2F319e53bf-f622-4ecb-92ff-30b05b2c59f9.JPEG" alt="olawalethefirst profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/olawalethefirst" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Olawale Bashiru
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Olawale Bashiru
                
              
              &lt;div id="story-author-preview-content-3015581" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/olawalethefirst" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F682788%2F319e53bf-f622-4ecb-92ff-30b05b2c59f9.JPEG" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Olawale Bashiru&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/olawalethefirst/how-i-built-a-tiny-tool-that-makes-responsive-design-feel-effortless-4caj" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Nov 12 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/olawalethefirst/how-i-built-a-tiny-tool-that-makes-responsive-design-feel-effortless-4caj" id="article-link-3015581"&gt;
          How I Built a Tiny Tool That Makes Responsive Design Feel Effortless
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/frontend"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;frontend&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/css"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;css&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opensource"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opensource&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/olawalethefirst/how-i-built-a-tiny-tool-that-makes-responsive-design-feel-effortless-4caj" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;109&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/olawalethefirst/how-i-built-a-tiny-tool-that-makes-responsive-design-feel-effortless-4caj#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              35&lt;span class="hidden s:inline"&gt; comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>css</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How I Built a Tiny Tool That Makes Responsive Design Feel Effortless</title>
      <dc:creator>Olawale Bashiru</dc:creator>
      <pubDate>Wed, 12 Nov 2025 10:04:53 +0000</pubDate>
      <link>https://dev.to/olawalethefirst/how-i-built-a-tiny-tool-that-makes-responsive-design-feel-effortless-4caj</link>
      <guid>https://dev.to/olawalethefirst/how-i-built-a-tiny-tool-that-makes-responsive-design-feel-effortless-4caj</guid>
      <description>&lt;h3&gt;
  
  
  Setting the Stage
&lt;/h3&gt;

&lt;p&gt;Ever wondered why the features your favorite product promises often take longer than planned? Or why it sometimes feels like engineers deliver more promises than features? Considering how disappointing it feels, experiencing both sides of that letdown has taught me how crucial it is to deliver on time and with high quality.&lt;br&gt;
Developer tooling is one of the core elements that impact delivery speed. The capacity of a developer is enhanced by great tools, such as the many hands of modern AI-powered workflows that enable us to accomplish more with less effort.&lt;/p&gt;

&lt;p&gt;For frontend engineers, a core metric of their efficiency in replicating designs is how it looks on laptops, tablets, mobile devices, and large monitors: a phenomenon known as responsiveness. To achieve this, we define breakpoints: width thresholds that tell our layouts when to adapt.&lt;/p&gt;

&lt;p&gt;Here's the catch, though: during implementation of a design, browser debugging tools don’t show which breakpoint is currently active. Developers have to cross-check window widths or manually inspect styles, a tiny task that makes each design review and QA cycle longer than necessary. This desire to maximize the efficiency of determining breakpoints sparked the inspiration to build Breakpoint Overlay: a small, yet effective widget that provides real-time responsiveness transparency.&lt;/p&gt;




&lt;h3&gt;
  
  
  From Frustration to Functionality
&lt;/h3&gt;

&lt;p&gt;Once this gap was verified, I started looking for a way to increase productivity without interfering with my workflow. I wanted a tool that would be easy to use and integrate into my current workflow. Upon exploring existing options, it became clear that most required installing an entirely new browser just to work. That felt excessive. Switching tools comes with steep learning curves and uncertain trade-offs, so I aimed for minimal change and maximum impact.&lt;/p&gt;

&lt;p&gt;That realization inspired me to build one myself, not just for me, but for others who care about speed, precision, and simplicity.&lt;br&gt;
Once I had a clearer sense of how the tool should integrate, the next challenge was figuring out what it should feel like. I experimented with modal, sidebar, and persistent panel presentation models, but none of them felt light enough. I eventually settled on a &lt;em&gt;&lt;strong&gt;badge overlay&lt;/strong&gt;&lt;/em&gt;, a tiny, unobtrusive widget that quietly lives on top of your project without altering its flow.&lt;/p&gt;

&lt;p&gt;The badge uses soft, muted colors to stay out of the way visually. In its collapsed state, it shows the &lt;em&gt;&lt;strong&gt;active breakpoint, viewport size, and screen density&lt;/strong&gt;&lt;/em&gt;. When expanded, it reveals a full list of user-defined breakpoints, a compact, focused display that respects the project’s aesthetic while delivering just enough information at a glance.&lt;/p&gt;

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

&lt;p&gt;Once the design direction was set, I outlined functionality that would make it genuinely useful, not just visually informative. A small example is a keyboard shortcut to toggle the overlay’s imperative handlers, allowing developers to show or hide it instantly during workflow.&lt;/p&gt;

&lt;p&gt;After settling on the idea and features, I turned my attention to the implementation specifics, which are what make a tool either a habit or a toy. In any setting, I wanted Breakpoint Overlay to be portable, dependable, and simple to use. A few guiding principles shaped this stage:&lt;/p&gt;

&lt;h4&gt;
  
  
  Core Concepts
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero dependencies&lt;/strong&gt;: Keeping it dependency-free ensures the widget stays lightweight and avoids conflicts within complex build chains.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modularity&lt;/strong&gt;: Each slice of implementation manages a distinct task, creating a unified system that is simple to test and expand.&lt;/li&gt;
&lt;li&gt;Layered testing: To guarantee that its behavior continuously complies with design intent, each significant module has specific test coverage.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Key Technical Decisions
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Resize Event vs. ResizeObserver&lt;/strong&gt;: ResizeObserver does not alert users when the viewport height changes, despite being excellent for tracking content changes. To address this, I used a throttled &lt;code&gt;window.resize&lt;/code&gt; handler, ensuring reliable breakpoint detection without performance loss.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shadow DOM&lt;/strong&gt;: Style and DOM leaks are common when multiple scripts share the same document tree. To avoid unintended collisions and maintain strict encapsulation, the widget renders inside its own Shadow DOM.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;requestAnimationFrame&lt;/strong&gt;: For smooth and efficient updates, the overlay throttles resize computations using &lt;code&gt;requestAnimationFrame&lt;/code&gt;. Older updates are cancelled so the tool always reflects the most recent screen state, a simple but powerful performance win.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these decisions reflects the same philosophy that started the project: efficiency through empathy, both for the developer’s workflow and the product’s integrity.&lt;/p&gt;

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




&lt;h3&gt;
  
  
  Reflections and Learnings
&lt;/h3&gt;

&lt;p&gt;Charting unfamiliar territory always comes with unique challenges. Determining the minimum viable product (MVP) was a persistent problem for Breakpoint Overlay, just like similar projects.&lt;/p&gt;

&lt;p&gt;The idea started simple: track the active breakpoint. But my curiosity got the better of me; I continued to experiment, adding other "cool-to-have" features, reporting container queries, and highlighting overflowing content. New user-experience choices, implementation specifics, and testing considerations arose with every addition. This pursuit for perfection can lead to an unending cycle of development, as was soon discovered.&lt;/p&gt;

&lt;p&gt;Snapping out of that obsession was one of the most important lessons of the project. I discovered how to deliver a minimal version that addressed the correct issue first and to put impact ahead of complexity.&lt;/p&gt;

&lt;p&gt;Beyond scoping features, there were challenges rooted in unfamiliar technologies. Setting up the project as a monorepo, a single repository managing multiple applications and their dependencies, was new to me. While leaving room for upcoming additions like documentation and integration examples, it was crucial for separating the widget's package, demo app, and configuration files.&lt;/p&gt;

&lt;p&gt;These conflicting moments served as stepping stones. Every obstacle revealed a learning gap, and each gap led me back to documentation, community forums, AI research tools, and the open web—a reminder of how collaborative modern development really is.&lt;/p&gt;

&lt;p&gt;Looking ahead, I envision Breakpoint Overlay evolving beyond its current functionality. Consider innovative adapters for popular design systems or a movable widget that can be positioned in any viewport corner. More than features, though, this project taught me that building well is about knowing what really matters and not just about adding more.&lt;/p&gt;

&lt;p&gt;In the end, Breakpoint Overlay became more than a tool. It became a reflection of curiosity, restraint, and the constant pursuit of better ways to build.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FVcDmL4GY%2Fbreakpoint-overflow-in-action.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FVcDmL4GY%2Fbreakpoint-overflow-in-action.gif" alt="Illustration of a developer efficiently managing multiple tasks, symbolizing productivity through better tools" width="720" height="501"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Closing Thought
&lt;/h3&gt;

&lt;p&gt;Every line of code in Breakpoint Overlay carries a lesson about design empathy, deliberate constraint, and the quiet power of developer tools. &lt;/p&gt;

&lt;p&gt;Because sometimes, innovation isn’t about doing more; it’s about making what you already do feel effortless.&lt;/p&gt;

&lt;p&gt;If you’ve ever wished for a simpler way to see which breakpoint your app is using, check out Breakpoint Overlay.&lt;/p&gt;

&lt;p&gt;It’s open source, dependency-free, and available on both &lt;a href="https://github.com/olawalethefirst/breakpoint-overlay" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/breakpoint-overlay" rel="noopener noreferrer"&gt;npm&lt;/a&gt;. Feedback, suggestions, or contributions would be greatly appreciated, especially from engineers who share my passion for the developer experience.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>css</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Role of Cryptography in Secure Digital Communication and Software Development.</title>
      <dc:creator>Olawale Bashiru</dc:creator>
      <pubDate>Sat, 20 May 2023 18:50:20 +0000</pubDate>
      <link>https://dev.to/olawalethefirst/role-of-cryptography-in-secure-digital-communication-and-software-development-4a30</link>
      <guid>https://dev.to/olawalethefirst/role-of-cryptography-in-secure-digital-communication-and-software-development-4a30</guid>
      <description>&lt;p&gt;Ensuring safe digital communication may seem so simple at its core, yet can be the bane of a product's survival in the ever evolving market. This may seem like an overstatement, but when the risks are fully considered, it becomes apparent why so much money and effort is invested to evolve security practices and mitigate new risks as they are discovered. At the core of ensuring safe communication, lies one of the fundamental building block, &lt;em&gt;&lt;strong&gt;Cryptography&lt;/strong&gt;&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Cryptography can simply be defined as the practice of applying techniques to conduct secure data communication in the presence of adversaries. The key principle of cryptography is to ensure &lt;em&gt;&lt;strong&gt;confidentiality&lt;/strong&gt;&lt;/em&gt;, &lt;em&gt;&lt;strong&gt;integrity&lt;/strong&gt;&lt;/em&gt; and &lt;em&gt;&lt;strong&gt;authenticity&lt;/strong&gt;&lt;/em&gt; during communication.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fab63u4b8elcb9jxsr8fh.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fab63u4b8elcb9jxsr8fh.jpeg" alt="Two people ensuring secure communication in the presence of adversaries" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;TLDR: Cryptography is one of the core building blocks for secure communication in software development.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Core principles
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Confidentiality&lt;/strong&gt;: act of concealing data from unauthorised access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authenticity&lt;/strong&gt;: ability to trace data identity back to its origin of creation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrity&lt;/strong&gt;: concept of determining if data has been altered since its creation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Methodologies
&lt;/h2&gt;

&lt;p&gt;There are several techniques upon which security of data is ensured, below is a brief summary of some of this concepts:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hashing&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is a pattern of encoding data in cipher text such that the process is &lt;strong&gt;&lt;em&gt;deterministic&lt;/em&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;em&gt;irreversible&lt;/em&gt;&lt;/strong&gt;, and &lt;strong&gt;&lt;em&gt;collision resistant&lt;/em&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;In simpler terms, this means that no data, plain text for example is redeemable from its encoded cipher text, making it an irreversible process.&lt;/li&gt;
&lt;li&gt;Different cipher texts are formed for any slight change in the value of the plain text, hence deterministic.&lt;/li&gt;
&lt;li&gt;Collision resistant refers to its ability to create a unique cipher value for every plain text &lt;em&gt;&lt;strong&gt;hashed&lt;/strong&gt;&lt;/em&gt;, ensuring that no two plain text have the same cipher text. &lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;The cipher text, also known as &lt;strong&gt;&lt;em&gt;hash&lt;/em&gt;&lt;/strong&gt; is created by unique algorithms that are designed to operate by relying on specific mathematical theories. Examples of such theories are the &lt;strong&gt;&lt;em&gt;discrete logarithmic problem&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;modular arithmetic&lt;/em&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;One application of hashing can be illustrated in &lt;em&gt;&lt;strong&gt;Public Key Cryptography&lt;/strong&gt;&lt;/em&gt;, a pair of related key values that include a public and a private key. The public key is generated from the private through hashing.&lt;/li&gt;
&lt;li&gt;By leveraging on cryptographic hashing, other important techniques have been designed, such as &lt;em&gt;&lt;strong&gt;checksums&lt;/strong&gt;&lt;/em&gt; and &lt;em&gt;&lt;strong&gt;digital signatures&lt;/strong&gt;&lt;/em&gt;. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Checksums&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;These are small values generated from the cryptographic hashing of specific data, typically much larger than the checksum itself.&lt;/li&gt;
&lt;li&gt;The process of generating a checksum is a simple process, aimed at  ascertaining the integrity of data during transmission or storage.&lt;/li&gt;
&lt;li&gt;This is  important because, some of the data may be accidentally misplaced or otherwise corrupted.&lt;/li&gt;
&lt;li&gt;Its simplicity makes computing its integrity easy and efficient to ascertain. &lt;/li&gt;
&lt;li&gt;It is typically used by data storage and transmission systems to enforce efficiency of the process. &lt;/li&gt;
&lt;li&gt;Although they aren't a full proof solution to data security, they are useful for preserving data integrity.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Public Key Cryptography&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is an application of cryptographic hashing that consists of a &lt;em&gt;&lt;strong&gt;Public Key&lt;/strong&gt;&lt;/em&gt;, a &lt;em&gt;&lt;strong&gt;Private Key&lt;/strong&gt;&lt;/em&gt; and a &lt;strong&gt;&lt;em&gt;Signature&lt;/em&gt;&lt;/strong&gt;. &lt;/li&gt;
&lt;li&gt;The public key is a value that serves as a means of public identity for its corresponding secrete private key.&lt;/li&gt;
&lt;li&gt;Private keys are kept secret specifically for the power that it wields. Unauthorised access to a private key enables the possessor to impersonate the actual owner of the key.&lt;/li&gt;
&lt;li&gt;By convention, private keys are generated from randomly generated data to maximise its security. Digitally, this randomness is simulated by relying on algorithms known as &lt;em&gt;&lt;strong&gt;pseudorandom number generators&lt;/strong&gt;&lt;/em&gt;. &lt;/li&gt;
&lt;li&gt;Although private keys can be generated manually, this may compromise its security, hence advised against. &lt;/li&gt;
&lt;li&gt;The private key can be used to form a binding relationship between the Public key pair and a &lt;em&gt;signed&lt;/em&gt; piece of data, producing a corresponding signature. &lt;/li&gt;
&lt;li&gt;Using the public key, the signed data, and the resulting signature, the &lt;em&gt;&lt;strong&gt;authenticity&lt;/strong&gt;&lt;/em&gt; of the signed data can be verified by any third party without accessing the private key.&lt;/li&gt;
&lt;li&gt;This means that the signed piece of information can be verifiably proven to originate from the public key pair without the owner ever disclosing the private key, therefore establishing trust.
&lt;/li&gt;
&lt;li&gt;There are various types of digital signatures, each formed from by unique algorithms. Examples are the Elliptic curve digital signature(ECDSA) and Knorr signature. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Data Encryption&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is a cryptographic technique specifically aimed at enforcing &lt;strong&gt;&lt;em&gt;confidentiality&lt;/em&gt;&lt;/strong&gt; of data. &lt;/li&gt;
&lt;li&gt;It is the process of encrypting or encoding data as cipher text such that it is &lt;em&gt;&lt;strong&gt;confidential&lt;/strong&gt;&lt;/em&gt;, &lt;em&gt;&lt;strong&gt;reversible&lt;/strong&gt;&lt;/em&gt;, yet difficult to decode by unauthorised adversaries.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;This process is not aimed at preventing interference during transmission of data, rather it is designed to ensure intelligibility to any unauthorised interceptor.&lt;/li&gt;
&lt;li&gt;This is achieved by using a secret key during the encoding of the data to secure it.&lt;/li&gt;
&lt;li&gt;There are two forms of commonly used encryption techniques, &lt;em&gt;&lt;strong&gt;Symmetric and Public-key encryption&lt;/strong&gt;&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Symmetric encryption involves the use of the same key to encrypt and decrypt data, hence they’re easier to compute in comparison to Public-key encryption.&lt;/li&gt;
&lt;li&gt;Public-Key encryption, also known as Asymmetric encryption, employs the use of a public key cryptography to encrypt data.&lt;/li&gt;
&lt;li&gt;This is achieved by using a public key to encrypt data, such that only the bearer of its private key can decrypt it. &lt;/li&gt;
&lt;li&gt;Because of this additional layer of separating concern, they offer more security, and as a result require more computing resource than symmetric encryption.&lt;/li&gt;
&lt;li&gt;Ideally, data encryption does not guarantee full proof security from interceptors, but a well encrypted data will require a good amount of both skill and computational resource to decode without the required secret key. &lt;/li&gt;
&lt;li&gt;Authorised decoding of encrypted text with the secret key on the other hand is as easy as cracking a nut, requiring relatively much lesser computational resource. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Practical Applications
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Transport Layer Security (TLS)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is a Cryptographic protocol that ensures security of transit data over networks.&lt;/li&gt;
&lt;li&gt;It operates by providing end to end security of data sent between applications over the internet.&lt;/li&gt;
&lt;li&gt;It leverages the cryptographic encryption of data during transit. &lt;/li&gt;
&lt;li&gt;This encryption includes both Symmetric and Asymmetric types to maximise security. &lt;/li&gt;
&lt;li&gt;A random session key is generated for the transmission session by the client. &lt;/li&gt;
&lt;li&gt;It further uses the server's public key to encrypt it such that the server can only decrypt this session key using its private key, and transmits it to the server.&lt;/li&gt;
&lt;li&gt;Upon receival and decryption of the session key by the server, both participants would bear the session key in their possession.&lt;/li&gt;
&lt;li&gt;Further communication would then be encrypted and decrypted with the session key. &lt;/li&gt;
&lt;li&gt;It is used in applications such as email, VOIP, instant messaging, DNS and web applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Data storage&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The secure storage and transmission of data is one of the most important factors to consider when building software products. &lt;/li&gt;
&lt;li&gt;A “minor” breach of data, either due to unauthorised access or accidental corruption can mar the reputation of any product.&lt;/li&gt;
&lt;li&gt;The detriment of this risk is why software developers apply a combination of techniques to maximise security and ensure integrity. &lt;/li&gt;
&lt;li&gt;An example is in the encryption of data during transit, between a client and its server, rather than leveraging only on network security. This additional measures further reinforces data protection.&lt;/li&gt;
&lt;li&gt;Data hashing prior to storage is another means of storing extremely sensitive information, by reducing risk of exposure upon a breach. This pattern of storing hashes rather than actual data provides an elevated level of security to sensitive data. It is frequently applied in the storing of passwords and credit card information.&lt;/li&gt;
&lt;li&gt;Lastly, Checksums are frequently used to establish the integrity of data at various point during its lifecycle.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;JSON Web Token (JWT)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is a mechanism designed to communicate &lt;em&gt;&lt;strong&gt;authenticity&lt;/strong&gt;&lt;/em&gt; of any entity, such as a user, by ascertaining their identity. &lt;/li&gt;
&lt;li&gt;JWT is a standard for representing claims of ownership in modern applications.&lt;/li&gt;
&lt;li&gt;It provides a secure alternative to storing login credentials such as username and passwords, on servers after initial authorisation, to verify future claims.&lt;/li&gt;
&lt;li&gt;After the user's initial authorisation, a token is generated by the server. &lt;/li&gt;
&lt;li&gt;This token is generated from the claim, such as a user’s credentials and an additional secret, known only to the server. &lt;/li&gt;
&lt;li&gt;The token consists of three integral parts, namely an &lt;strong&gt;&lt;em&gt;header&lt;/em&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;em&gt;payload&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;signature&lt;/em&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The header contains the type of token created and the hashing algorithm used to create the signature.&lt;/li&gt;
&lt;li&gt;The payload contains the claim, such as the identity of the user in this scenario.&lt;/li&gt;
&lt;li&gt;While the signature is the &lt;strong&gt;&lt;em&gt;cryptographic hashing&lt;/em&gt;&lt;/strong&gt; of the &lt;strong&gt;&lt;em&gt;header&lt;/em&gt;&lt;/strong&gt;, &lt;em&gt;&lt;strong&gt;payload&lt;/strong&gt;&lt;/em&gt; and the secret data, known only to the server.&lt;/li&gt;
&lt;li&gt;This token can then passed around back to the requesting client for use.&lt;/li&gt;
&lt;li&gt;Whenever the client requires further access to any protected resource, alongside its request for the resource, it presents the previously received token for authentication. &lt;/li&gt;
&lt;li&gt;Upon receiving this request, the server verifies the authenticity of the token, then grants access if successful. &lt;/li&gt;
&lt;li&gt;JWT introduces better efficiency by removing a round trip, that would have been used by the server to authorise access requests with login credentials. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Decentralised systems&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Thanks to recent boom in popularity of Bitcoin and decentralised systems in general, cryptography has gained massive popularity, prompting many to believe it is a recent innovation.&lt;/li&gt;
&lt;li&gt;Decentralised systems are designed such that they rely heavily on the super powers of cryptography to function.&lt;/li&gt;
&lt;li&gt;This results from the decentralised approach to authority in the system. &lt;/li&gt;
&lt;li&gt;What this means simply is that unlike centralised systems which rely on a central authority for trust, to verify claims, or direct the affairs of the system, participants of most decentralised systems operate at the same level of control, with no participant ranking higher in authority than another.&lt;/li&gt;
&lt;li&gt;This design to decentralise trust by distributing control, also prevents censorship of participation, promotes transparency, maximises both scalability and resillience of the system.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;To enforce trust in a trustless system, cryptography is leveraged, from public key pair identities, to transactions integrity,  authentication of claims, to  network wide state consensus, creation of currency and much more. &lt;/li&gt;
&lt;li&gt;The application of cryptography is evidently the glue that holds the several moving components of decentralised systems, operating efficiently as one.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope that with these few ramblings of mine, I have been able to successfully convince you and not confuse you of the importance of security in digital communication, the role of Cryptography and the need to ensure strict adherence to best security practices during software development. &lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Encryption" rel="noopener noreferrer"&gt;Encryption&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.tutorialspoint.com/cryptography/cryptography_digital_signatures.htm" rel="noopener noreferrer"&gt;Cryptography Digital signatures&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.internetsociety.org/deploy360/tls/basics/" rel="noopener noreferrer"&gt;TLS Basics&lt;/a&gt;&lt;br&gt;
&lt;a href="https://jwt.io" rel="noopener noreferrer"&gt;JW Token&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=7Q17ubqLfaM" rel="noopener noreferrer"&gt;What Is JWT and Why Should You Use JWT&lt;/a&gt;&lt;br&gt;
&lt;a href="https://resources.infosecinstitute.com/topic/how-is-cryptography-used-in-applications/" rel="noopener noreferrer"&gt;How Is Cryptography Used In Applications?&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cryptocurrency</category>
      <category>cybersecurity</category>
      <category>informationsecurity</category>
      <category>security</category>
    </item>
    <item>
      <title>How my obsession drove me to re-engineer a different type of FlatList, I called it "NestedLists".</title>
      <dc:creator>Olawale Bashiru</dc:creator>
      <pubDate>Thu, 20 Oct 2022 09:57:54 +0000</pubDate>
      <link>https://dev.to/olawalethefirst/how-my-obsession-drove-me-to-re-engineer-a-different-type-of-flatlist-i-called-it-nestedlists-2i21</link>
      <guid>https://dev.to/olawalethefirst/how-my-obsession-drove-me-to-re-engineer-a-different-type-of-flatlist-i-called-it-nestedlists-2i21</guid>
      <description>&lt;p&gt;An exercise that started out as an effort to replicate a screen from one of the most used social media applications by leveraging on the React Native framework turned out to be a lot more work than I had originally anticipated. I assumed all I had to do was to slap a few React Native elements together with their appropriate styling and “Tada!”, I could applaud myself for a job well done. Little did I know of the impeding bottleneck patiently awaiting me. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwd913ss58fpekr3asmc6.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwd913ss58fpekr3asmc6.JPG" alt="An old tweet about working on this" width="750" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Eager to complete the necessary work as quickly as I could, I dived right in to constructing a mental model of how the layout should be structured. This is my intuitive approach to implementing designs; I never go wrong with breaking complex designs into fundamental core components needed to achieve desired layout. &lt;/p&gt;

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

&lt;p&gt;I concluded on an approach which required nesting FlatLists. In total, there were four of them. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One grandparent vertical FlatList where the three remaining FlatLists and other necessary components will be nested.
&lt;/li&gt;
&lt;li&gt;One child horizontal FlatList where the remaining two Flatlists will be nested directly in. This enables easy horizontal scrolling between the other nested lists. &lt;/li&gt;
&lt;li&gt;The last two grandchildren FlatLists are vertical lists where the image items are nested directly in.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;I implemented the mockup immediately and the gotcha became obvious. The problem with this approach was that Scrolling of the nested vertical FlatLists’ content was impeded when the pan was initiated directly in the grandparent vertical FlatList region and vice-versa. It became apparent that my traditional approach to implementing the layout was most likely not achievable. I spent hours trying to research ways to circumvent these limitations but every suggestion introduced a certain trade-off in the desired UX.&lt;br&gt;&lt;br&gt;
To provide more context into the desired UX, a scroll in the composite component should be able to pan any available content in the direction to which it is being moved, continuously; regardless of whichever specific FlatList the content was nested directly in.  &lt;/p&gt;

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

&lt;p&gt;Having nested vertical FlatLists with impeded scrolling during content panning was not an acceptable bargain; hence I was prompted to take a not so little detour of building a list that could seamlessly fulfil my layout and UX requirements. &lt;/p&gt;

&lt;h2&gt;
  
  
  NestedLists
&lt;/h2&gt;

&lt;p&gt;Prior to this exercise I had very limited experience using gesture responders. Although I had basic understanding of React Native’s &lt;a href="https://reactnative.dev/docs/gesture-responder-system" rel="noopener noreferrer"&gt;Gesture Responder System&lt;/a&gt;, I had no experience using the more elaborate &lt;a href="https://docs.swmansion.com/react-native-gesture-handler/" rel="noopener noreferrer"&gt;React Native Gesture Handler&lt;/a&gt;. I dived straight into their documentations to get myself armored up to defeat my enemies, I couldn’t afford to be put to shame by mere inanimate objects. 😅 &lt;/p&gt;

&lt;p&gt;One of my first impressions was the vast difference in ease of usage of the &lt;a href="https://docs.swmansion.com/react-native-gesture-handler/" rel="noopener noreferrer"&gt;React Native Gesture Handler&lt;/a&gt; in comparison to React Native’s &lt;a href="https://reactnative.dev/docs/gesture-responder-system" rel="noopener noreferrer"&gt;Gesture Responder System&lt;/a&gt;. One less obvious impression was how &lt;a href="https://docs.swmansion.com/react-native-gesture-handler/" rel="noopener noreferrer"&gt;React Native Gesture Handler’s&lt;/a&gt; seamless integration with &lt;a href="https://docs.swmansion.com/react-native-reanimated/" rel="noopener noreferrer"&gt;React Native Reanimated&lt;/a&gt; transformed fluidity and complexity of animations.  Hence, I concluded on leveraging on the power boost from the duo. Armed to the teeth with weapons of mass destruction, I proceeded on the journey to build NestedLists. 😂 &lt;/p&gt;

&lt;p&gt;NestedLists Features &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Its layout is structured to have two regions, a header region where the “grandparent FlatList” content (a.k.a NestedLists header) is rendered and a nested lists region where the “grandchildren FlatLists” (a.k.a Nested Lists) are rendered. &lt;/li&gt;
&lt;li&gt;Scrolling between the nested lists is achieved by a horizontal swipe in the nested lists region of the component. 
Panning the entire lists content must complete seamlessly between regions without any restriction in movement.
&lt;/li&gt;
&lt;li&gt;Scrolling to the NestedLists header region from any of the nested lists, scrolls other nested lists to the top of their content. &lt;/li&gt;
&lt;li&gt;Each nested list’s height is solely dependent on the height of its own content &lt;/li&gt;
&lt;li&gt;Refreshable - nested lists content should be refreshable
&lt;/li&gt;
&lt;li&gt;Dynamic content loading – nested lists should be able to load more content upon scroll to end. &lt;/li&gt;
&lt;li&gt;Scalable - NestedLists should exhibit features specified above efficiently regardless of the number of nested lists. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using &lt;a href="https://docs.swmansion.com/react-native-reanimated/" rel="noopener noreferrer"&gt;React Native Reanimated&lt;/a&gt; and &lt;a href="https://reactnative.dev/docs/gesture-responder-system" rel="noopener noreferrer"&gt;React Native Gesture Handler&lt;/a&gt;, I created animated values (a.k.a Shared Values) which reacted to gestures and drove the animation of Animated Views during scrolling. The Animated Views contained components of NestedLists and were transformed using their “translateX” and “translateY” style property upon update of their animated values.  &lt;/p&gt;

&lt;p&gt;Using reactive hooks from &lt;a href="https://docs.swmansion.com/react-native-reanimated/" rel="noopener noreferrer"&gt;React Native Reanimated&lt;/a&gt; such as “useAnimatedReaction” and “useDerivedValue”, I updated animated values when conditions for their update were met. These conditional updates were key to ensuring the desired UX was achievable. &lt;/p&gt;

&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;To test the performance of NestedLists, I completed my implementation of Instagram’s profile screen and checked if it fulfilled the requirements it was built for. My observations were: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It loads more content dynamically by triggering the “onEndReached” prop provided to it when it reaches towards the end of the list.
&lt;/li&gt;
&lt;li&gt;It calls the “onRefresh” prop provided to the list, refreshing the active nested list’s content upon trigger.
&lt;/li&gt;
&lt;li&gt;It has as an optional nested lists sticky header which remain visible at the top of the nested lists, when the NestedLists Header have been panned out of view.&lt;/li&gt;
&lt;li&gt;It provides an optional nested lists footer which can be used to indicate loading of more content when necessary. &lt;/li&gt;
&lt;li&gt;It also fulfilled the desired layout and UX requirements earlier stated.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also wondered how performant it functioned so I tracked the JS and UI thread FPS ratings of the Instagram profile screen implementation, using the Expo Go App on an iPhone 7 (to test on low-end devices). I monitored its ratings while the app actively performed operations such as fetching data from remote sources, storing or manipulation of data and rendering of components. Its performance rating on the UI thread was consistently within 60 FPS, the lowest it dropped to after initial mount was 57 FPS. The JS thread was however inconsistent in its ratings. During basic actions such as scrolling through the list content, it consistently reported a rating around 60FPS. The rating however dropped to as low as 30 FPS during rendering of content, manipulation of data, navigation and other JS thread related activities. I was however unable to get any conclusive evidence that indicates the performance lag was indeed caused by the NestedLists implementation. &lt;/p&gt;

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

&lt;p&gt;One other major limitation that flawed NestedLists is its lack of virtualization. Virtualization is an important feature of a performant list as it optimizes resources to maximize performance while rendering list content as necessary. My incomplete understanding of the behind the scenes logic or the optimal approach to designing such a feature is why I ignored it during the implementation of NestedLists. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I enjoyed every bit of trying to recreate one of React Native’s core components as it helped enhance my understanding of how React Native is able to wield the wonderful weapon of deploying applications for multiple platforms without breaking a sweat, well, maybe just a little, okay a lot of sweat 💀. The purpose of this writeup is to open myself to feedback, I am curious about what fellow React Native warriors think about my implementation. Was this a pointless venture with rewards that could have been sowed through less excruciating means? Should I even be trying to reinvent the wheels?  &lt;/p&gt;

&lt;p&gt;I have &lt;a href="https://github.com/olawalethefirst/instagram-profile-implementation" rel="noopener noreferrer"&gt;linked&lt;/a&gt; the repo to my Instagram profile screen implementation, it includes the source code for NestedLists.  &lt;/p&gt;

&lt;p&gt;Please comment your feedback on what or how I could have done better.  &lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>javascript</category>
      <category>react</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
