Ruact.configure
Configure ruact via Ruact.configure in an initializer.
Setup
The install generator creates config/initializers/ruact.rb:
# config/initializers/ruact.rb
Ruact.configure do |config|
# config.manifest_path = Rails.root.join("public", "react-client-manifest.json")
# config.strict_serialization = true
# config.suspense_timeout = 5.0
# config.vite_dev_server = "http://localhost:5173"
endAll settings have sensible defaults. You only need to set the ones you want to override.
Configuration Options
manifest_path
Type: String, Pathname, or nilDefault: Rails.root.join("public/react-client-manifest.json")
Path to the react-client-manifest.json generated by the Vite plugin. Override this if you move the manifest to a non-default location.
config.manifest_path = Rails.root.join("public", "rsc-manifest.json")The manifest is loaded once at boot time (via Rails' to_prepare hook) and cached for the lifetime of the process. It is not re-read on every request.
strict_serialization
Type: BooleanDefault: false in development/test, true in production
When true, objects without an explicit ruact_props declaration raise Ruact::SerializationError instead of falling back to as_json. This prevents accidental attribute exposure in production.
# Explicitly opt in to strict mode in all environments
config.strict_serialization = trueRecommended: enable strict mode in production. Disable in development for faster prototyping.
suspense_timeout
Type: FloatDefault: 5.0 (seconds)
Maximum time (in seconds) ruact waits for a deferred Suspense chunk to resolve before timing out. After a timeout, the Suspense boundary emits an error row.
config.suspense_timeout = 10.0This setting only applies when streaming is enabled (ActionController::Live included).
vite_dev_server
Type: StringDefault: "http://localhost:5173"
Base URL of the Vite dev server. ruact uses this to inject the correct <script> tags into the HTML shell during development.
config.vite_dev_server = "http://localhost:3036"In production, Vite is not used — production assets are served from public/assets/.
signed_global_id_default_purpose
Type: Symbol | String | nilDefault: nil
App-wide default for: purpose used by Ruact.signed_global_id / Ruact.locate_signed when a call omits for:. A purpose scopes a signed reference to one use-site. Left nil, ruact requires an explicit for: per call and raises rather than sign an unscoped token.
config.signed_global_id_default_purpose = :ruact_refsigned_global_id_default_expires_in
Type: ActiveSupport::Duration | nilDefault: nil
App-wide default token lifetime used when a call omits expires_in:. Must be an ActiveSupport::Duration (e.g. 15.minutes). Left nil, ruact requires an explicit expires_in: per call and raises rather than mint a non-expiring token; pass an explicit expires_in: nil at the call site to deliberately opt into a non-expiring token.
config.signed_global_id_default_expires_in = 15.minutesAccessing configuration at runtime
# Read the current config
Ruact.config.manifest_path
Ruact.config.strict_serialization
# Access the loaded manifest (post-boot)
Ruact.manifest # => Ruact::ClientManifest instanceFull example
# config/initializers/ruact.rb
Ruact.configure do |config|
# Custom manifest location
config.manifest_path = Rails.root.join("public", "react-client-manifest.json")
# Strict mode in production — prevents accidental data leaks
config.strict_serialization = Rails.env.production?
# 10-second timeout for slow data fetches
config.suspense_timeout = 10.0
# Custom Vite port (if you changed it in vite.config.js)
config.vite_dev_server = "http://localhost:5173"
end