styled-ppx includes a native OCaml runtime —Documentation Index
Fetch the complete documentation index at: https://mintlify.com/davesnx/styled-ppx/llms.txt
Use this file to discover all available pages before exploring further.
styled-ppx.native — that implements emotion’s CSS hashing and injection algorithm entirely on the server. This makes it possible to use the same [%styled.div], [%cx], and related extensions in a native OCaml program or HTTP server, then extract all generated styles as a string or as a React <style> element for server-side rendering.
This guide assumes you have opam and dune installed and a server or native executable project to integrate with.
Install styled-ppx via opam
styled-ppx— the PPX binary that transforms[%styled.div {|...|}],[%cx {|...|}], and related extensions at compile time.styled-ppx.native— the native runtime library. It exposes theCSSmodule and implements emotion-compatible CSS storage, hashing, unique className generation, and autoprefixing — entirely in OCaml, with no JavaScript dependency.
Update your dune build files
Add For an
styled-ppx to (preprocess (pps ...)) and styled-ppx.native to (libraries ...) for every stanza that uses the extensions.For a (library ...) stanza:(executable ...) stanza:server-reason-react and server-reason-react-ppx are optional. They are only required if you use styled components ([%styled.div {||}]). If you only need [%cx] for className generation, you can omit them.Learn the native-only API
The
CSS module exposed by styled-ppx.native provides two server-side utilities not available in the browser runtimes:| Function | Return type | Description |
|---|---|---|
CSS.get_stylesheet() | string | Returns the full stylesheet as a raw CSS string containing all rules registered so far. |
CSS.style_tag | React.element | Returns a <style> React element with all styles injected. Designed for use with server-reason-react. |
CSS.get_string_style_hashes() | string | Returns a space-separated list of all registered style hashes. Required for client-side hydration. |
Write a plain native example
The simplest use case is a native OCaml program that generates classNames and prints the resulting stylesheet:Every call to
[%cx] registers its rules in a global stylesheet registry. CSS.get_stylesheet() drains that registry and returns the full CSS string, which you can embed in an HTML <style> tag or write to a .css file.Use CSS.style_tag with server-reason-react
When building an SSR application with To inject the stylesheet into the rendered HTML, add
server-reason-react, place <CSS.style_tag /> inside the <head> of your document component. It renders a <style> element containing all styles that have been registered up to that point:<CSS.style_tag /> to the document <head>:Advanced: the dynamic CSS / missing classNames problem
Consider this example:[%cx] calls inside the switch are only executed when React renders App. If CSS.style_tag is placed in the <head> and App is placed in the <body>, React renders the head first — at which point the dynamic classNames have not yet been registered.
The solution: render your React application to a string first, then inject the result as dangerouslySetInnerHTML in the <body>. This ensures that all [%cx] calls in App are executed before styles are collected:
ReactDOM.renderToString(<App />) runs synchronously before the outer renderToString(<Document />) reaches the <head>, all dynamic classNames are already registered when <CSS.style_tag /> is evaluated.
Advanced: client-side hydration
If you need the browser’s React to hydrate a server-rendered page, the<style> tag must carry the correct data-emotion attributes so that emotion on the client can recognise and reuse the server-injected styles.
Instead of CSS.style_tag, construct the element manually using CSS.get_string_style_hashes() and CSS.get_stylesheet():