Philosophy

Why semantic HTML/CSS matters

The Case for Semantic HTML

Class names should describe what elements are, not how they look.

Semtx: Semantic Classes

Card Title
Content
Actions
<div class="form-group">
  <label class="form-label">Email</label>
  <input class="form-input">
</div>

<button class="btn btn-primary">Submit</button>

<div class="card">
  <header>Title</header>
  <div class="card-body">Content</div>
  <footer>Actions</footer>
</div>

Why It Matters

Semantic class names describe what an element is, not how it looks. This creates code that is easier to read, maintain, and collaborate on. When you use .btn-primary instead of a dozen utility classes, your intent is clear.

For AI coding assistants, semantic classes provide context that utility-first frameworks cannot. An AI can immediately understand that .card is a container component, whereas flex p-4 rounded-lg shadow requires the AI to mentally assemble these into a component pattern.

  • Readable - Class names reveal purpose
  • Maintainable - Changes propagate automatically
  • AI-Friendly - Coding agents understand intent
  • Portable - Works across projects
  • Accessible - Semantic = accessible by default
  • SEO-Friendly - Search engines understand structure
  • Consistent - Uniform patterns across codebase

HTML5 Semantic Elements

Use native HTML elements that describe their meaning.

Semtx Works with Native Elements

Article Title

Article content goes here...

Author info

Sample
Figure caption
<main>
  <article>
    <header><h2>Title</h2></header>
    <p>Content...</p>
    <footer>Author info</footer>
  </article>
  
  <aside>
    <nav>...</nav>
  </aside>
</main>

<figure>
  <img src="...">
  <figcaption>Caption</figcaption>
</figure>

Benefits of Semantic Elements

  • <main> - Primary content region
  • <article> - Self-contained content
  • <section> - Thematic grouping
  • <aside> - Sidebar content
  • <header> - Intro/navigation
  • <footer> - Footer info
  • <nav> - Navigation links
  • <figure> - Images with caption

SEO-Friendly by Design

Semantic HTML helps search engines understand your content.

🔍

Better Indexing

Search engines prioritize content in <main>, <article>, and heading elements.

📊

Rich Snippets

Structured content enables rich results in search (articles, products, reviews).

Faster Crawling

Clear structure helps bots find content faster, improving SEO performance.

Example: Proper Heading Hierarchy

<main>
  <h1>Page Title</h1>
  <article>
    <h2>Article Title</h2>
    <h3>Subsection</h3>
  </article>
</main>

Search engines use heading hierarchy to understand content structure and importance.

Code Quality Benefits

Semantic HTML/CSS leads to better code overall.

Easier to Read

  • Class names describe purpose, not appearance
  • New developers understand code faster
  • Code reviews are more efficient
  • Self-documenting markup

Greater Visibility

  • Component patterns are obvious
  • Easy to search for all cards, forms, buttons
  • Global styles in one place
  • Consistent naming eliminates confusion

Consistent Code

  • Same patterns everywhere
  • No reinventing styling solutions
  • Team-wide convention
  • Easy to enforce standards

Example: Finding All Buttons

With Tailwind:

grep -r "bg-blue-500\|text-white\|px-4 py-2" .

With Semtx:

grep -r "btn" .

The Tailwind Bloating Problem

When every style decision becomes a class name.

A Simple Card in Tailwind

<div class="max-w-sm rounded overflow-hidden shadow-lg bg-white">
  <img class="w-full h-48 object-cover" src="..." alt="Card">
  <div class="px-6 py-4">
    <div class="font-bold text-xl mb-2">Card Title</div>
    <p class="text-gray-700 text-base">
      Some text here.
    </p>
  </div>
  <div class="px-6 pt-4 pb-2">
    <span class="inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2">Tag</span>
  </div>
</div>

That's 187 characters of class names for a card. Now imagine maintaining 50 similar cards.

The Same Card in Semtx

<div class="card">
  <img src="..." alt="Card">
  <div class="card-body">
    <h3>Card Title</h3>
    <p>Some text here.</p>
  </div>
  <footer>
    <span class="badge">Tag</span>
  </footer>
</div>

Tailwind vs Semtx

Tailwind Semtx
Class intent Describes style Describes component
Readability Low - unreadable markup High - semantic
File size ~50-100KB+ ~8KB
AI understanding Poor - scattered styles Good - clear structure
HTMX integration Manual Built-in
Learning curve Steep - memorize classes Low - intuitive names
Maintainability Change everywhere Single point of change

Why Semtx Works Better with AI

Coding agents (LLMs) understand semantic class names better.

The AI Prompt Problem

When you ask an AI to "make this button bigger", it needs to understand which classes control the button size.

With Semtx:

The AI sees btn btn-primary and knows exactly what to change. It might add btn-lg or modify .btn in CSS.

With Tailwind:

The AI must parse px-3 py-2 text-sm font-medium border-1 border-solid rounded-md to figure out it is related to a button, then find and modify multiple utility classes.

AI-Friendly Patterns

Good Prompt

"Add a form with email and password inputs"

The AI generates:

<div class="form-group">
  <label class="form-label">Email</label>
  <input type="email" class="form-input">
</div>
<div class="form-group">
  <label class="form-label">Password</label>
  <input type="password" class="form-input">
</div>

Component Discovery

AI agents can easily find all components by searching for class names like .card, .btn, .form-input. No need to search for scattered utilities.

Consistent Changes

When you ask an AI to "update all buttons to use the new primary color", it only needs to change --primary in CSS. With Tailwind, it must find every bg-blue-500 pattern.

Built for HTMX

Semtx includes native HTMX patterns that work without extra code.

Loading Indicator

<button hx-get="/data" hx-indicator=".loading">
  Load
  <span class="htmx-indicator loading">Loading...</span>
</button>

<!-- CSS handles visibility automatically -->

Progress Bar

<div class="progress">
  <div class="progress-bar" style="width: 60%"></div>
</div>

<!-- Or indeterminate -->
<div class="progress">
  <div class="progress-bar indeterminate"></div>
</div>

Search with Loading

<div class="input-search">
  <input hx-get="/search" hx-trigger="input changed delay:300ms">
  <span class="input-search-icon">🔍</span>
  <span class="htmx-indicator spinner"></span>
</div>