DEV Community

Yuuichi Eguchi
Yuuichi Eguchi

Posted on

@constela/server v4.1.0: SSR Style Evaluation Support

What is Constela?

Constela is a compiler-first UI framework where you describe UI behavior in a constrained JSON DSL. Instead of writing JavaScript/JSX, you write declarative JSON that gets validated, analyzed, and compiled into minimal runtime code.

New Feature in @constela/server v4.1.0

The renderToString function now accepts a styles option, allowing style presets to be passed for evaluation during server-side rendering. Style expressions are evaluated and output as CSS class strings.

How It Works

1. Define Style Presets

Constela's style system is similar to Tailwind Variants or CVA:

{
  "styles": {
    "button": {
      "base": "px-4 py-2 rounded font-medium transition-colors",
      "variants": {
        "variant": {
          "primary": "bg-blue-500 text-white hover:bg-blue-600",
          "secondary": "bg-gray-200 text-gray-800 hover:bg-gray-300",
          "danger": "bg-red-500 text-white hover:bg-red-600"
        },
        "size": {
          "sm": "text-sm px-3 py-1",
          "md": "text-base px-4 py-2",
          "lg": "text-lg px-6 py-3"
        }
      },
      "defaultVariants": {
        "variant": "primary",
        "size": "md"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

2. Use Style Expressions in Views

{
  "kind": "element",
  "tag": "button",
  "props": {
    "className": {
      "expr": "style",
      "name": "button",
      "variants": {
        "variant": { "expr": "state", "name": "currentVariant" }
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

3. Pass Styles to SSR

import { renderToString } from '@constela/server';

const html = await renderToString(compiledProgram, {
  styles: {
    button: {
      base: 'px-4 py-2 rounded',
      variants: {
        variant: {
          primary: 'bg-blue-500 text-white',
          secondary: 'bg-gray-200 text-gray-800',
        },
      },
      defaultVariants: { variant: 'primary' },
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

Output

<button class="px-4 py-2 rounded bg-blue-500 text-white">Click me</button>
Enter fullscreen mode Exit fullscreen mode

API Reference

interface RenderOptions {
  route?: {
    params?: Record<string, string>;
    query?: Record<string, string>;
    path?: string;
  };
  imports?: Record<string, unknown>;
  styles?: Record<string, StylePreset>;  // Added in v4.1.0
}

interface StylePreset {
  base: string;
  variants?: Record<string, Record<string, string>>;
  defaultVariants?: Record<string, string>;
}
Enter fullscreen mode Exit fullscreen mode

Why Constela?

Constela React/Next.js
UI authoring JSON DSL JavaScript/JSX
Execution Compiler-driven Runtime-driven
State updates Declarative actions Arbitrary JS
Errors Structured with JSON Pointer Runtime exceptions

Constela is optimized for:

  • AI-generated UI
  • Deterministic behavior
  • Inspectable state transitions

Get Started

npm install @constela/start
mkdir -p src/routes
Enter fullscreen mode Exit fullscreen mode

Create src/routes/index.json:

{
  "version": "1.0",
  "state": {
    "count": { "type": "number", "initial": 0 }
  },
  "actions": [
    {
      "name": "increment",
      "steps": [{ "do": "update", "target": "count", "operation": "increment" }]
    }
  ],
  "view": {
    "kind": "element",
    "tag": "button",
    "props": { "onClick": { "event": "click", "action": "increment" } },
    "children": [{ "kind": "text", "value": { "expr": "state", "name": "count" } }]
  }
}
Enter fullscreen mode Exit fullscreen mode

Run:

npx constela dev
Enter fullscreen mode Exit fullscreen mode

Summary

With @constela/server v4.1.0, style expressions are now evaluated during SSR. Just pass your style presets to the styles option in renderToString, and your styles will be applied on the server just like on the client.

If you're interested in Constela, give it a try. We welcome your feedback and issues on GitHub.

Links


@constela/server v4.1.0 is available now. Upgrade with npm install @constela/server@latest

Top comments (0)