Styling
Use globals.css, optional Tailwind CSS, safe areas, and responsive Activity layouts.
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.
1/* file: app/globals.css */2@import "tailwindcss";34: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}1415body {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.
1npm install tailwindcss2npm install --save-dev @tailwindcss/vite
Add @import "tailwindcss"; to app/globals.css. Ludicord detects the integration. You do not need a vite.config file.
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.
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.
#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.