### Example CSP response header with nonce
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Example HTTP response header after enabling CSP with nonce generation. The nonce value is generated per request.
```HTTP
Content-Security-Policy: default-src https: self:; script-src 'nonce-4ze2IRazk4Yu/j5K6SEzjA';
```
--------------------------------
### Pebble template example (home.html)
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Example Pebble template that renders a username if logged in, otherwise shows a not-logged-in message. Place this file at src/main/resources/views/home.html.
```html
Home
{% if loggedIn %}
username: {{ username }}
{% else %}
You are not logged in
{% endif %}
```
--------------------------------
### Freemarker template: src/main/resources/views/home.ftl
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Freemarker template that renders the example from the Views section. Uses the `loggedIn` variable to conditionally display the username or a login prompt.
```freemarker
Home
<#if loggedIn??>
username: ${username}
<#else>
You are not logged in
#if>
```
--------------------------------
### Renamed HTML output example
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Example of the HTML output after renaming, showing the CSS classes rewritten to 'a-b-c' and 'a-b-c-d'.
```html
... content, and stuff...
```
--------------------------------
### Login form HTML example
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
HTML login form that the fieldset annotations are meant to render. It posts username and password fields to /login.
```html
```
--------------------------------
### TurboFrameView controller example in Java, Python, Kotlin, Groovy
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Controller route annotated with @TurboFrameView("form") and @View("edit") that returns a message object. The same example is shown in Java, Python, Kotlin, and Groovy.
```java
@Produces(MediaType.TEXT_HTML)
@TurboFrameView("form")
@View("edit")
@Get
Map index() {
return Map.of("message", new Message(1L, "My message title", "My message content"));
}
```
```python
@Produces(MediaType.TEXT_HTML)
@TurboFrameView("form")
@View("edit")
@Get
def index(self) -> dict[str, object]:
return {"message": Message(1, "My message title", "My message content")}
```
```kotlin
@Produces(MediaType.TEXT_HTML)
@TurboFrameView("form")
@View("edit")
@Get
fun index() =
mapOf("message" to Message(1L, "My message title", "My message content"))
```
```groovy
@Produces(MediaType.TEXT_HTML)
@TurboFrameView("form")
@View("edit")
@Get
Map index() {
["message": new Message(id: 1L, name: "My message title", content: "My message content")]
}
```
--------------------------------
### Velocity template for home view
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Example Velocity template that conditionally displays a username or a login prompt.
```velocity
Home
#if( $loggedIn )
username: $username
#else
You are not logged in
#end
```
--------------------------------
### Controller rendering a template with the View annotation
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Example of a controller that renders a template by passing a model as a java.util.Map via the returned response object. Place file-based views in src/main/resources/views or set micronaut.views.folder to use a different folder.
```java
@Controller("/hello")
public class HelloController {
@View("hello")
@Get
public Map index() {
return Map.of("name", "Jason");
}
}
```
--------------------------------
### Handlebars template for home view
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Example Handlebars template that conditionally displays a username or a login prompt.
```handlebars
Home
{{#if loggedIn}}
username: {{username}}
{{else}}
You are not logged in
{{/if}}
```
--------------------------------
### Thymeleaf template and layout files
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Thymeleaf template and layout files for the example shown in the Views section. The template uses th:replace to include the layout, and the layout defines a fragment with title and content parameters.
```HTML
Home
username:
You are not logged in
```
```HTML
Layout Title
Layout H1
```
--------------------------------
### HTML form for book save
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Example HTML form that the application should display. It posts to /books/save with fields for title and pages, including validation attributes (minlength, maxlength, min, max, required).
```html
```
--------------------------------
### Configure webpack.client.js for Micronaut React SSR
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Webpack client configuration for a Micronaut React SSR setup. It bundles client.js and outputs to src/main/resources/views/static, defining SERVER as false and using Babel with React presets.
```javascript
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: ['./client.js'],
devtool: false,
output: {
path: path.resolve(__dirname, '../resources/views/static'),
filename: 'client.js',
},
plugins: [
new webpack.DefinePlugin({
SERVER: false,
})
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react']
}
}
}
]
}
};
```
--------------------------------
### Render Turbo Stream with TurboStreamRenderer
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Renders a Turbo Stream with a server-side template using TurboStreamRenderer. Builds a TurboStream with an APPEND action, target DOM ID "dom_id", and a template view named "fruit" with a model containing a Fruit instance, then renders it to an Optional. The example is shown in Java, Python, Kotlin, and Groovy.
```Java
String view = "fruit";
Map model = Collections.singletonMap("fruit", new Fruit("Banana", "Yellow"));
TurboStream.Builder builder = TurboStream.builder()
.action(TurboStreamAction.APPEND)
.targetDomId("dom_id")
.template(view, model);
Optional writable = turboStreamRenderer.render(builder, null);
```
```Python
view = "fruit"
model = {"fruit": Fruit("Banana", "Yellow")}
builder = (TurboStream.builder()
.action(TurboStreamAction.APPEND)
.targetDomId("dom_id")
.template(view, model))
writable = turbo_stream_renderer.render(builder, None)
```
```Kotlin
val view = "fruit"
val model = mapOf("fruit" to Fruit("Banana", "Yellow"))
val builder = TurboStream.builder()
.action(TurboStreamAction.APPEND)
.targetDomId("dom_id")
.template(view, model)
val writable = turboStreamRenderer.render(builder, null)
```
```Groovy
String view = "fruit"
Map model = Collections.singletonMap("fruit", new Fruit("Banana", "Yellow"))
TurboStream.Builder builder = TurboStream.builder()
.action(TurboStreamAction.APPEND)
.targetDomId("dom_id")
.template(view, model)
Optional writable = turboStreamRenderer.render(builder, null)
```
--------------------------------
### Enable CSP with micronaut.views.csp.enabled=true
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Enable Micronaut Views CSP by setting micronaut.views.csp.enabled=true. Shown in all supported configuration formats.
```Properties
micronaut.views.csp.enabled=true
```
```Yaml
micronaut:
views:
csp:
enabled: true
```
```Toml
micronaut = {views = {csp = {enabled = true}}}
```
```Groovy
micronaut {
views {
csp {
enabled = true
}
}
}
```
```Hocon
{
micronaut {
views {
csp {
enabled = true
}
}
}
}
```
```JSON
{
"micronaut": {
"views": {
"csp": {
"enabled": true
}
}
}
}
```
--------------------------------
### Return POJO to view with @View and @Get
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Controller method returning a POJO annotated with @Introspected to a view. The method is annotated with @View("fruits") and @Get, and returns a new Fruit instance. The same example is shown in Java, Python, Kotlin, and Groovy.
```Java
@View("fruits")
@Get
public Fruit index() {
return new Fruit("apple", "red");
}
```
```Python
@View("fruits")
@Get
def index(self) -> Fruit:
return Fruit("apple", "red")
```
```Kotlin
@View("fruits")
@Get
fun index() = Fruit("apple", "red")
```
```Groovy
@View("fruits")
@Get
Fruit index() {
return new Fruit("apple", "red")
}
```
--------------------------------
### GET /turbofruit
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Documentation for the GET /turbofruit endpoint that uses the @TurboStreamView annotation to render Turbo Streams.
```APIDOC
## [GET] /turbofruit
### Description
Renders a Turbo Stream response by annotating a controller route with @TurboStreamView. The route returns a map containing a fruit object, which is rendered as a Turbo Stream template.
### Method
GET
### Endpoint
/turbofruit
### Parameters
#### Query Parameters
None
#### Request Body
None
### Request Example
```
HttpRequest> request = HttpRequest.GET("/turbofruit")
.accept(TurboMediaType.TURBO_STREAM, MediaType.TEXT_HTML, MediaType.APPLICATION_XHTML)
.header(TurboHttpHeaders.TURBO_FRAME, "dom_id");
```
### Response
#### Success Response (200)
- **Content-Type**: text/vnd.turbo-stream.html
- **Body**: A Turbo Stream HTML fragment with action "append" and target "dom_id"
#### Response Example
```
""+
"" +
"fruit: Banana
\n" +
"color: Yellow
\n" +
"" +
""
```
```
--------------------------------
### CustomSoyFileSetProvider implementation
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
A naive implementation of SoyFileSetProvider that loads Soy templates from the configured views folder. It uses the resource loader to find each template file and adds it to a SoyFileSet builder.
```java
@Singleton
public class CustomSoyFileSetProvider implements SoyFileSetProvider {
private static final Logger LOG = LoggerFactory.getLogger(CustomSoyFileSetProvider.class);
private static final String[] VIEWS = {
"home.soy"
};
private final String folder;
private final ResourceLoader resourceLoader;
public CustomSoyFileSetProvider(ViewsConfiguration viewsConfiguration, ResourceLoader resourceLoader) {
this.folder = viewsConfiguration.getFolder();
this.resourceLoader = resourceLoader;
}
@Override
public SoyFileSet provideSoyFileSet() {
final SoyFileSet.Builder builder = SoyFileSet.builder();
for (final String template : VIEWS) {
resourceLoader.getResource(folder + "/" + template).ifPresent(url -> {
try {
builder.add(new File(url.toURI()));
} catch (URISyntaxException e) {
if (LOG.isWarnEnabled()) {
LOG.warn("URISyntaxException raised while generating the SoyFileSet for folder {}",
folder, e);
}
}
});
}
return builder.build();
}
}
```
```python
@Singleton
class CustomSoyFileSetProvider(SoyFileSetProvider):
VIEWS = ["home.soy"]
def __init__(self, views_configuration: ViewsConfiguration, resource_loader: ResourceLoader):
self.folder = views_configuration.getFolder()
self.resource_loader = resource_loader
def provideSoyFileSet(self) -> SoyFileSet:
builder = SoyFileSet.builder()
for template in self.VIEWS:
url = self.resource_loader.getResource(self.folder + "/" + template)
if url.isPresent():
try:
builder.add(File(url.get().toURI()))
except Exception:
LOG.warning("Exception raised while generating the SoyFileSet for folder %s", self.folder, exc_info=True)
return builder.build()
```
--------------------------------
### Create server.js for React SSR
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Server-side entry point for React SSR. Imports and re-exports React, ReactDOMServer, and page components. The bundle must be compatible with GraalJS, which is not NodeJS and doesn't support the same APIs.
```javascript
import React from 'react';
import ReactDOMServer from 'react-dom/server';
// Page components
import App from './components/App';
export { React, ReactDOMServer, App };
```
--------------------------------
### Scaffold a Micronaut project with views-react using mn CLI
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Use the Micronaut CLI to scaffold a new project with ReactJS views support. The --features=views-react flag enables the views-react feature, and the project name is my-cool-project. The build system (Gradle or Maven) is selected with the --build flag; Gradle is recommended for faster builds.
```bash
$ mn create-app --features=views-react my-cool-project
```
--------------------------------
### Minified CSS matching renamed classes
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Example of the minified CSS that matches the renamed classes, with rules for 'a-b-c' and 'a-b-c-d'.
```css
.a-b-c{color:blue;}.a-b-c-d{background:yellow;}
```
--------------------------------
### Generate renaming map with Closure Stylesheets
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Generate a JSON renaming map with Closure Stylesheets. The command outputs the map to `src/main/resources/renaming-map.json` and the minified CSS to `src/main/resources/styles/app-styles.min.css`.
```bash
> java -jar closure-stylesheets.jar \
--output-renaming-map-format JSON \
--output-renaming-map src/main/resources/renaming-map.json \
--rename CLOSURE \
[...inputs...] > src/main/resources/styles/app-styles.min.css
```
--------------------------------
### Create client.js for React hydration
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Client-side entry point that hydrates the React app after page load. Uses dynamic import to load the page component specified by Micronaut.rootComponent and hydrates the root with Micronaut.rootProps.
```javascript
import React from 'react';
import {hydrateRoot} from 'react-dom/client';
const pageComponentName = Micronaut.rootComponent;
import(`./components/${pageComponentName}.js`).then(module => {
const PageComponent = module[pageComponentName]
hydrateRoot(document, )
})
```
--------------------------------
### Render Turbo Streams with @TurboStreamView
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Annotate a controller route with @TurboStreamView to render Turbo Streams. The action is APPEND and the view is "fruit". The route is /turbofruit and returns a map with a Fruit object.
```Java
@Produces(value = {MediaType.TEXT_HTML, TurboMediaType.TURBO_STREAM})
@TurboStreamView(value = "fruit", action = TurboStreamAction.APPEND)
@Get("/turbofruit")
Map show() {
return Collections.singletonMap("fruit", new Fruit("Banana", "Yellow"));
}
```
```Python
@Produces(value=[MediaType.TEXT_HTML, TurboMediaType.TURBO_STREAM])
@TurboStreamView(value="fruit", action=TurboStreamAction.APPEND)
@Get("/turbofruit")
def show(self) -> dict[str, object]:
return {"fruit": Fruit("Banana", "Yellow")}
```
```Kotlin
@Produces(value = [MediaType.TEXT_HTML, TurboMediaType.TURBO_STREAM])
@TurboStreamView(value = "fruit", action = TurboStreamAction.APPEND)
@Get("/turbofruit")
fun show() = mapOf("fruit" to Fruit("Banana", "Yellow"))
```
```Groovy
@Produces(value = [MediaType.TEXT_HTML, TurboMediaType.TURBO_STREAM])
@TurboStreamView(value = "fruit", action = TurboStreamAction.APPEND)
@Get("/turbofruit")
Map show() {
return Collections.singletonMap("fruit", new Fruit("Banana", "Yellow"));
}
```
--------------------------------
### Preact client.js for Micronaut React SSR
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Client-side hydration entry point for Preact. Dynamically imports the page component based on `Micronaut.rootComponent` and renders it with `Micronaut.rootProps` into the document. Used as `client.js` in the Micronaut React SSR setup.
```javascript
import {h, render} from 'preact'
const pageComponentName = Micronaut.rootComponent;
import(`./components/${pageComponentName}.js`).then(module => {
const PageComponent = module[pageComponentName]
render(h(PageComponent, Micronaut.rootProps, null), document)
})
```
--------------------------------
### Compile Soy templates with SoyToJbcSrcCompiler
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Compile Soy templates to Java bytecode. This step is required before providing the renaming map to Micronaut Views Soy.
```bash
> java -jar SoyToJbcSrcCompiler.jar \
--output templates.jar \
--srcs [...templates...];
```
--------------------------------
### Generated Turbo Stream HTML output
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
The generated Turbo Stream HTML string from the previous example. The output is a turbo-stream element with action "append" and target "dom_id", containing the template content.
```Java
"" +
"" +
"Content to append to container designated with the dom_id." +
"" +
""
```
```Python
""
""
"Content to append to container designated with the dom_id."
""
""
```
```Kotlin
"" +
"" +
"Content to append to container designated with the dom_id." +
"" +
""
```
```Groovy
'' +
'' +
'Content to append to container designated with the dom_id.' +
'' +
''
```
--------------------------------
### Kotlin RewriteMapProvider implementing SoyNamingMapProvider
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Kotlin implementation of SoyNamingMapProvider that loads a JSON renaming map from a resource and provides a SoyCssRenamingMap. The map is loaded lazily and defaults to an empty map if the resource is missing.
```kotlin
@Singleton
class RewriteMapProvider(resourceLoader: ResourceLoader, jsonMapper: JsonMapper) : SoyNamingMapProvider {
private val cssRenamingMap: Map =
// load the renaming map embedded as a resource
resourceLoader.getResourceAsStream(RENAMING_MAP_NAME).map { json ->
json.use { jsonMapper.readValue(it, Argument.mapOf(String::class.java, String::class.java)) }
}.orElse(emptyMap())
/**
* Provide a CSS renaming map to Soy/Micronaut.
*
* @return Inflated Soy CSS renaming map.
*/
override fun cssRenamingMap(): SoyCssRenamingMap {
// (or whatever logic you need to rewrite the class)
return SoyCssRenamingMap { className -> cssRenamingMap[className] }
}
companion object {
/** Filename for the JSON class renaming map. */
private const val RENAMING_MAP_NAME = "renaming-map.json"
}
}
```
--------------------------------
### Bind HtmxRequestHeaders in controller method (Java, Python, Kotlin, Groovy)
Source: https://micronaut-projects.github.io/micronaut-views/latest/guide/index.html
Bind HtmxRequestHeaders in a controller method. The parameter is bound when the request is an HTMX request; otherwise it is null. The example returns a different view depending on whether the header is present.
```java
@Get
ModelAndView