<?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: Robrecht Meersman</title>
    <description>The latest articles on DEV Community by Robrecht Meersman (@robrechtme).</description>
    <link>https://dev.to/robrechtme</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%2F817494%2F3bd499d5-b2e2-4506-a914-6df4539519a3.png</url>
      <title>DEV Community: Robrecht Meersman</title>
      <link>https://dev.to/robrechtme</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/robrechtme"/>
    <language>en</language>
    <item>
      <title>React Native is here to stay</title>
      <dc:creator>Robrecht Meersman</dc:creator>
      <pubDate>Tue, 09 Apr 2024 09:42:48 +0000</pubDate>
      <link>https://dev.to/inthepocket/react-native-is-here-to-stay-43n7</link>
      <guid>https://dev.to/inthepocket/react-native-is-here-to-stay-43n7</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post originally appeared on our &lt;a href="https://www.inthepocket.com/blog/react-native-is-here-to-stay" rel="noopener noreferrer"&gt;ITP website&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;React Native is one of many cross-platform frameworks aiming to bridge the gap between iOS and Android app development. However, React Native is not like any other cross-platform framework. With a growing number of top-ranking apps built using React Native and the backing of major companies, it's clear that this framework is not just a passing trend but a &lt;strong&gt;significant player in the mobile development landscape&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you’re not already sold, this article should convince you to embrace React Native and show you how we utilise it at In The Pocket to create top-notch mobile experiences.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(For clarity: this article is NOT sponsored by React Native 🥲)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Built on solid ecosystems
&lt;/h2&gt;

&lt;p&gt;React Native builds upon solid foundations: &lt;strong&gt;JavaScript&lt;/strong&gt; and &lt;strong&gt;React&lt;/strong&gt;. Foundations many developers are skilled in and that have big and active communities. The "Learn once, write anywhere" slogan of React Native really holds true, empowering developers to utilise their existing coding skills to write code for both iOS and Android platforms with minimal learning curve.&lt;/p&gt;

&lt;p&gt;Apart from leveraging these foundations, React Native still retains the ability to &lt;strong&gt;fully access and utilise the native capabilities&lt;/strong&gt; of the underlying iOS and Android platforms. This means that developers can tap into the performance and accessibility functionalities of the devices seamlessly, without compromise, even though they're primarily working with JavaScript and React.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F37x40rd54fpo3mzoe82f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F37x40rd54fpo3mzoe82f.png" alt="React Native, a simple schematic overview"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Backed by big companies
&lt;/h2&gt;

&lt;p&gt;The open source landscape can be the Wild West, often relying on the goodwill of solo developers who can pull the plug at anytime. React Native distinguishes itself with &lt;strong&gt;backing from major players like Meta, Microsoft, and Shopify&lt;/strong&gt;. Their active involvement ensures the continuous growth and improvement of React Native. Moreover, companies such as Software Mansion and Callstack contribute valuable libraries and host yearly conferences, enlarging the community.&lt;/p&gt;

&lt;p&gt;Another big asset is &lt;strong&gt;Expo, a major player in simplifying React Native development&lt;/strong&gt; with a suite of tools and services. By getting rid of native complexities, Expo allows developers to focus on building features rather than dealing with technical cross-platform intricacies. Through open-source libraries and tools, Expo streamlines development.&lt;/p&gt;

&lt;p&gt;Next to that, Expo Application Services (EAS) is a cloud-based solution for building, signing, distributing, and updating apps, reducing setup time and continuous integration workflows. And &lt;strong&gt;Expo Updates&lt;/strong&gt;, a feature of EAS, enables &lt;strong&gt;over-the-air updates&lt;/strong&gt;, ensuring users have access to the latest features and bug fixes, facilitating rapid app iteration and improvement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bright future ahead
&lt;/h2&gt;

&lt;p&gt;The future of React Native looks promising, as the React Native team plans a significant overhaul of its core internals, called the &lt;strong&gt;New Architecture&lt;/strong&gt;, aimed at improving its performance and scalability. Additionally, &lt;strong&gt;Expo&lt;/strong&gt; continues to evolve, enhancing developer experience with new features and keeping an exciting roadmap.&lt;/p&gt;

&lt;p&gt;Expo promises to release an update to their SDK each quarter, so apps will always be able to target the latest iOS and Android versions. These advancements make it easier than ever to build, deploy, and manage React Native applications, ensuring the framework remains at the forefront of mobile development.&lt;/p&gt;

&lt;h2&gt;
  
  
  React Native in practice
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Izimi mobile app
&lt;/h3&gt;

&lt;p&gt;At In The Pocket, React Native has enabled us to create robust and future-proof applications like the &lt;strong&gt;&lt;a href="https://www.inthepocket.com/work/izimi" rel="noopener noreferrer"&gt;Izimi&lt;/a&gt; mobile app&lt;/strong&gt;: a sturdy and future-proof digital vault, also available as a web portal. Harnessing React Native's native capabilities and seamlessly integrating Itsme e-ID authentication, Izimi ensures a secure and user-friendly authentication experience. By sharing JavaScript code between web and app, we've accelerated our development process while minimising code duplication.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffvolcc1sphkebkrz6tfv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffvolcc1sphkebkrz6tfv.png" alt="The Izimi vault: Built with React Native"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Multipharma app
&lt;/h3&gt;

&lt;p&gt;For &lt;strong&gt;&lt;a href="https://www.inthepocket.com/work/multipharma" rel="noopener noreferrer"&gt;Multipharma&lt;/a&gt;&lt;/strong&gt;, React Native facilitated the rapid development of a new mobile app in just five months. The same developers could work on the mobile app and web portal, keeping feature parity high. Because React Native is &lt;em&gt;just native&lt;/em&gt;, we could leverage on-device security measures like biometrics and encryption, ensuring end-to-end application security.&lt;/p&gt;

&lt;h3&gt;
  
  
  Colruyt Xtra app
&lt;/h3&gt;

&lt;p&gt;These security features also play a role in the &lt;strong&gt;&lt;a href="https://www.inthepocket.com/work/xtra" rel="noopener noreferrer"&gt;Xtra&lt;/a&gt; app&lt;/strong&gt; we help develop for Colruyt Group. Native integrations allow the user to use biometrics to securely pay your groceries right from the app. Thanks to the large open source community, these native integrations often already exist, helping us gain speed by not reinventing the wheel. The modularity of React allows us to collaborate with multiple &lt;em&gt;feature teams&lt;/em&gt; in parallel while maintaining a consistent look and feel through the use of a centralised design system. The design system used in Xtra enforces accessibility by default, and using TypeScript strengthens the ability to ensure accessibility in the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  React Native at In The Pocket
&lt;/h3&gt;

&lt;p&gt;At In The Pocket we’ve had React Native on our &lt;a href="https://tech.inthepocket.com/?domains=mobile" rel="noopener noreferrer"&gt;tech radar&lt;/a&gt; since its early stages and we have seen it grow and mature. We have seen that React Native can create just as high-quality, performant, innovative apps as native ones. At In The Pocket, &lt;strong&gt;we fully embrace React Native&lt;/strong&gt; and we are actively contributing to its open source landscape. We adopt Expo's ecosystem to accelerate our development even further.&lt;/p&gt;

&lt;p&gt;We're excited to see how React Native continues to evolve and how it will shape the future of mobile development. As we continue to build and innovate, one thing remains clear—React Native is not just here to stay but to lead the way in mobile development.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>expo</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>From Figma to React Native using Specify</title>
      <dc:creator>Robrecht Meersman</dc:creator>
      <pubDate>Fri, 11 Mar 2022 14:20:19 +0000</pubDate>
      <link>https://dev.to/inthepocket/from-figma-to-react-native-using-specify-2ogd</link>
      <guid>https://dev.to/inthepocket/from-figma-to-react-native-using-specify-2ogd</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post originally appeared on our &lt;a href="https://inthepocket.dev/posts/2021-10-14-figma-to-react-native/" rel="noopener noreferrer"&gt;ITP Dev blog&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We all know the benefit of &lt;strong&gt;design systems&lt;/strong&gt;. As a designer we want to have a consistent UI over web, mobile and any other platform the brand is present. As a developer we do not want to spend time exporting assets and colors from Figma, importing them into the code and repeating this process every time something changes.&lt;/p&gt;

&lt;p&gt;Luckily there exists a tool to automate this process. &lt;a href="https://specifyapp.com" rel="noopener noreferrer"&gt;Specify&lt;/a&gt; is a cloud platform which stores a &lt;strong&gt;single source of truth&lt;/strong&gt; for your design tokens (text styles, colors, icons, imagery, etc.) and distributes them to the different platforms. Specify allows you to &lt;strong&gt;import&lt;/strong&gt; your tokens from a source like Figma (and soon other sources like Google Drive or Dropbox) and keep them in sync while you make changes to the source. You can view the tokens in the web app and export them to GitHub or to your project using the &lt;a href="https://specifyapp.com/developers/cli" rel="noopener noreferrer"&gt;CLI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this blogpost we will focus on syncing the design tokens from Figma to React Native.&lt;/p&gt;

&lt;h2&gt;
  
  
  Figma to Specify
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fveyeqikgcdzyi3a8ahrz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fveyeqikgcdzyi3a8ahrz.png" alt="Screenshot of the Specify dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Syncing design tokens from Figma to Specify is just a matter of clicking a few buttons. The Specify team has written a clear &lt;a href="https://help.specifyapp.com/en/articles/4722449-figma-integration" rel="noopener noreferrer"&gt;guide&lt;/a&gt; on how to set it up, and Specify will automatically sync any new changes made to the Figma file.&lt;br&gt;
I recommend taking a look at the &lt;a href="https://www.figma.com/file/ilwc27dKXPt3QTGORsVZwl/Specify-%C2%B7-File-Example?node-id=0%3A1&amp;amp;viewport=25%2C361%2C0.3232876658439636" rel="noopener noreferrer"&gt;example Figma file&lt;/a&gt; to see how each design token should be delivered.&lt;/p&gt;
&lt;h2&gt;
  
  
  Specify to React Native
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy1rjuko46h328ie1uiti.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy1rjuko46h328ie1uiti.png" alt="Illustration of a flow going from the Specify logo to the React Native Logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To pull design tokens into a project, Specify offers a &lt;a href="https://specifyapp.com/developers/cli" rel="noopener noreferrer"&gt;CLI&lt;/a&gt; with a &lt;code&gt;pull&lt;/code&gt; and &lt;code&gt;sync&lt;/code&gt; command. The &lt;code&gt;pull&lt;/code&gt; command will import all design tokens, where the &lt;code&gt;sync&lt;/code&gt; command will only update the ones that are already present.&lt;br&gt;
The CLI uses a &lt;code&gt;.specifyrc&lt;/code&gt; config file (JS or JSON) in which you can write &lt;strong&gt;rules&lt;/strong&gt;, which are different jobs to run in parallel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// .specifyrc.js&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@my_organization/my-repository&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;personalAccessToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my_personal_access_token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;// different jobs in parallel&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For each rule we can use a different &lt;strong&gt;filter&lt;/strong&gt;, such that the rule only applies to certain types of design tokens. Next to filters, we can also use &lt;strong&gt;parsers&lt;/strong&gt;, which will manipulate the raw design tokens (which are in JSON format) and output a format that suits the programming language and platform more. Parsers behave like a pipeline, where each parser receives the input of the previous one. There are a lot of &lt;a href="https://github.com/Specifyapp/parsers/tree/master/parsers" rel="noopener noreferrer"&gt;parsers&lt;/a&gt; to choose from, some perform very low level transformations such as &lt;a href="https://github.com/Specifyapp/parsers/tree/master/parsers/round-number" rel="noopener noreferrer"&gt;round-number&lt;/a&gt; and &lt;a href="https://github.com/Specifyapp/parsers/tree/master/parsers/camelcasify" rel="noopener noreferrer"&gt;camelcasify&lt;/a&gt;, but also full-blown parsers to a single technology such as &lt;a href="https://github.com/Specifyapp/parsers/tree/master/parsers/to-tailwind" rel="noopener noreferrer"&gt;to-tailwind&lt;/a&gt; and &lt;a href="https://github.com/Specifyapp/parsers/tree/master/parsers/to-react-native" rel="noopener noreferrer"&gt;to-react-native&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Downloading fonts &amp;amp; assets
&lt;/h3&gt;

&lt;p&gt;If we filter on assets (&lt;code&gt;'vector'&lt;/code&gt;, &lt;code&gt;'bitmap'&lt;/code&gt; and &lt;code&gt;'font'&lt;/code&gt;), Specify will download the assets themselves instead of the JSON describing them. They will be placed under the given folder (here &lt;code&gt;src/common/assets&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;For SVG's, we can use the &lt;a href="https://github.com/svg/svgo" rel="noopener noreferrer"&gt;&lt;code&gt;svgo&lt;/code&gt;&lt;/a&gt; parser, which optimizes the SVG code and outputs a minified result. The default &lt;code&gt;svgo&lt;/code&gt; settings are pretty good, but we add &lt;code&gt;removeDimensions&lt;/code&gt; to make them responsive and replace the hard coded colors with &lt;code&gt;"currentColor"&lt;/code&gt; such that we can color them with React Native styles.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// .specifyrc.js&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="nx"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🖊 Download Vector Assets&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src/common/assets/vector&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vector&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;parsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;camelcasify&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;svgo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;svgo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;removeDimensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;convertColors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;currentColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
              &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🏞 Download Bitmap Assets&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src/common/assets/bitmap&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bitmap&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;parsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;camelcasify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;// This parser will give @2x and @3x variants their correct file name&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name-assets-files-by-pattern&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{{name}}{{#dimension}}@{{dimension}}x{{/dimension}}.{{format}}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🔡 Download Fonts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src/common/assets/fonts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;font&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Syncing desing tokens
&lt;/h3&gt;

&lt;p&gt;Now that assets and fonts are downloaded, we are ready to import the rest of the design system. For this we will use the &lt;a href="https://github.com/Specifyapp/parsers/tree/master/parsers/to-react-native" rel="noopener noreferrer"&gt;&lt;code&gt;to-react-native&lt;/code&gt;&lt;/a&gt; parser. It will generate a JavaScript (or TypeScript) &lt;code&gt;theme&lt;/code&gt; object with all the design tokens in the correct format for React Native to understand.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// .specifyrc.js&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;⚛️ Import tokens&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/common/theme/theme.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;parsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;to-react-native&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;assetsFolderPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;bitmap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/common/assets/bitmap&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;vector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/common/assets/vector&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If you have questions or notice any issues with the &lt;code&gt;to-react-native&lt;/code&gt; parser, feel free to &lt;a href="https://github.com/Specifyapp/parsers" rel="noopener noreferrer"&gt;contribute&lt;/a&gt; or talk to me about it 🙏&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An example of a full &lt;code&gt;.specifyrc.js&lt;/code&gt; file can be found &lt;a href="https://gist.github.com/robrechtme/453f3c3e5ddf1e222417ae3e99faedcd" rel="noopener noreferrer"&gt;here&lt;/a&gt;. The output file will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/common/theme/theme.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;assetChevronRight&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../assets/vector/chevronRight.svg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;assetLogo&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../assets/bitmap/logo.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;bitmap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;logo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;assetLogo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;vector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;chevronRight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;assetChevronRight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;textStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;fontWeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;500&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;lineHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;fontFamily&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Montserrat-Medium&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rgb(0, 0, 0)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;measurement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;primary500&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rgb(0, 0, 153)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;gradient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;sunset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rgb(245, 72, 63)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rgb(255, 142, 5)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;locations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;dimmed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;font&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;montserratMedium&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Montserrat-Medium&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a final step we will add an npm script in our &lt;code&gt;package.json&lt;/code&gt;:&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.json&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&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="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"specify:pull"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"specify pull -C .specifyrc.js"&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="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have our Figma project synced with React Native 🎉. Every time the designer changes a color or adds an icon, we can run &lt;code&gt;npm run specify:pull&lt;/code&gt; and see the changes in our app!&lt;/p&gt;

&lt;h3&gt;
  
  
  Using the theme object
&lt;/h3&gt;

&lt;p&gt;Making use of the design tokens is fairly straighforward for most types.&lt;/p&gt;

&lt;h4&gt;
  
  
  Bitmaps
&lt;/h4&gt;

&lt;p&gt;Simple as that!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&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;Image&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="s1"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;common/theme&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Image&lt;/span&gt; &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bitmap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Vectors
&lt;/h4&gt;

&lt;p&gt;All vector assets in &lt;code&gt;theme.js&lt;/code&gt; are imported directly. If you are not using Expo, you will need to install and configure &lt;a href="https://github.com/kristerkari/react-native-svg-transformer" rel="noopener noreferrer"&gt;&lt;code&gt;react-native-svg-transformer&lt;/code&gt;&lt;/a&gt; to resolve the import statements.&lt;/p&gt;

&lt;p&gt;Unlike bitmaps, the imported assets are React elements. We create a &lt;code&gt;Vector&lt;/code&gt; component to make the usage look more like regular images:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Vector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SVGElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SVGElement&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&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="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* a bit weird */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;vector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nt"&gt;chevronRight&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* much better! */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Vector&lt;/span&gt; &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chevronRight&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Fonts
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;This part is specific to non-Expo projects. For Expo apps, it could be different.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the "Download Fonts" rule above, the downloaded &lt;code&gt;.ttf&lt;/code&gt; files will be under &lt;code&gt;src/common/assets/fonts/&lt;/code&gt;, but they should also be imported in the native projects as well. This can be done by creating a &lt;code&gt;react-native.config.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// react-native.config.js&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;ios&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="na"&gt;android&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;assets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/common/assets/fonts/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Optionally.&lt;/span&gt;
    &lt;span class="c1"&gt;// Prevent `react-native-vector-icons`&lt;/span&gt;
    &lt;span class="c1"&gt;// from linking all fonts&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native-vector-icons&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;assets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;react-native link&lt;/code&gt; will link all fonts under that path automatically to the Android and iOS project! We can run it after every specify pull job:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;// package.json
  "scripts": {
    ...
&lt;span class="gd"&gt;-    "specify:pull": "specify pull -C .specifyrc.js",
&lt;/span&gt;&lt;span class="gi"&gt;+    "specify:pull": "specify pull -C .specifyrc.js &amp;amp;&amp;amp; react-native link",
&lt;/span&gt;  },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Gradients
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;to-react-native&lt;/code&gt; parser transforms gradients into a format which is easy to use with &lt;a href="https://github.com/react-native-linear-gradient/react-native-linear-gradient" rel="noopener noreferrer"&gt;react-native-linear-gradient&lt;/a&gt;.&lt;br&gt;
Example usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;LinearGradient&lt;/span&gt;
    &lt;span class="na"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gradients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myGradient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;locations&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gradients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myGradient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locations&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;useAngle&lt;/span&gt;
    &lt;span class="na"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gradients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myGradient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;angle&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Specify is a young but promising tool to sync Figma files to all you different platforms. If you feel like there is a parser missing or want to add some options, feel free to &lt;a href="https://github.com/Specifyapp/parsers" rel="noopener noreferrer"&gt;contribute&lt;/a&gt; to the project. The Specify team is very responsive and is open to suggestions.&lt;/p&gt;

</description>
      <category>design</category>
      <category>reactnative</category>
      <category>figma</category>
    </item>
    <item>
      <title>Dynamic Open Graph images with Next.js</title>
      <dc:creator>Robrecht Meersman</dc:creator>
      <pubDate>Thu, 10 Mar 2022 13:10:07 +0000</pubDate>
      <link>https://dev.to/inthepocket/dynamic-open-graph-images-with-nextjs-jg7</link>
      <guid>https://dev.to/inthepocket/dynamic-open-graph-images-with-nextjs-jg7</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update 2022-10&lt;/strong&gt;: Vercel release a new &lt;a href="https://vercel.com/blog/introducing-vercel-og-image-generation-fast-dynamic-social-card-images" rel="noopener noreferrer"&gt;OG Image Generation&lt;/a&gt; library, which does the same thing except 5x faster and at the edge! &lt;/p&gt;
&lt;/blockquote&gt;




&lt;blockquote&gt;
&lt;p&gt;This post originally appeared on our &lt;a href="https://inthepocket.dev/posts/2022-03-08-dynamic-open-graph-images/" rel="noopener noreferrer"&gt;ITP Dev blog&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Let me start of with a question: which link are you more likely to click on, the left or the right?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fooxhr357x1uwc9btl6hg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fooxhr357x1uwc9btl6hg.png" alt="Twitter posts side by side"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Obviously, adding a social media preview image is an great way to improve the professional look of your website and increase your click through rate (though I have no data on this). These social media images are specified using the &lt;strong&gt;&lt;a href="https://ogp.me/" rel="noopener noreferrer"&gt;Open Graph Protocol&lt;/a&gt;&lt;/strong&gt;, which is a spec introduced by Facebook and now supported by any software that previews URLs for you. The OG image is specified in the document's head:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"https://url-to-your-image.png"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can be hooked up to a CMS so editors can choose a picture which suits their landing page, blog post, news article… the most. It is important that &lt;strong&gt;the preview gives the user a clear idea of what to expect&lt;/strong&gt; on the webpage, similar to a thumbnail on a YouTube video.&lt;/p&gt;

&lt;p&gt;But what if the content of the page is not visual at all, and no photo really suits the contents of the page? And what if we have a lot of these pages, with &lt;strong&gt;dynamically generated content&lt;/strong&gt;? Luckily we are not limited to photography, we can use text! The prime example of this is how GitHub generates previews for issue URLs: they generate an image containing enough info such that users know what they will click on. These images are &lt;strong&gt;generated on-demand&lt;/strong&gt;, as storing an image for every GitHub pull request or issue would be unfeasable. Another example is Vercel, which even open sourced their &lt;a href="https://github.com/vercel/og-image" rel="noopener noreferrer"&gt;Open Graph Image as a Service&lt;/a&gt; that they occasionally use on blog posts or announcements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftlxv3i4mbrtenr6ywmaj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftlxv3i4mbrtenr6ywmaj.jpg" alt="GitHub issue example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article we will find out how we can create these dynamic Open Graph images in Next.js. We will use our In The Pocket &lt;a href="https://inthepocket.tech" rel="noopener noreferrer"&gt;Tech Radar&lt;/a&gt; as an example. Our Tech Radar reflects &lt;strong&gt;our current view on software engineering technologies&lt;/strong&gt;. It includes the technology choices we’ve made and motivates why we’ve made them. It also shows which technologies are “on our radar”, and why we consider adopting them.&lt;br&gt;&lt;br&gt;
Each technology has its own webpage, and we have more than 100 technologies on our radar. Manually creating an OG image for each technology would be a boring, repeating task.&lt;/p&gt;
&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Don't care about the details? Here's a small tutorial on how to add an API route to your Next.js app that generates the images on demand.&lt;/p&gt;

&lt;p&gt;First, install &lt;a href="https://github.com/neg4n/next-api-og-image" rel="noopener noreferrer"&gt;&lt;code&gt;next-api-og-image&lt;/code&gt;&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add next-api-og-image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then configure an API route&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/api/og-image.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;withOGImage&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="s1"&gt;next-api-og-image&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;QueryParams&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;withOGImage&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;QueryParams&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                                &lt;span class="c1"&gt;// include HTML template here&lt;/span&gt;
    &lt;span class="na"&gt;html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stage&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="s2"&gt;`&amp;lt;h1&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; - &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/h1&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;cacheControl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public, max-age=604800, immutable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;dev&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;inspectHtml&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And call the route from the web page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/technology/[slug].ts&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Next.js | Tech Radar&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; 
    &lt;span class="na"&gt;property&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"og:image"&lt;/span&gt; 
    &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://inthepocket.tech/api/og-image?name=Next.js&amp;amp;stage=adopt"&lt;/span&gt; 
  &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and done!&lt;/p&gt;

&lt;h2&gt;
  
  
  Behind the scenes
&lt;/h2&gt;

&lt;p&gt;As you see in the code above, we are using the &lt;a href="https://github.com/neg4n/next-api-og-image" rel="noopener noreferrer"&gt;&lt;code&gt;next-api-og-image&lt;/code&gt;&lt;/a&gt; library with almost no configuration required to generate the images. Super easy! The interesting part however is &lt;strong&gt;what the library does under the hood&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;withOGImage&lt;/code&gt; method exposes a &lt;code&gt;GET /api/og-image?name=Next.js&amp;amp;stage=adopt&lt;/code&gt; API route with some query parameters we can define ourselves. In the case of our Tech Radar, we use the &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;stage&lt;/code&gt; parameters. The API route returns an image containing the name and stage we provided:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvqet954s1srffybd8xjy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvqet954s1srffybd8xjy.png" alt="Tech Radar Open Graph image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When requesting the API route, the Next.js serverless function will actually spin up a &lt;strong&gt;web browser on the server&lt;/strong&gt; (a headless instance of Chromium, using &lt;a href="https://github.com/alixaxel/chrome-aws-lambda" rel="noopener noreferrer"&gt;&lt;code&gt;chrome-aws-lambda&lt;/code&gt;&lt;/a&gt;). Next, a webpage will be generated with HTML we can define ourselves. This HTML will be used to construct the image. That means that as a developer we can generate images using HTML and CSS, technologies we are already familiar with!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;  &lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stage&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="s2"&gt;`&amp;lt;h1&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; - &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/h1&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course we are not limited to a simple &lt;code&gt;h1&lt;/code&gt; tag, this can be a full HTML document with styles, images and custom fonts.  &lt;/p&gt;

&lt;p&gt;Finally, a &lt;strong&gt;screenshot of the webpage&lt;/strong&gt; is taken using &lt;a href="https://github.com/puppeteer/puppeteer" rel="noopener noreferrer"&gt;&lt;code&gt;puppeteer&lt;/code&gt;&lt;/a&gt; and sent to the client-side.&lt;/p&gt;

&lt;p&gt;We add some aggressive &lt;strong&gt;caching&lt;/strong&gt; (&lt;code&gt;public, max-age=604800, immutable&lt;/code&gt;) to prevent generating the same image too many times, because the image generation is quite slow and computationally intensive. The way we set up caching is also the reason we pass the query parameters and not just the technology's ID. You might think it is cleaner to fetch the technology's stage and name from the CMS inside the API route, but this makes caching more tricky. By adding all variable elements as query parameters, one URL will always return the same image and we can use the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#immutable" rel="noopener noreferrer"&gt;immutable&lt;/a&gt; setting on the caching. If the stage or the name of a technology would change on the Tech Radar, we will update the URL, and not update the image behind the URL.&lt;/p&gt;

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

&lt;p&gt;Adding dynamic Open Graph images in Next.js is very low effort, but makes your site feel 10x more professional!&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
