Initial Setup

This guide covers how to set up Reef in a SolidStart application with full SSR support and StyleX integration.

Installation

Add the required dependencies to your project:

# Using bun
bun add @228-co/reef @stylexjs/stylex @stylexjs/unplugin

Vite Configuration

Configure the StyleX Vite plugin in your app.config.ts:

import { defineConfig } from "@solidjs/start/config";
import stylex from "@stylexjs/unplugin";

export default defineConfig({
  server: {
    preset: "cloudflare_module",
  },
  vite: {
    plugins: [
      stylex.vite({
        useCSSLayers: true,
        enableDevClassNames: true,
        treeshakeCompensation: true,
        unstable_moduleResolution: {
          type: "commonJS",
        },
      }),
    ],
  },
});

App Setup

Wrap your application with ReefProvider inside a Suspense boundary. The Suspense wrapper is required for proper SSR hydration.

// src/app.tsx
import "@228-co/reef/css-reset.css";
import { ReefProvider, ScrollRestoration } from "@228-co/reef/components";
import { chalkboardColors } from "@228-co/reef/themes/chalkboard.stylex";
import { textPageSizing } from "@228-co/reef/themes/text-page.stylex";
import { Router } from "@solidjs/router";
import { FileRoutes } from "@solidjs/start/router";
import { Suspense } from "solid-js";

export default function App() {
  return (
    <Router
      root={(props) => (
        <Suspense>
          <ReefProvider
            theme={{ sizing: textPageSizing, colors: chalkboardColors }}
          >
            <ScrollRestoration storageKey="my-app-scroll" />
            {props.children}
          </ReefProvider>
        </Suspense>
      )}
    >
      <FileRoutes />
    </Router>
  );
}

Important Notes

Suspense - Required wrapper for SSR hydration. Without it, you'll see hydration mismatch errors.

css-reset.css - Provides consistent baseline styles across browsers. Import this before any other styles.

ScrollRestoration - Optional component that persists scroll position across page refreshes.

SSR Theme Setup

To prevent a flash of unstyled content during SSR, apply the theme classes directly to the <html> element in your entry-server.tsx:

// src/entry-server.tsx
import { createHandler, StartServer } from "@solidjs/start/server";
import * as stylex from "@stylexjs/stylex";
import { rootStyle } from "@228-co/reef/root-styles.stylex";
import { chalkboardColors } from "@228-co/reef/themes/chalkboard.stylex";
import { textPageSizing } from "@228-co/reef/themes/text-page.stylex";

const themeProps = stylex.props(
  rootStyle.root,
  chalkboardColors,
  textPageSizing,
);

export default createHandler(() => (
  <StartServer
    document={({ assets, children, scripts }) => (
      <html lang="en" class={themeProps.className} style={themeProps.style}>
        <head>
          <meta charset="utf-8" />
          <meta name="viewport" content="width=device-width, initial-scale=1" />
          <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
          {assets}
        </head>
        <body>
          <div id="app">{children}</div>
          {scripts}
        </body>
      </html>
    )}
  />
));

This ensures the theme variables are available immediately when the page loads, eliminating any visual flash. The rootStyle.root applies base styles like background color and text color, while the theme overrides (chalkboardColors, textPageSizing) customize the visual appearance.

Available Themes

Color Themes

chalkboardColors - Dark theme with chalk-like colors, supports light/dark mode

whitePaperColors - Light theme optimized for readability

Sizing Presets

textPageSizing - Larger typography for content-heavy pages (blogs, docs, landing pages)

appPageSizing - Denser UI with smaller fonts for web applications

Using Components

Once set up, you can import and use Reef components in your routes:

import { Text, Button, Container } from "@228-co/reef/components";
import * as stylex from "@stylexjs/stylex";

const styles = stylex.create({
  page: {
    padding: "2rem",
    maxWidth: "800px",
    margin: "auto",
  },
});

export default function Home() {
  return (
    <main {...stylex.props(styles.page)}>
      <Text.H1>Welcome</Text.H1>
      <Text.body>
        This is a Reef-powered page with full SSR support.
      </Text.body>
      <Container status="info">
        <Text status="info">
          Components automatically use theme colors and sizing.
        </Text>
      </Container>
      <Button status="success">Get Started</Button>
    </main>
  );
}

Troubleshooting

Hydration Mismatch Errors

If you see hydration mismatch errors, ensure ReefProvider is wrapped in <Suspense>. This is required because some providers use client-side APIs.

Flash of Unstyled Content

If you see a flash when the page loads, make sure you've added the theme props to the <html> element in entry-server.tsx as shown above.

Missing Styles

Ensure the StyleX Vite plugin is configured correctly and that you've imported @228-co/reef/css-reset.css at the top of your app.tsx.