The big mistake

Using Tailwind CSS for Notado is the single biggest mistake I have ever made in my career as a developer.

I cannot overstate the amount of technical debt that this has introduced, and how it has compounded over the years since this decision was taken. Never use this for a one-man SaaS project.

One of the biggest consequences of this mistake was that introducing dark mode immediately became a non-trivial task, especially when compared to Kullish, where I had the good sense to use Bulma, and adding dark mode was the simple case of adding a single link element to my existing base HTML template:

<link
  rel="stylesheet"
  type="text/css"
  href="https://unpkg.com/bulma-prefers-dark"
/>

I’m not really interested in LLMs to help me write code

I personally have not had much use for LLMs while writing code, and I definitely don’t want LLM-powered code suggestions integrated into my text editor. This would remove a significant part of the “fun” of programming for me.

Nevertheless, I kept hearing that LLMs were great for “boring” and tedious programming tasks, and since Tailwind still seems to be recommended everywhere alongside React, I was pretty confident that most LLMs would have a good understanding of the library.

Using an LLM for the tedious task of implementing dark mode with Tailwind

Despite having acknowledged and accepted that using Tailwind was a mistake, I have no interest in redesigning Notado to remove it.

Notado is a finished product of which I am now primarily an end user. I rarely return to the codebase, and when I do, it’s to fix a broken integration test or to add support for a new micro-blogging platform.

Given these facts, I thought it would be an interesting exercise to give an LLM my main.css file and ask it to come up with a dark theme which would be applied automatically depending on a user’s system settings.

I went with Claude.ai, for no particular reason besides hearing people talk positively about it on the internet.

Trial and error

The conversation between Claude and I:

Me

In a project I am using "tailwindcss": "^3.1.8"

This is my main.css file

main.css code snippet

This is a bright color scheme.

I would like for you to propose a dark color scheme which can be automatically enabled if a user has a preference for dark mode set on their system.

Claude

I’ll help you create a dark mode version of your color scheme using Tailwind’s dark mode feature. By default, Tailwind uses the prefers-color-scheme media query, so it will automatically switch based on system preferences.

updated main.css code snippet

Key changes I’ve made for the dark theme:

  • Background colors:
    • Changed light grays to darker variants (gray-800, gray-700)
    • Adjusted border colors to be visible on dark backgrounds
  • Text colors:
    • Changed dark text to light variants
    • Adjusted blue links to be more visible (blue-400)
    • Made secondary text slightly lighter (gray-400)
  • Interactive elements:
    • Modified hover and focus states to be visible on dark backgrounds
    • Adjusted shadow colors for dark mode
    • Made sure form elements (inputs, selects) have proper dark backgrounds
  • Contrast considerations:
    • Ensured text remains readable on dark backgrounds
    • Maintained proper contrast ratios for accessibility
    • Kept interactive elements clearly distinguishable

To enable this, make sure your tailwind.config.js has dark mode enabled. It should have darkMode: 'media'.

Would you like me to adjust any of the color combinations or make any other changes to the dark theme?

Me

This is a good start, however the background color is still white and a lot of the text inside divs and paragraphs is still black.

Claude

Ah yes, let’s add base background and text colors for the dark theme by setting default dark mode styles for the body and common elements. Here’s the updated CSS:

updated main.css code snippet

Key changes made:

  1. Added base styles for body element with dark background and text colors
  2. Added default dark mode text colors for common elements (p, div, span)
  3. Updated background colors for form elements and containers to use gray-800
  4. Ensured all text elements have appropriate dark mode colors
  5. Added dark backgrounds to elements that previously inherited the white background

The color scheme now uses:

  • gray-900 as the main background color
  • gray-800 for elevated elements (inputs, cards, etc.)
  • gray-100 for primary text
  • gray-200/gray-300 for secondary text
  • gray-700 for borders

All interactive elements should now be clearly visible and accessible in dark mode. Would you like me to adjust any of these colors or make other changes?

Me

This is looking even better, however there are still a few elements which have white backgrounds. I’ll provide some examples of them taken directly from the rendered HTML.

<div class="flex">
  <a
    class="bg-white py-2 px-4 border border-gray-300 shadow-md text-sm
    font-medium text-gray-700 focus:border-gray-600 hover:border-gray-600"
    disabled=""
  >
    Previous
  </a>
</div>
<a
  id="library-title"
  href="/library?title=Mohammed%20El-Kurd%20%28%40m7mdkurd%29&amp;sort=latest&amp;count=any"
>
  <div
    class="bg-notado-blue text-white px-4 py-3 sm:px-6 sm:w-full text-sm
    font-medium border-b"
  >
    Mohammed El-Kurd (@m7mdkurd)
  </div>
</a>
<div class="mt-1 flex shadow-sm gap-2">
  <span
    class="inline-flex items-center px-3 border border-gray-300 bg-gray-50 sm:text-sm"
    >IF</span
  >
  <select onmouseup="generateTaggingRule()" name="field" class="tselect w-full">
    <option value="content">content</option>
    <option value="url">url</option>
    <option value="title">title</option>
  </select>
</div>
<a id="library-title" href="/feeds/jado/capitalism">
  <div
    class="group bg-white px-4 py-3 sm:px-6 sm:w-full text-sm font-medium
    focus:bg-notado-blue hover:bg-notado-blue hover:text-white focus:text-white
    border-b"
  >
    <h3 class="group-hover:text-white group-focus:text-white">Capitalism</h3>
    <p class="text-gray-500 group-hover:text-white group-focus:text-white">
      Thoughts on how capitalism intersects with work, art, technology, urban
      planning, life and love from around the internet
    </p>
  </div>
</a>

The <span> in this next one has a white background:

<div class="mt-1 flex shadow-sm gap-2">
  <span
    class="inline-flex items-center px-3 border border-gray-300 bg-gray-50 sm:text-sm"
    >IF</span
  >
  <select onmouseup="generateTaggingRule()" name="field" class="tselect w-full">
    <option value="content">content</option>
    <option value="url">url</option>
    <option value="title">title</option>
  </select>
</div>

In addition, the borders on some divs are pure white, but I would like for them to also have the same look as these borders in the compiled output in dark mode:

@media (prefers-color-scheme: dark) {
  #navigation > :not([hidden]) ~ :not([hidden]) {
    --tw-divide-opacity: 1;
    border-color: rgb(55 65 81 / var(--tw-divide-opacity));
  }

  #navigation {
    --tw-border-opacity: 1;
    border-color: rgb(55 65 81 / var(--tw-border-opacity));
  }
}

Claude

I’ll update the CSS to handle these specific cases. The issue is that some elements have explicit bg-white classes that need to be overridden, and we need to handle inline border styles.

updated main.css code snippet

Key changes made:

  1. Added a direct override for the bg-white class in dark mode
  2. Added specific handling for elements with inline border styles
  3. Updated the library title elements using an ID selector
  4. Added specific selectors for any element with a bg-white class
  5. Enhanced group hover/focus states for text colors
  6. Made sure navigation links have consistent border colors even with inline styles
  7. Added more specific handling for footer elements

The changes ensure:

  • All white backgrounds transition to gray-800 in dark mode
  • All borders are consistently gray-700 in dark mode
  • Text colors properly transition on hover/focus states
  • Inline styles are properly overridden in dark mode

Would you like me to make any adjustments to these styles?

Me

When I visit the site on iPhone in dark mode, the top notch still shows white.

How can I make it match the dark mode colors?

Claude

To handle the iPhone notch (and other similar areas) in dark mode, you’ll need to add a meta tag to your HTML and set the correct color scheme. Here’s what you need to add to your HTML <head> section:

<meta
  name="theme-color"
  content="#111827"
  media="(prefers-color-scheme: dark)"
/>
<meta
  name="theme-color"
  content="#ffffff"
  media="(prefers-color-scheme: light)"
/>

The #111827 color value corresponds to Tailwind’s gray-900 which we’re using for our dark mode background. If you’re using a different color for your dark mode background, you should adjust this hex value accordingly.

This will make the iPhone notch area match your site’s theme in both light and dark modes. The browser will automatically switch between these colors based on the user’s system preferences.

End result

I am happy with the end result on both desktop and mobile.

A side by side comparison of the dark and light themes

The experience

I was pleasantly surprised by my experience iterating on this problem with Claude. Perhaps others with more experience working with LLMs might have tips or approaches that are more efficient than mine, but I found this basic flow to work well:

  • Define the task and the constraints within which the task must be completed
    • Specify the versions of dependencies you are working with (exact Tailwind version)
    • Specify any behavior you are expecting (automatically apply based on system settings)
  • Share the relevant context (there probably isn’t a need to dump the entire src dir of a project)
  • Iterate first by describing any edge cases that need addressing
  • If description is not enough, augment description with reference output code artifacts

I don’t see myself using this approach very often (except whenever I next have to touch Tailwind again), but I think I can vouch for its ability to help when faced with boring, tedious programming tasks.

Fin

If you have any questions or comments you can reach out to me on Mastodon, Bluesky or Twitter.

If you’re interested in what I read to come up with software like Notado, you can subscribe to my Software Development RSS feed.

If you’d like to watch me writing code while explaining what I’m doing, you can also subscribe to my YouTube channel.

If you found this content valuable, or if you are a happy user of the komorebi tiling window manager or my NixOS starter templates, please consider sponsoring me on GitHub or tipping me on Ko-fi.