Glaze Basecoat

Package Version Hex Docs

This is a collection of Lustre components mapped from Basecoat UI.

Basecoat UI is a Tailwind CSS-based component library inspired by shadcn/ui that works with any web stack.

For a full list of components, take a look at https://hexdocs.pm/glaze_basecoat or https://basecoatui.com/components/

Latest supported version is Basecoat v0.3.11.

GitHub Pages Demo: https://daniellionel01.github.io/glaze/glaze_basecoat/

Getting Started

gleam add glaze_basecoat@1
import glaze/basecoat
import glaze/basecoat/icon
import glaze/basecoat/theme
import glaze/basecoat/theme_switcher
import lustre/element/html

html.head([], [
  // (Optional) Register Tailwind (if not already coming from your build-tool)
  html.script(
    [attribute.src("https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4")],
    "",
  ),
  // Don't forget this, if you're using Tailwind through a CDN!
  theme.tailwind_v4_bridge_style_tag(),
  
  // Register Basecoat Components
  basecoat.register(basecoat.version),
  
  // Register your theme
  theme.style_tag(theme.default_theme()),
  
  // Register Lucide icons, required by some components
  icon.register_cdn("latest"),
  
  // (Optional) Init theme switcher
  theme_switcher.init_script(),
])

Example

In a real project this might look like this:

import glaze/basecoat
import glaze/basecoat/button
import glaze/basecoat/card
import glaze/basecoat/theme
import lustre/element/html

pub fn layout() {
  html.html([], [
    html.head([], [
      // ...
      
      theme_switcher.init_script(),
      icon.register_cdn("latest"),
      
      html.script(
        [attribute.src("https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4")],
        "",
      ),
      theme.tailwind_v4_bridge_style_tag(),
      
      basecoat.register(basecoat.version),
      theme.style_tag(theme.default_theme()),
    ]),
    html.body([], [
      card.card([], [
        card.header([], [
          card.title([], [html.text("Welcome")]),
          card.description([], [html.text("Hello!")]),
        ]),
        card.content([], [
          button.button([], [html.text("Get Started")]),
        ]),
      ]),
    ]),
  ])
}

You can find the full documentation here: https://hexdocs.pm/glaze_basecoat.

Take a look at the dev module for a kitchen sink of all components and how you might use them!

Tailwind CSS

Basecoat UI ships Tailwind-based styles. You can either use the CDN for a fast setup, or integrate it into your own Tailwind build.

TL;DR

ScenarioCSSJSUse these functions
Use Tailwind CDNTailwind CDN + Basecoat CDNBasecoat JS via CDNTailwind <script ...@tailwindcss/browser@4>
glaze_basecoat.register(version)
theme.style_tag(...)
theme.tailwind_v4_bridge_style_tag()
Build-time Tailwind (CLI/PostCSS/Vite)Your Tailwind build output (with @import "basecoat-css")Basecoat JS via CDNglaze_basecoat.register_js(version)
theme.style_tag(...)
Manage CSS/JS separately (still CDN)Basecoat compiled CSS via CDNOnly specific JS components via CDNglaze_basecoat.register_css(version)
glaze_basecoat.register_component(version, "popover")

Option 1: Full CDN

Use basecoat.register() to include Basecoat’s compiled CSS and all Basecoat JavaScript via CDN.

Option 2: Tailwind Play CDN

If you use Tailwind’s CDN (https://tailwindcss.com/docs/installation/play-cdn), you also need Basecoat’s Tailwind v4 @theme mapping so utilities like bg-accent exist.

If you have a build-time Tailwind setup, you do not need this bridge (it comes from @import "basecoat-css").

import glaze/basecoat
import glaze/basecoat/theme
import lustre/attribute.{attribute}
import lustre/element/html

html.head([], [
  html.script(
    [attribute.src("https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4")],
    "",
  ),
  basecoat.register(basecoat.version),
  theme.style_tag(theme.default_theme()),
  theme.tailwind_v4_bridge_style_tag(),
])

Option 3: Build-time Tailwind

If you have a build-time Tailwind setup (Tailwind CLI/PostCSS/Vite/etc) and you install Basecoat from npm, you can import Basecoat directly in your Tailwind entry CSS.

npm install basecoat-css
@import "tailwindcss";
@import "basecoat-css";

In this case you should not use basecoat.register(), since it also includes Basecoat’s CSS from the CDN. Use basecoat.register_js() (or basecoat.register_component()) to only include the JavaScript and let your Tailwind build produce the CSS.

import glaze/basecoat
import glaze/basecoat/theme
import lustre/attribute.{attribute}
import lustre/element/html

html.head([], [
  basecoat.register_js(basecoat.version),
  theme.style_tag(theme.default_theme()),
])

Option 4: Split CSS and JS (CDN)

If you want to manage CSS and JavaScript separately (still via CDN), register the compiled CSS and only the JS components you use.

import glaze/basecoat
import glaze/basecoat/theme
import lustre/element/html

html.head([], [
  basecoat.register_css(basecoat.version),
  basecoat.register_component(basecoat.version, "popover"),
  theme.style_tag(theme.default_theme()),
])

Theming

Basecoat uses shadcn/ui compatible CSS variables. You can customize the theme:

import glaze/basecoat/theme

let custom_theme =
  theme.default_theme()
  |> theme.set(theme.Primary, "oklch(0.205 0 0)")
  |> theme.set(theme.Radius, "0.5rem")

Browse available themes at ui.shadcn.com/themes.

You can also use tools like https://tweakcn.com/editor/theme!

Icons

Basecoat uses Lucide icons.

The icon helpers in glaze/basecoat/icon render placeholders like <i class="lucide" data-lucide="plus">. To turn those placeholders into SVGs you must also load the Lucide runtime.

Lucide docs (including the CDN snippet): https://lucide.dev/guide/packages/lucide

Option 1: Bundled

Install lucide (npm/pnpm/bun) and use icon.init().

Note: icon.init() injects a <script type="module"> that does import lucide from "lucide". That means your app must have a JS setup that can resolve the bare module specifier (bundler, import map, etc).

import glaze/basecoat/icon
import lustre/element/html

// Initialize Lucide
html.head([], [
  icon.init(),
])

// Use icons
icon.plus([])
icon.search([])

Option 2: CDN

If you are not bundling JavaScript, include Lucide icons via CDN.

import glaze/basecoat/icon

html.head([], [
  // Use a pinned version in real projects.
  icon.register_cdn("latest"),
])

// Use icons (same API)
icon.plus([])
icon.search([])

FAQs

Client vs Server?

This library constructs HTML elements the same way on a client or on a server, so it is compatible in both environments.

Development

There is a dev module that constructs a Demo with all available elements and writes it to a .html file:

gleam dev
open ../docs/glaze_basecoat/index.html
✨ Search Document