Ludicord
Guide 07 · Build the UI

Styling

Use globals.css, optional Tailwind CSS, safe areas, and responsive Activity layouts.

Ludicord 3.1.0Public source 20c4889

Ludicord renders React, so standard CSS, CSS Modules, component libraries, and Tailwind CSS all work. The generator supports either Tailwind 4 or plain global CSS without exposing Vite configuration.

#Global styles

Import app/globals.css from app/pages.tsx. Use it for resets, design tokens, typography, and Discord safe-area variables.

csscss
1/* file: app/globals.css */
2@import "tailwindcss";
3
4:root {
5 color-scheme: dark;
6 --surface: #0b0c10;
7 --text: #f5f5f5;
8 --accent: #5865f2;
9 --ludicord-safe-top: var(--sait, env(safe-area-inset-top, 0px));
10 --ludicord-safe-bottom: var(--saib, env(safe-area-inset-bottom, 0px));
11 --ludicord-safe-left: var(--sail, env(safe-area-inset-left, 0px));
12 --ludicord-safe-right: var(--sair, env(safe-area-inset-right, 0px));
13}
14
15body {
16 margin: 0;
17 min-width: 320px;
18 background: var(--surface);
19 color: var(--text);
20}

#Use Tailwind CSS

Choose Tailwind during project creation, or install it in an existing app.

Terminalbash
1npm install tailwindcss
2npm install --save-dev @tailwindcss/vite

Add @import "tailwindcss"; to app/globals.css. Ludicord detects the integration. You do not need a vite.config file.

app/embeds/home/embed.tsxtsx
1export default function embed() {
2 return (
3 <main className="min-h-screen bg-black px-5 py-8 text-white">
4 <h1 className="text-4xl font-semibold tracking-tight">Game night</h1>
5 </main>
6 );
7}

#Respect safe areas

Discord can reserve space around the Activity on mobile or when controls overlap the viewport. Add safe-area values to interactive edges instead of hard-coding padding.

csscss
1.activity-shell {
2 padding-top: calc(1rem + var(--ludicord-safe-top));
3 padding-right: calc(1rem + var(--ludicord-safe-right));
4 padding-bottom: calc(1rem + var(--ludicord-safe-bottom));
5 padding-left: calc(1rem + var(--ludicord-safe-left));
6}

The CSS variables update from Discord layout events. useLudicordSafeArea() is available when JavaScript needs the numeric values, but CSS should handle ordinary layout.

#Design mobile first

Start with the smallest usable surface, then add space or columns when available. Avoid viewport assumptions based on a normal browser window: Discord Activities can be narrow, floating, embedded beside chat, or full screen.

PatternRecommendation
Primary actionsKeep reachable and at least 44px tall
SidebarsCollapse to a drawer or top selector
TablesWrap in horizontal overflow
Game canvasSize from its container, not only window.innerWidth
Fixed controlsInclude Discord safe-area insets
MotionRespect prefers-reduced-motion

#Use layout data only when CSS is not enough

useActivityLayoutMode() and useOrientation() can switch behavior, not just presentation. For visual changes, media or container queries are usually simpler and more resilient.

#Next step

Continue to State and effects to choose the correct state lifetime for local UI, saved preferences, server data, and live multiplayer state.