Templates Layouts & Components

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