facebook / facebook/astryx

Adoption DX: integrating Astryx into an existing Next 15 + Tailwind app was harder than it should be (silent-failure traps + missing integration docs)

Open
#3,374 0 comments 0 reactions 1 assignee Claimed by @josephfarina View on GitHub
documentation enhancement
Dominant language
TypeScript
Stars
13k
Forks
1.1k
Avg merge
1d 15h
Merged PRs (30d)
690

Description

## Summary

This is an umbrella / experience report from adopting Astryx into a **real, existing Next.js 15 (App Router) + Tailwind 3** project (theming components with a custom `defineTheme` theme). The end result is great — a mostly-pure-Astryx surface driven entirely by a theme — but getting there hit several **silent-failure traps** and **missing integration docs** that cost a lot of time. Each is individually minor to fix or document; together they make first-time adoption rough. Filing so the next person doesn't have to rediscover them.

Two of these are broken out as standalone issues: #3371 (custom-variant type augmentation) and #3373 (StyleX build setup for swizzle). The rest are below, roughly by impact.

**Versions:** `@astryxdesign/core@0.1.2`, `@astryxdesign/cli@0.1.2`; Next 15 App Router, Tailwind 3, SWC.

---

### 1. [SILENT FAILURE] Tailwind preflight silently defeats *all* theme overrides (highest impact)

This one cost the most time and produced **zero errors** — just a theme that appeared totally ignored (buttons transparent, `h1` rendering at ~16px, etc.).

**Cause:** Astryx emits component theme overrides in `@layer astryx-theme`. An existing Tailwind app emits `@tailwind base` (preflight) **unlayered**. Per the cascade, *unlayered rules beat any `@layer` rule regardless of specificity* — so every Astryx theme override loses to preflight, silently.

**Fix (one line, but very non-obvious):**
```css
/* globals.css */
@layer tw-preflight { /* was: @tailwind base; (unlayered) */
@tailwind base;
}
```
Moving preflight into a named layer lets `@layer astryx-theme` win, while unlayered app utilities still beat preflight, so the legacy app is unaffected.

**Ask:** This should be front-and-center in an "adopting Astryx alongside Tailwind" doc. It's a total, silent failure mode for what is probably the single most common adoption scenario (Astryx into an existing Tailwind codebase).

---

### 2. Requires `moduleResolution: bundler` (or node16+), with no clear signpost

Astryx ships subpath `exports` (`@astryxdesign/core/Button`, `/theme`, `/Link`, ...). With the very common `"moduleResolution": "node"` these don't resolve. Switching to `"bundler"` fixed Astryx but is a **project-wide** change that broke unrelated imports in other packages (e.g. a dep whose `exports` map doesn't append extensions now needs explicit `.js`).

**Ask:** Document the required `moduleResolution` (`bundler`/`node16`+) in the getting-started/install docs, and mention it's project-wide so adopters can anticipate the fallout.

---

### 3. Custom variants aren't type-safe (generator targets wrong interface) — #3371

`components.button['variant:accentOutline']` emits correct CSS but a **broken** type augmentation (`XDSButtonVariantMap` instead of `ButtonVariantMap`), so `variant="accentOutline"` fails `TS2322`. Full details in #3371. Related: the generated `*.variants.d.ts` isn't referenced by the generated theme index, so even a correct augmentation wouldn't load without a manual side-effect import.

---

### 4. Swizzle → StyleX build cliff, undocumented (esp. Next/SWC) — #3373

`astryx swizzle` emits raw StyleX source that needs a build-time compiler; no docs cover setup, and the babel path breaks `next/font` under SWC. Full details in #3373.

---

### 5. Smaller papercuts

- **`defineTheme` typing friction:** typography weights must be string values; `lineHeight`/`fontWeight` must be strings; `url` isn't allowed on a typography role (fonts have to be loaded out-of-band). The constraints are reasonable but the type errors aren't self-explanatory; examples in the `theme` docs would help.
- **CLI discoverability:** `astryx component`, `astryx docs`, and `astryx search` are excellent and are the real source of truth for capabilities (custom variants, styling interop, etc.) — but nothing early in the onboarding flow points you to them, so it's easy to guess at limitations that don't exist. A prominent "start with `astryx docs` / `astryx component `" pointer would save time.

---

## Net

The theming model itself is a pleasure once it works — the friction is almost entirely at the **integration boundary** with an existing app (cascade layers, module resolution, StyleX build, and a couple of codegen/type gaps). A single "Adopting Astryx into an existing Next.js + Tailwind project" guide covering items 1, 2, and 4 would remove most of the pain.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.