FAQ and troubleshooting
The traps this build actually hit. Each one cost time to find, so they are written down rather than left for you to rediscover.
Layout
My stat cards get taller on wide screens
They are in a GridView with a childAspectRatio,
which ties height to width. Use KiteStatGrid:
fixed height, flexible width.
Aspect ratio is right for content that genuinely scales with size — thumbnails, media cards. It is wrong for anything with a fixed amount to say.
My maxWidth is being ignored
SingleChildScrollView passes a tight width constraint,
and ConstrainedBox cannot shrink below a tight incoming
constraint. Loosen it first:
SingleChildScrollView(
padding: const EdgeInsets.all(KiteSpace.xl),
child: Align( // ← without this, no-op
alignment: AlignmentDirectional.topStart,
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 960),
child: …,
),
),
)
A card in a Row has dead space at the bottom
Siblings in a Row stretch to match the tallest. Either give the
shorter card a footer of supporting facts, or drop the
IntrinsicHeight and let each size itself.
My layout breaks in Arabic
Something names a physical side. Alignment.topLeft,
EdgeInsets.only(left:), Border(right:) and
Positioned(right:) are all direction-agnostic — they stay
physically left even in RTL. See Localisation for the
directional equivalents.
Data and rendering
Pagination shows the wrong number of pages
ListResult.total is being set to the page length rather than the
row count. See Data layer — it comes from
X-Total-Count or Content-Range, not
rows.length.
Currency sorts wrongly
The value was formatted into a string before reaching the cell, so
$9.00 sorts after $1,264.55. Use
TrinaColumnType.currency and keep the numeric value.
A chart tooltip shows a long decimal
Pass valueLabel to KiteLineChart. Without it, a
hover prints the raw double.
"Unsupported operation: Not available for web"
Almost certainly ShadAvatar handed an empty string rather than
null — it renders its placeholder only when src is
null, and a non-null empty string reaches an image loader
that has no web implementation. KiteAvatar already guards this.
A disabled button looks enabled
Nulling onPressed is not enough — pass enabled: false,
which is what dims it.
Build and CI
CI fails on formatting but my code looks fine
You ran dart format lib/. CI runs
dart format --set-exit-if-changed . across the whole tree,
including test/. Run it from the project root.
The size job fails after I added a screen
Check the composition before raising the budget — fonts and assets are
usually the cause, not Dart. If the growth is legitimate, raise
WASM_GZIP_BUDGET_KB in the workflow and say why in the
commit. The budget exists to make growth visible, not to be moved quietly.
The architecture job fails
Something outside lib/kite_ui/ imports
package:shadcn_ui. Wrap what you need in
kite_ui and import that instead — see
the one rule.
Icons render as empty boxes
The font subsetter dropped the base Lucide family. Exactly one must survive;
the fonts CI job fails on zero or more than one.
Refreshing a detail page 404s
The host is not falling back to index.html for unknown paths.
See Deploying.
Product questions
Can I use forui, or plain Material, instead of shadcn_ui?
Yes — that is what kite_ui is for.
lib/kite_ui/_shadcn.dart is the single import surface; change it
and reimplement the wrappers. Nothing in features/ moves.
Why is the session lost on reload?
It is in-memory on purpose. Persisting it means choosing a storage package and a token format on your behalf — decisions that belong to your auth provider. See State for the two methods to change.
Is it really free?
MIT. Commercial use, no attribution required, no asterisk.
Something is missing or wrong here
Open an issue on GitHub. If it cost you an hour, it is worth a paragraph in these docs.