<?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>Forem: Ayobami Adejumo</title>
    <description>The latest articles on Forem by Ayobami Adejumo (@aayostem).</description>
    <link>https://forem.com/aayostem</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%2F957468%2Fa4e029ec-7612-4da9-9d62-0dfc535583b4.png</url>
      <title>Forem: Ayobami Adejumo</title>
      <link>https://forem.com/aayostem</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/aayostem"/>
    <language>en</language>
    <item>
      <title>I audited 12 startup stacks in 90 days. Here is what breaks before 1,000 users every single time.</title>
      <dc:creator>Ayobami Adejumo</dc:creator>
      <pubDate>Thu, 09 Apr 2026 23:01:15 +0000</pubDate>
      <link>https://forem.com/aayostem/i-audited-12-startup-stacks-in-90-days-here-is-what-breaks-before-1000-users-every-single-time-3095</link>
      <guid>https://forem.com/aayostem/i-audited-12-startup-stacks-in-90-days-here-is-what-breaks-before-1000-users-every-single-time-3095</guid>
      <description>&lt;p&gt;The thing that breaks before 1,000 users is almost never the code.&lt;/p&gt;

&lt;p&gt;Not a race condition. Not a memory leak. Not a missing index. Founders assume their app will collapse because of a bug they could have caught in PR review. Engineers assume they'll get paged for a logic error at 2am. Neither is true.&lt;/p&gt;

&lt;p&gt;In twelve startup audits, the first failure was always an infrastructure primitive. A limit someone didn't know existed. An environment that didn't exist at all. A default that worked perfectly at 50 users and silently died at 500.&lt;/p&gt;

&lt;p&gt;The first thing I check on any stack is the Supabase project plan. If it is on the free tier with more than 20 active users, the connection pool is already at 60% capacity. Most founders have no idea. They only find out when &lt;code&gt;PGRST 104&lt;/code&gt; appears in their logs at 3pm on a Tuesday — right when their biggest customer is running a demo.&lt;/p&gt;

&lt;p&gt;That error message means "too many clients already." Not "your query is slow." Not "your code is wrong." Just: you hit a number you didn't know existed. That is what breaks before 1,000 users. Every single time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Failure pattern 1 — The Supabase free tier connection cliff
&lt;/h2&gt;

&lt;p&gt;You have 47 active users. Your Product Hunt launch is in 4 hours. Everything worked on staging. Then your Sentry dashboard turns red.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;remaining connection slots are reserved for non-replication superuser connections&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is not a database crash. It is a configuration limit. Supabase free tier allows 60 direct connections. At 50 concurrent users — each holding a connection open while they browse, type, or leave a tab in the background — the pool is exhausted. Request 61 gets that error. Every user after that sees a 500 response.&lt;/p&gt;

&lt;p&gt;Here is why you never saw this coming. Your local development environment had one user: you. Your staging environment had three test accounts. You never simulated 50 concurrent connections because that requires 50 concurrent humans, not 50 automated requests.&lt;/p&gt;

&lt;p&gt;I have seen this exact failure at 3pm on a Tuesday. At 11am on a Monday. And once at 8:47am on the morning of a Product Hunt launch. Two hundred people clicked through. The first ten saw the site. The next 190 saw &lt;code&gt;remaining connection slots are reserved&lt;/code&gt; — an error message that means nothing to a non-technical user except "this product is broken." The launch slot passed. There is no second first impression.&lt;/p&gt;

&lt;p&gt;The fix takes four minutes once you know what it is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enable pgBouncer in the Supabase dashboard (Settings → Database → Connection pooler)&lt;/li&gt;
&lt;li&gt;Change your connection string from port &lt;code&gt;5432&lt;/code&gt; to port &lt;code&gt;6543&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Deploy&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That is it. The same free tier now handles 200 concurrent connections instead of 60. No code change. No migration. No additional cost.&lt;/p&gt;




&lt;h2&gt;
  
  
  Failure pattern 2 — No staging environment
&lt;/h2&gt;

&lt;p&gt;Without staging, every code change is tested on real users. Every deploy is a gamble. The developer pushes a change that works on their laptop and breaks in production because of one difference they could not see.&lt;/p&gt;

&lt;p&gt;Here is exactly how that happens. It is 6:13pm on a Thursday. A developer pushes a one-line fix for a typo on the pricing page. The fix works locally. They run &lt;code&gt;git push&lt;/code&gt; and &lt;code&gt;vercel deploy --prod&lt;/code&gt;. The deploy completes in 47 seconds. The typo is fixed.&lt;/p&gt;

&lt;p&gt;But the fix introduced a regression on the payment flow. Why? Because the local environment uses a Stripe test key starting with &lt;code&gt;pk_test_&lt;/code&gt;. Production uses a live key starting with &lt;code&gt;pk_live_&lt;/code&gt;. The developer never tested the payment flow after the change because the change was "just a typo."&lt;/p&gt;

&lt;p&gt;At 9:04pm, a user emails: "Your checkout page gives me an error after I enter my card." At 9:12pm, a second user reports the same thing. At 9:23pm, the founder checks Stripe dashboard. Zero successful charges in the last three hours. Three hours of revenue lost. Twelve customers abandoned.&lt;/p&gt;

&lt;p&gt;The developer now has to roll back manually. There is no automated rollback process. They run &lt;code&gt;git revert HEAD&lt;/code&gt;, wait for the CI pipeline, manually verify the typo is back but the payment flow works, and redeploy. Total time: 47 minutes.&lt;/p&gt;

&lt;p&gt;Here is what a correct staging environment looks like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Same infrastructure as production&lt;/li&gt;
&lt;li&gt;Same environment variable structure (different values)&lt;/li&gt;
&lt;li&gt;Same database schema — run &lt;code&gt;pg_dump --schema-only production_database &amp;gt; schema.sql&lt;/code&gt; weekly&lt;/li&gt;
&lt;li&gt;Different data (seeded test accounts, no real emails)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The deployment workflow becomes: &lt;code&gt;git push&lt;/code&gt; → deploy to staging (5 minutes) → run smoke tests (90 seconds) → deploy to production. Three hours of setup once. A 90-second automated check before every deploy. I have seen this gap in nine of twelve startup audits. The answer is always the same: "We meant to set up staging. We just haven't gotten to it yet."&lt;/p&gt;




&lt;h2&gt;
  
  
  Failure pattern 3 — No error monitoring
&lt;/h2&gt;

&lt;p&gt;Here is how a founder discovers a broken feature without error monitoring. A user emails: "Hey, the export button hasn't worked for the last two days. Love the product otherwise." The founder replies: "Thanks for letting us know — we'll look into it immediately."&lt;/p&gt;

&lt;p&gt;What the founder does not know: that user is one in twenty who experienced the problem. The other nineteen left quietly. They did not email. They just stopped using the export feature, assumed the product was unreliable, and started looking for alternatives. By the time the founder knows, the feature has been broken for 47 hours. No one is tracking the revenue impact. No one knows when it started.&lt;/p&gt;

&lt;p&gt;Now compare that to what Sentry tells you within 60 seconds of the first error occurring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The exact line of code: &lt;code&gt;src/components/ExportButton.tsx:47&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The exact error message: &lt;code&gt;TypeError: Cannot read property 'map' of undefined&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The browser and device: &lt;code&gt;Chrome 122 on macOS, 2560x1440&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The user's email address (if logged in)&lt;/li&gt;
&lt;li&gt;How many times the error has occurred: &lt;code&gt;14 times, 9 unique users&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A senior engineer looking at that alert can reproduce and fix most errors within 20 minutes. The same engineer without Sentry spends hours unable to reproduce an intermittent failure.&lt;/p&gt;

&lt;p&gt;Here is the part that founders do not believe until they see it. Sentry takes 25 minutes to install in a Next.js or Node.js application:&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; @sentry/nextjs
npx @sentry/wizard &lt;span class="nt"&gt;-i&lt;/span&gt; nextjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The free tier covers 5,000 errors per month — enough for any startup under 10,000 active users. The paid tier starts at $26 per month. There is no technical reason not to have it. I have audited twelve stacks. Eight of them had no error monitoring. The founders all said the same thing: "We rely on users to tell us when something is broken." Users do not tell you. They leave.&lt;/p&gt;




&lt;h2&gt;
  
  
  Failure pattern 4 — The free tier that sleeps
&lt;/h2&gt;

&lt;p&gt;Heroku Eco dynos and Render free tier web services spin down after 30 minutes of inactivity. No traffic for half an hour? The server goes to sleep. This is not a bug. It is the feature that makes the free tier free.&lt;/p&gt;

&lt;p&gt;When a user hits the application after a period of inactivity, the server has to start up before it can respond. This cold start takes between 10 and 30 seconds. During those seconds, the browser shows a blank screen. No loading spinner. No progress bar. Just white. The user assumes the site is broken. Most leave before the server has finished starting.&lt;/p&gt;

&lt;p&gt;A founder demos their product to a potential investor. They open their laptop. They navigate to their own URL. They have not visited the site themselves in the last 45 minutes because they have been preparing for this demo. The site takes 22 seconds to load. The investor sees a blank screen for 22 seconds. The founder refreshes. Another 22 seconds. The investor's first impression of the product's reliability is a 22-second blank screen. The signal sent is not about the product. It is about the team.&lt;/p&gt;

&lt;p&gt;This is fixable for $7 per month. A Heroku Basic dyno or a Render paid web service does not sleep. The site loads in under one second every single time. The cost of not fixing it is incalculable. That investor meeting does not happen again. That user who saw a blank screen does not come back.&lt;/p&gt;

&lt;p&gt;Here is the alternative if you genuinely cannot afford the paid tier. UptimeRobot on a free plan. Configure it to ping the server every 5 minutes: &lt;code&gt;https://yourapp.com/health&lt;/code&gt;. The cold start never happens. This is not a production-grade solution. But it costs $0 and takes 4 minutes to set up. I have audited twelve stacks. Four of them were running on free tier dynos with no keep-alive mechanism. Every single founder said the same thing: "I didn't know it went to sleep."&lt;/p&gt;




&lt;h2&gt;
  
  
  The pattern across all 12 audits
&lt;/h2&gt;

&lt;p&gt;None of these failures were caused by bad engineering. Not one.&lt;/p&gt;

&lt;p&gt;The Supabase free tier is the right choice for day one. The missing staging environment was a pragmatic trade-off when the team was two people and zero customers. The Heroku free tier that sleeps was a smart way to keep costs at zero during the three months before launch. These were rational decisions made by competent engineers who were optimizing for the constraints they had at the time.&lt;/p&gt;

&lt;p&gt;The problem is that those constraints change. At zero users, a free tier connection pool of 60 is infinite. At 500 users, it is a wall. At zero users, a hardcoded API key in a private repository feels safe. At 500 users, that key has been cloned onto six laptops, three of which are no longer managed by the company. The gap between "the right choice for day one" and "the wrong choice for launch day" is rarely filled because no one is watching.&lt;/p&gt;

&lt;p&gt;Here is the specific moment when these gaps become expensive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The launch:&lt;/strong&gt; Product Hunt goes live. Two hundred people click through. The database connection pool exhausts at request 61. The next 139 users see a 500 error. The launch slot passes. There is no second first impression.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The investor demo:&lt;/strong&gt; The founder opens the laptop. The Render free tier has been idle for an hour. Cold start takes 22 seconds. The investor sees a blank screen. The signal sent is not about the product. It is about the team.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The first enterprise prospect:&lt;/strong&gt; The security questionnaire arrives. Question 17: "Do you store secrets in your source code repositories?" The founder hesitates. The answer is yes. The deal stalls.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A one-day audit run before any of these moments costs £1,500. Here is what happens in that day: &lt;code&gt;trufflehog&lt;/code&gt; scan against the repository history (5 minutes), Supabase project plan review, staging environment verification (&lt;code&gt;pg_dump --schema-only comparison&lt;/code&gt;), error monitoring check, cold start audit (&lt;code&gt;curl -w "Time: %{time_total}s" https://yourapp.com/health&lt;/code&gt;). The output is a two-page document: five specific gaps, the exact command to verify each one, and the fix time measured in minutes.&lt;/p&gt;

&lt;p&gt;A launch failure costs more than £1,500. A failed investor demo costs more than £1,500. A stalled enterprise deal costs multiples of £1,500. The audit is not insurance. Insurance pays out after the loss. The audit prevents the loss from happening at all.&lt;/p&gt;

&lt;p&gt;The thing that breaks before 1,000 users is almost never the code. The thing that fixes it is almost never more code. It is a one-day audit, a toggle in a dashboard, a port number change, a $7/month dyno, and a secret scanner that runs for five minutes.&lt;/p&gt;

&lt;p&gt;Twelve startups. Every single one had at least three of these gaps. Every single one fixed them in less time than they spent reading this post.&lt;/p&gt;




&lt;p&gt;If your stack is on this list, I run a one-day audit. Link in bio.&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>node</category>
      <category>heroku</category>
      <category>github</category>
    </item>
    <item>
      <title>Git Quick Reference | The Comprehensive Guide to Git</title>
      <dc:creator>Ayobami Adejumo</dc:creator>
      <pubDate>Tue, 02 May 2023 18:53:33 +0000</pubDate>
      <link>https://forem.com/aayostem/git-quick-reference-the-comprehensive-guide-to-git-1loe</link>
      <guid>https://forem.com/aayostem/git-quick-reference-the-comprehensive-guide-to-git-1loe</guid>
      <description>&lt;p&gt;Git is a Version Control System. A version control system is a software designed to record changes within one or more files over time. &lt;br&gt;
When developers work on a project, different files are created and changes are made continuously to parts of the code. As the project grows, some of the code results in conflict. Git enables us to roll back, revert or cancel pending changes within one or more files. Git also enables us to compare the changes made to the different versions of a project. Having understood the importance of git, let's dive in&lt;/p&gt;
&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;If you don't have git already installed on your machine, you can download the latest version from the git-scm website &lt;a href="https://git-scm.com/downloads" rel="noopener noreferrer"&gt;https://git-scm.com/downloads&lt;/a&gt; according to the version of your operating system - Windows, Mac, or Linux.&lt;br&gt;
if you're running a Windows operating system, download the Windows version and go to the DOWNLOAD folder in file explorer.&lt;br&gt;
Now double-click to install and follow the prompt. once installed, let's proceed to set up.&lt;/p&gt;
&lt;h3&gt;
  
  
  Configuration
&lt;/h3&gt;

&lt;p&gt;You can confirm if you correctly installed git with the &lt;code&gt;git --version&lt;/code&gt; On confirmation, let's proceed to configure our name and email.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git config --global user.name "firstname lastname"
git config --global user.email "firstname@email.com"
#check this 
git config --global --list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Getting Started
&lt;/h3&gt;

&lt;p&gt;To learn the basic git commands by practice, open the terminal of a text editor such as Vscode and practice with the following commands.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git init&lt;/code&gt;&lt;br&gt;
Initialize a new git repo in the current working directory. Without this command, most of the commands below won't work.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git clone [https://yourremoterepo...]&lt;/code&gt;&lt;br&gt;
This command helps to download a project from a remote repository. git clone copies the entire repository including branches and commit&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git status&lt;/code&gt;&lt;br&gt;
Displays the state of the working directory. It displays the files which are staged, unstaged or untracked. This command doesn't make any changes or modify any file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git add filename&lt;/code&gt;&lt;br&gt;
Add file from the working directory to the staging area&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git add .&lt;/code&gt;&lt;br&gt;
recursive add lets you add all untracked files in the working directory to the staging area.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git commit -m "enter your commit message here"&lt;/code&gt;&lt;br&gt;
Create a new commit from changes added to the staging area. The commit must have a message!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ git rm [filename]&lt;/code&gt;&lt;br&gt;
Remove the file from the working directory and staging area.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reviewing Commit History
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;$ git log&lt;/code&gt;&lt;br&gt;
Used to view the history of committed changes within a repository. git log displays the history of everything.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ git log --oneline --graph --decorate&lt;/code&gt;&lt;br&gt;
Display a text-based graphical representation of the commit history. It shows an overview with reference labels and a history graph.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ git show commit-id&lt;/code&gt;&lt;br&gt;
Show commit log with information such as author, date, and diff output&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git diff&lt;/code&gt;&lt;br&gt;
show changes between the working directory and the staging area. This helps you track and compare the various changes you've made to code.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git diff --staged [file]&lt;/code&gt;&lt;br&gt;
Shows any changes between the staging area and the repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  Revert or Undo Changes
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;git checkout [filename]&lt;/code&gt;&lt;br&gt;
Discard changes in the working directory. This operation is unrecoverable.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git reset commit-id&lt;/code&gt;&lt;br&gt;
Revert your repository to a previously known working state.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git revert&lt;/code&gt;&lt;br&gt;
Undo changes to a repository's commit history&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ git revert [commit sha]&lt;/code&gt;&lt;br&gt;
Create a new commit, reverting changes from the specified commit.&lt;br&gt;
It generates an inversion of changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Git branching model
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;$ git branch -a&lt;/code&gt;&lt;br&gt;
List all local branches in a repository. With -a: show all branches (with remote).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ git branch [branch_name]&lt;/code&gt;&lt;br&gt;
Create a new branch, referencing the current HEAD.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ git checkout [branch_name]&lt;/code&gt;&lt;br&gt;
Switch the working directory to the specified branch.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ git checkout -b [branch_name]&lt;/code&gt;&lt;br&gt;
Create a new branch and switch the working directory to the new branch.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ git merge [branchname]&lt;/code&gt;&lt;br&gt;
Join specified [branchname] into your current branch (the one&lt;br&gt;
you are on currently).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ git branch -d [branchname]&lt;/code&gt;&lt;br&gt;
Remove the selected branch, if it is already merged into any other.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ git reflog&lt;/code&gt;&lt;br&gt;
List operations (e.g. checkouts or commits) made on the local repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tagging
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;$ git tag&lt;/code&gt;&lt;br&gt;
List all tags.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ git tag [tagname]&lt;/code&gt;&lt;br&gt;
Create a tag reference named name for the current commit.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ git tag -d [tagname]&lt;/code&gt;&lt;br&gt;
Remove a tag from the local repository&lt;/p&gt;

&lt;h3&gt;
  
  
  Synchronizing repositories
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;$ git fetch [remote]&lt;/code&gt;&lt;br&gt;
Download changes from the remote, but not update tracking branches.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ git fetch --prune [remote]&lt;/code&gt;&lt;br&gt;
Delete remote Refs that were removed from the remote repository.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ git pull [remote]&lt;/code&gt;&lt;br&gt;
Fetch changes from the remote and merge the current branch with its upstream.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ git push [--tags] [remote]&lt;/code&gt;&lt;br&gt;
Push local changes to the remote. Use --tags to push tags.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stashing
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;$ git stash&lt;/code&gt;&lt;br&gt;
Put current changes in your working directory into the stash for later use.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ git stash pop&lt;/code&gt;&lt;br&gt;
Apply stored stash content into the working directory, and clear stash.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ git stash drop&lt;/code&gt;&lt;br&gt;
Delete a specific stash from all your previous stashes&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Full Guide: How to Build a UI Component Library</title>
      <dc:creator>Ayobami Adejumo</dc:creator>
      <pubDate>Sun, 06 Nov 2022 23:10:42 +0000</pubDate>
      <link>https://forem.com/aayostem/full-guide-how-to-build-a-ui-component-library-59ho</link>
      <guid>https://forem.com/aayostem/full-guide-how-to-build-a-ui-component-library-59ho</guid>
      <description>&lt;p&gt;The trees that are slow bear the best of fruits. We’ve all heard this phrase thousands of times, but can this be said of modern businesses and technologies where products are shipped everyday?&lt;/p&gt;

&lt;p&gt;In a constantly evolving world, you can definitely bear good fruits at a slower pace but there’s no guarantee of being the best. Infact, launching too late has been a major business killer.&lt;/p&gt;

&lt;p&gt;Therefore, as a developer you should try to eliminate or substitute your less important tasks to focus most on the high-value tasks.&lt;/p&gt;

&lt;h4&gt;
  
  
  One area where developers spend a lot of time but ideally they shouldn’t (initially) is the styling of their web app.
&lt;/h4&gt;

&lt;p&gt;Writing CSS code from scratch can be a beautiful experience but if you’re an organization or startup hoping to launch products sooner and faster, writing repetitive css code is not the best. This is the reason for the development of design systems and UI components libraries.&lt;/p&gt;

&lt;p&gt;However, you need to first evaluate your need so that you can choose between a ready made UI components or building a custom UI library from scratch. Sometimes, a custom component library is an overkill and you’re much better off using ready-made UI components.&lt;/p&gt;

&lt;p&gt;if you are an organisation or a startup looking to create a visual identity for your company (think big companies like Netflix, Amazon, Uber) and can do so without straining your budget, go for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where do we start building?
&lt;/h2&gt;

&lt;p&gt;Numerous sectors such as Architecture or Industrial Design have developed smart modular systems for manufacturing extremely complex objects like airplanes, ships, and skyscrapers. That is, these complex objects are made up of multiple building blocks that can be put together to form a bigger entity.&lt;/p&gt;

&lt;p&gt;Inspired by this, Atomic Design was proposed by Brad Frost in 2013 as a system that involves breaking down a website or web application into its basic components so that they are reusable throughout the site. Due to new devices with new screen sizes, that are getting released each year, creating pixel-perfect design gets harder if no systems are put in place&lt;/p&gt;

&lt;p&gt;Atomic Design, introduces a methodology for creating scalable systems, reusable components as well as design systems. There are five distinct levels in atomic design&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Atoms&lt;/li&gt;
&lt;li&gt;Molecules&lt;/li&gt;
&lt;li&gt;Organism&lt;/li&gt;
&lt;li&gt;Templates&lt;/li&gt;
&lt;li&gt;Pages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Atoms - represent the smallest entity in UI elements and they can’t be broken down any further examples of an atom include button, input, label.&lt;/p&gt;

&lt;p&gt;Molecules - Molecules are groups of atoms bonded together that take on distinct new properties. For instance, a profile molecule is the combination of avatar atom with name and title labels&lt;/p&gt;

&lt;p&gt;Organism - Organisms are more complex UI components composed of groups of molecules and/or atoms header organism;&lt;/p&gt;

&lt;p&gt;Templates - Templates are pages without real content.&lt;/p&gt;

&lt;p&gt;Pages - Pages are instances of templates that demonstrate the final UI looks like and with real data and contents.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a Monorepository
&lt;/h2&gt;

&lt;p&gt;We'll start by setting up a monorepository. &lt;/p&gt;

&lt;p&gt;A monorepo is a version-controlled code repository that holds many projects with well defined relationships. While these projects may be related, they are often logically independent and run by different teams.&lt;/p&gt;

&lt;p&gt;In this case, the monorepo will contain scss package, react, vue and angular packages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir seraph-design-system
cd seraph-design-system
yarn init -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;proceed to setup your workspace&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"private":"true",
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can check the &lt;a href="https://github.com/janto-pee/Seraph-Design-System" rel="noopener noreferrer"&gt;github repository&lt;/a&gt; for project dependencies. Proceed to install and configure lerna.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add --dev lerna
yarn lerna --init

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

&lt;/div&gt;



&lt;p&gt;add "useWorspaces": "true" and "stream":"true"&lt;br&gt;
By now, your lerna file should look like;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "$schema": "node_modules/lerna/schemas/lerna-schema.json",
  "useWorkspaces": true,
  "version": "0.0.0",
  "stream": true
}

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

&lt;/div&gt;



&lt;p&gt;add worskspaces, dev and build script to package.json;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"scripts": {
    "build": "yarn lerna run build",
    "dev": "yarn lerna run dev"
  },
  "workspaces": {
    "packages": [
      "packages/**",
      "playground/**"
    ]
  },
  "devDependencies": {
    "lerna": "^6.0.1",
    "process": "^0.11.10"
  }

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

&lt;/div&gt;



&lt;p&gt;let's create a package structure&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup Your Package structure in the root
&lt;/h2&gt;

&lt;p&gt;in the root directory - seraph-design-system&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir packages
cd packages

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

&lt;/div&gt;



&lt;p&gt;create a directory for react, vue, and scss. You can include angular too.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- node_modules/
- packages/
  - react
  - scss
  - vue
- package.json
- lerna.json
- .gitignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;let's create our css architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  SCSS Package
&lt;/h2&gt;

&lt;p&gt;To keep the css architecture modular, it’s important to break the code into smaller parts.&lt;/p&gt;

&lt;p&gt;Multiple files make the code easier to read, navigate and track. To do that, a CSS preprocessor – such as Sass, LESS or Stylus – or a post-processor – such as PostCSS – is the way to go.&lt;/p&gt;

&lt;p&gt;Preprocessors enhance the capabilities of CSS authoring, introducing new features such as variables, mixins and much more. To work with separate files, your code will be divided into partials and imported on a main.scss file, that will compile everything into a single .css file.&lt;/p&gt;

&lt;p&gt;3 benefit of using a preprocessor&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;breaking the code into smaller chunks and separating them by scope;&lt;/li&gt;
&lt;li&gt;coding components in a independent and encapsulated manner;&lt;/li&gt;
&lt;li&gt;naming CSS selectors according to their purpose and relationship with each other.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each component should be encapsulated on its own file. For consistency reasons, it’s a good practice to use the same name for the file and main selector&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd packages/scss
mkdir src
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now create a file global.scss in src&lt;br&gt;
in addition to the file, create four folders in src - atoms, molecules, foundation, organisms;&lt;/p&gt;

&lt;p&gt;cd into the foundation folder and create your _variables.scss, _typography, _mixins.scss, _all.scss, _colors.scss.&lt;/p&gt;

&lt;p&gt;By now, your folder structure should be like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  - scss
    - src/
        global.scss
        - atoms/
        - foundation/
            _all.scss
            _color.scss
            _mixins.scss
            _typography.scss
            _variables.scss

        - molecules/
        -organisms/

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

&lt;/div&gt;



&lt;p&gt;As the names of the files suggest, create all variables as specified in your design (figma) into the _variables.scss.&lt;/p&gt;

&lt;p&gt;Proceed to create default colors and typography in their respective files. _mixins.scss should contain reuable styles such as breakpoint sizes.&lt;/p&gt;

&lt;p&gt;You can checkout the &lt;a href="https://github.com/janto-pee/Seraph-Design-System" rel="noopener noreferrer"&gt;github&lt;/a&gt; repository for more information on this file&lt;/p&gt;

&lt;p&gt;import the four files (_variables.scss, _color.scss, _mixins.scss, _typography.scss) into the _all.scss&lt;/p&gt;

&lt;p&gt;Then, import the _all.scss into the global.scss (in src) to make it available to gulp-sass for compilation.&lt;/p&gt;

&lt;h4&gt;
  
  
  Install devDepencies for Scss package
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd package/scss
yarn init -y

yarn add --dev normalize-scss gulp gulp-sass stylelint prettier stylelint-config-sass-guidelines  stylelint-config-prettier stylelint-prettier

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  let configure normalize-scss and other devDependencies
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd scss/src
mkdir normalize

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

&lt;/div&gt;



&lt;p&gt;create two files in the normalize _root.scss and _reset.scss&lt;/p&gt;

&lt;p&gt;The _reset.scss contains import from normalize-scss&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@import "node_modules/normalize-scss/sass/normalize/import-now";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The _root.scss contains scss root such as&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:root{
  ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;import these two files (_root.scss and _reset.scss) into the global.scss&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- node_modules/
- packages/
  - scss
    - lib/
    - node_modules/
    - src/
        global.scss
        - atoms/
            Button.scss
            Text.scss
            Input.scss
        - foundation/
            _all.scss
            _color.scss
            _mixins.scss
            _typography.scss
            _variables.scss
        - molecules/
            inputfield.scss
    - package.json
    - .stylelintrc.json
    - gulpfile.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;create a .styleintrc.json file and gulpfile.js file.&lt;/p&gt;

&lt;p&gt;now run gulp watch.&lt;br&gt;
you should have your compiled files in the dist folder;&lt;br&gt;
congrats.&lt;/p&gt;
&lt;h2&gt;
  
  
  React UI library Component
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd packages/react
yarn init -y
yarn add --dev react typescript @types/react rollup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;since we're building a library, rollup is our preferred bundler.&lt;br&gt;
Therefore, create a tsconfig.json and rollup.config.js file&lt;/p&gt;

&lt;p&gt;now make atomic folders like we did for the scss package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- node_modules/
- packages/
  - react
    - lib/
    - node_modules/
    - src/
        - atoms/
        - molecules/
        - organisms/
    - package.json
    - rollup.config.js
    - tsconfig.json

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

&lt;/div&gt;



&lt;p&gt;set up dev and build script&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"scripts": {
    "build": "rollup -c",
    "dev": "yarn build --watch"
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  creating our First Component;
&lt;/h3&gt;

&lt;p&gt;create a Heading components.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd src/atoms
mkdir Button
cd Button
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;create two files Heading.tsx and index.ts&lt;/p&gt;

&lt;p&gt;atoms/Heading/Heading.tsx&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';

interface HeadingProps {
    title: string
    color?: string
}

const Heading: React.FunctionComponent&amp;lt;HeadingProps&amp;gt;({title, color}) =&amp;gt; {
    return &amp;lt;h1 style={{color: color}} class='header'&amp;gt;{title}&amp;lt;/h1&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in the atoms/Heading/index.ts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export {default} from './Heading'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in the src/index.ts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Heading from './atoms/Heading';
export {
    Heading;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your react package structure looks like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- node_modules/
- packages/
  - react
    - lib/
    - node_modules/
    - src/
        - index.ts
        - atoms/
            - Heading/
                - Heading.ts
                - index.ts
        - molecules
        -organisms
    - package.json
    - rollup.config.js
    - tsconfig.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now run yarn build to build your component.&lt;/p&gt;

</description>
      <category>design</category>
      <category>react</category>
      <category>vue</category>
      <category>css</category>
    </item>
  </channel>
</rss>
