Layouts and Components
Nimbus provides a flexible slot-based system for layouts and components. Keep your HTML DRY by reusing common components and page structures across your application.
§ Working with Layouts
Layouts define the outer shell of your pages (e.g. <html>, <head>, <body>, navigation headers, and footer blocks). Child templates insert their main content into the layout via the embed variable.
1. Define a Layout File
Create a layout file at resources/views/layout-app.nimbus:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title || "Default Title" }}</title>
</head>
<body class="bg-slate-50 text-slate-800">
<header class="bg-white border-b py-4">
<nav class="max-w-xl mx-auto px-4">
<a href="/">Dashboard</a>
</nav>
</header>
<main class="max-w-xl mx-auto px-4 py-8">
<!-- Child template contents are rendered here -->
{{{ embed }}}
</main>
</body>
</html>
2. Use the Layout in a Page Template
Place the @layout('layout-app') directive on the very first line of your page template:
@layout('layout-app')
<h1 class="text-2xl font-bold">Welcome Home</h1>
<p>This content is injected into layout-app's embed block.</p>
§ Creating Components
Components are reusable fragments of templates stored inside the resources/views/components/ directory. Any template file inside this folder automatically becomes available as a tag.
1. Build a Component Template
Create a card component at resources/views/components/card.nimbus. It receives nested content through the {{{ .slots.main }}} block:
<div class="p-5 rounded-lg border border-slate-200 bg-white shadow-sm">
<!-- Render main slot content -->
{{{ .slots.main }}}
</div>
2. Use Your Component
Consume the card component anywhere in your views using the @name() syntax:
@layout('layout-app')
<h1 class="mb-4">About Us</h1>
@card()
<h2 class="text-lg font-semibold">Our Team</h2>
<p>We build production-ready applications with Go and Nimbus!</p>
@end
Named Slots
For more complex components, you can define multiple named slots. This allows consumers to inject markup into specific locations of the component:
<div class="modal">
<div class="modal-header border-b">
{{{ .slots.header }}}
</div>
<div class="modal-body py-4">
{{{ .slots.main }}}
</div>
<div class="modal-footer border-t">
{{{ .slots.footer }}}
</div>
</div>
Render the component and specify values for each slot:
@modal()
@slot('header')
<h3 class="font-bold text-lg">Delete Account</h3>
@end
<p>Are you sure you want to delete your account? This action is irreversible.</p>
@slot('footer')
<button class="btn btn-danger">Delete</button>
<button class="btn">Cancel</button>
@end
@end