Customization

Styling

Get started with styling your app.

To build the user web interface TurboStarter comes with Nativewind pre-configured.

Why Nativewind?

Nativewind is basically a Tailwind CSS for mobile apps. It gives you a way to style your app with Tailwind CSS utilities and classes.

Tailwind config

In the tooling/tailwind/config directory you will find shared Tailwind CSS configuration files. To change some global styles you can edit the files in this folder.

Here is an example of a shared Tailwind config file:

tooling/tailwind/config/base.ts
import type { Config } from "tailwindcss";
 
export default {
  darkMode: "class",
  content: ["src/**/*.{ts,tsx}"],
  theme: {
    extend: {
      colors: {
        ...
        primary: {
          DEFAULT: "hsl(var(--primary))",
          foreground: "hsl(var(--primary-foreground))",
        },
        secondary: {
          DEFAULT: "hsl(var(--secondary))",
          foreground: "hsl(var(--secondary-foreground))",
        },
        success: {
          DEFAULT: "hsl(var(--success))",
          foreground: "hsl(var(--success-foreground))",
        },
        ...
      },
    },
  },
  plugins: [animate, containerQueries, typography],
} satisfies Config;

As you can see, for the colors part, we bet stricly on CSS Variables in HSL format to allow for easy theme management without a need for any JavaScript.

Also, each app has its own tailwind.config.ts file which extends the shared config and allows you to override the global styles.

Here is an example of a app's tailwind.config.ts file:

apps/web/tailwind.config.ts
import type { Config } from "tailwindcss";
import nativewind from "nativewind/preset";
import { hairlineWidth } from "nativewind/theme";
 
import baseConfig from "@turbostarter/tailwind-config/mobile";
 
export default {
  // We need to append the path to the UI package to the content array so that
  // those classes are included correctly.
  content: [...baseConfig.content, "../../packages/ui/**/*.{ts,tsx}"],
  presets: [baseConfig, nativewind],
  theme: {
    extend: {
      fontFamily: {
        sans: ["DMSans_400Regular"],
        mono: ["DMMono_400Regular"],
      },
      borderWidth: {
        hairline: hairlineWidth(),
      },
    },
  },
} satisfies Config;

That way we can have a separation of concerns and a clear structure for the Tailwind CSS configuration.

Themes

Multiple themes on mobile coming soon

We're working on a way to allow for multiple themes on mobile as well. For now, you can only configure one theme and the dark mode for it.

See roadmap

TurboStarter comes with predefined theme that is defined in apps/mobile/src/styles/globals.css:

apps/mobile/src/styles/globals.css
:root {
  ...
  --background: 0 0% 100%;
  --foreground: 240 10% 3.9%;
  --card: 0 0% 100%;
  --card-foreground: 240 10% 3.9%;
  --popover: 0 0% 100%;
  ...
}

Feel free to add your own themes or override the existing ones to match your brand's identity.

Dark mode

TurboStarter comes with a built-in dark mode support.

Each theme has a corresponding dark mode variables which are used to change the theme to its dark mode counterpart.

apps/packages/ui/shared/themes/orange.css
.dark:root {
  ...
  --background: 220 37% 8%;
  --foreground: 0 0% 98%;
  --card: 240 10% 3.9%;
  --card-foreground: 0 0% 98%;
  --popover: 240 10% 3.9%;
  ...
}

As we define the darkMode as class in the shared Tailwind config, we need to add the dark class to the main layout to apply the dark mode styles - it's handled automatically for you by custom hooks and Nativewind utilities.

apps/mobile/src/app/_layout.tsx
import { useTheme } from "~/lib/hooks/use-theme";
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  const { isDark } = useTheme();
 
  return (
    <ThemeProvider value={isDark ? DarkTheme : DefaultTheme}>
      {children}
    </ThemeProvider>
  );
}

Nativewind

nativewind.dev

Last updated on

On this page

Ship your startup everywhere. In minutes.Get TurboStarter