# Bootstrap Integration with Thymeleaf

## Dependency Setup

### Maven Dependencies

```xml
<dependencies>
    <!-- Thymeleaf starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>

    <!-- WebJars for Bootstrap -->
    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>bootstrap</artifactId>
        <version>5.3.2</version>
    </dependency>

    <!-- WebJars locator -->
    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>webjars-locator-core</artifactId>
    </dependency>

    <!-- Font Awesome for icons -->
    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>font-awesome</artifactId>
        <version>6.4.0</version>
    </dependency>
</dependencies>
```

### Gradle Dependencies

```gradle
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.webjars:bootstrap:5.3.2'
    implementation 'org.webjars:webjars-locator-core'
    implementation 'org.webjars:font-awesome:6.4.0'
}
```

## Base Layout with Bootstrap

### Main Layout Template

```html
<!DOCTYPE html>
<html
  xmlns:th="http://www.thymeleaf.org"
  th:replace="~{layout/base :: layout(~{::content})}"
  th:with="title=#{page.title}, 
               description=#{page.description}"
>
  <head th:fragment="head">
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="description" th:content="${description}" />
    <title th:text="${title}">Application Title</title>

    <!-- Bootstrap CSS -->
    <link
      th:href="@{/webjars/bootstrap/5.3.2/css/bootstrap.min.css}"
      rel="stylesheet"
    />

    <!-- Custom CSS -->
    <link th:href="@{/css/app.css}" rel="stylesheet" />

    <!-- Font Awesome -->
    <link
      th:href="@{/webjars/font-awesome/6.4.0/css/all.min.css}"
      rel="stylesheet"
    />
  </head>

  <body>
    <!-- Navigation -->
    <nav
      th:replace="~{fragments/navigation :: mainNav}"
      class="navbar navbar-expand-lg navbar-dark bg-dark"
    ></nav>

    <!-- Main Content -->
    <main class="container-fluid py-4">
      <div th:replace="~{::content}">Page content</div>
    </main>

    <!-- Footer -->
    <footer
      th:replace="~{fragments/footer :: footer}"
      class="bg-light text-center py-3"
    ></footer>

    <!-- Bootstrap JS Bundle -->
    <script
      th:src="@{/webjars/bootstrap/5.3.2/js/bootstrap.bundle.min.js}"
    ></script>

    <!-- Custom JS -->
    <script th:src="@{/js/app.js}"></script>
  </body>
</html>
```

## Navigation Components

### Main Navigation Bar

```html
<!-- fragments/navigation.html -->
<nav th:fragment="mainNav" class="navbar navbar-expand-lg navbar-dark bg-dark">
  <div class="container-fluid">
    <!-- Brand -->
    <a class="navbar-brand" th:href="@{/}" th:text="#{app.name}">App</a>

    <!-- Mobile toggle -->
    <button
      class="navbar-toggler"
      type="button"
      data-bs-toggle="collapse"
      data-bs-target="#navbarNav"
    >
      <span class="navbar-toggler-icon"></span>
    </button>

    <!-- Navigation items -->
    <div class="collapse navbar-collapse" id="navbarNav">
      <ul class="navbar-nav me-auto">
        <li class="nav-item">
          <a class="nav-link" th:href="@{/}" th:text="#{nav.home}">Home</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" th:href="@{/users}" th:text="#{nav.users}"
            >Users</a
          >
        </li>
        <li class="nav-item dropdown" sec:authorize="hasRole('ADMIN')">
          <a
            class="nav-link dropdown-toggle"
            href="#"
            role="button"
            data-bs-toggle="dropdown"
          >
            <span th:text="#{nav.admin}">Admin</span>
          </a>
          <ul class="dropdown-menu">
            <li>
              <a
                class="dropdown-item"
                th:href="@{/admin/dashboard}"
                th:text="#{nav.admin.dashboard}"
                >Dashboard</a
              >
            </li>
            <li>
              <a
                class="dropdown-item"
                th:href="@{/admin/settings}"
                th:text="#{nav.admin.settings}"
                >Settings</a
              >
            </li>
          </ul>
        </li>
      </ul>

      <!-- User menu -->
      <ul class="navbar-nav">
        <li class="nav-item dropdown" sec:authorize="isAuthenticated()">
          <a
            class="nav-link dropdown-toggle"
            href="#"
            role="button"
            data-bs-toggle="dropdown"
          >
            <i class="fas fa-user"></i>
            <span th:text="${#authentication.name}">User</span>
          </a>
          <ul class="dropdown-menu dropdown-menu-end">
            <li>
              <a
                class="dropdown-item"
                th:href="@{/profile}"
                th:text="#{nav.profile}"
                >Profile</a
              >
            </li>
            <li><hr class="dropdown-divider" /></li>
            <li>
              <a
                class="dropdown-item"
                th:href="@{/logout}"
                th:text="#{nav.logout}"
                >Logout</a
              >
            </li>
          </ul>
        </li>
        <li class="nav-item" sec:authorize="!isAuthenticated()">
          <a class="nav-link" th:href="@{/login}" th:text="#{nav.login}"
            >Login</a
          >
        </li>
      </ul>
    </div>
  </div>
</nav>
```

### Breadcrumb Navigation

```html
<!-- fragments/navigation.html -->
<nav th:fragment="breadcrumbs" aria-label="breadcrumb">
  <ol class="breadcrumb">
    <li class="breadcrumb-item">
      <a th:href="@{/}" th:text="#{nav.home}">Home</a>
    </li>
    <li class="breadcrumb-item" th:each="crumb,stat : ${breadcrumbs}">
      <a th:if="${not stat.last}" th:href="${crumb.url}" th:text="${crumb.name}"
        >Crumb</a
      >
      <span th:if="${stat.last}" th:text="${crumb.name}" class="active"
        >Current Page</span
      >
    </li>
  </ol>
</nav>
```

## Form Components

### Bootstrap Form Layout

```html
<!-- fragments/forms.html -->
<div th:fragment="formCard(title, action, object, fields)">
  <div class="card">
    <div class="card-header">
      <h5 class="card-title mb-0" th:text="${title}">Form Title</h5>
    </div>
    <div class="card-body">
      <form th:action="${action}" th:object="${object}" method="post">
        <!-- CSRF Token -->
        <input
          type="hidden"
          th:name="${_csrf.parameterName}"
          th:value="${_csrf.token}"
        />

        <!-- Dynamic fields -->
        <div th:each="field : ${fields}">
          <div th:replace="~{::formField(field)}"></div>
        </div>

        <!-- Form actions -->
        <div class="d-flex justify-content-end gap-2">
          <button type="submit" class="btn btn-primary" th:text="#{form.save}">
            Save
          </button>
          <a th:href="@{/}" class="btn btn-secondary" th:text="#{form.cancel}"
            >Cancel</a
          >
        </div>
      </form>
    </div>
  </div>
</div>

<!-- Individual form field -->
<div th:fragment="formField(field)" class="mb-3">
  <label
    th:for="${field.name}"
    th:text="#{form.${field.name}}"
    class="form-label"
    >Label</label
  >

  <!-- Input based on type -->
  <input
    th:if="${field.type == 'text'}"
    type="text"
    th:field="*{${field.name}}"
    th:placeholder="#{form.${field.name}.placeholder}"
    th:class="${field.required ? 'form-control is-invalid' : 'form-control'}"
    class="form-control"
  />

  <input
    th:if="${field.type == 'email'}"
    type="email"
    th:field="*{${field.name}}"
    th:placeholder="#{form.${field.name}.placeholder}"
    th:class="${field.required ? 'form-control is-invalid' : 'form-control'}"
    class="form-control"
  />

  <textarea
    th:if="${field.type == 'textarea'}"
    th:field="*{${field.name}}"
    th:placeholder="#{form.${field.name}.placeholder}"
    th:class="${field.required ? 'form-control is-invalid' : 'form-control'}"
    class="form-control"
    rows="4"
  ></textarea>

  <select
    th:if="${field.type == 'select'}"
    th:field="*{${field.name}}"
    th:class="${field.required ? 'form-control is-invalid' : 'form-control'}"
    class="form-select"
  >
    <option value="" th:text="#{form.select.placeholder}">Choose...</option>
    <option
      th:each="option : ${field.options}"
      th:value="${option.value}"
      th:text="${option.label}"
      th:selected="${option.value == field.value}"
    >
      Option
    </option>
  </select>

  <!-- Validation feedback -->
  <div th:if="${#fields.hasErrors(field.name)}" class="invalid-feedback">
    <span th:each="error : ${#fields.errors(field.name)}" th:text="${error}"
      >Error message</span
    >
  </div>

  <!-- Help text -->
  <div
    th:if="${field.help}"
    class="form-text text-muted"
    th:text="#{form.${field.name}.help}"
  >
    Help text
  </div>
</div>
```

### User Registration Form

```html
<div class="row justify-content-center">
  <div class="col-md-8">
    <div
      th:replace="~{fragments/forms :: formCard(
               title=#{user.register},
               action=@{/users/register},
               object=${user},
               fields=${registrationFields})}"
    ></div>
  </div>
</div>

<!-- Controller setup -->
<script th:inline="javascript">
  /*<![CDATA[*/
  window.registrationFields = [
    {name: 'username', type: 'text', required: true, help: 'username.help'},
    {name: 'email', type: 'email', required: true, help: 'email.help'},
    {name: 'password', type: 'password', required: true, help: 'password.help'},
    {name: 'confirmPassword', type: 'password', required: true, help: 'confirmPassword.help'},
    {name: 'role', type: 'select', required: true, options: ${userRoles}}
  ];
  /*]]>*/
</script>
```

## Data Display Components

### Bootstrap Tables

```html
<!-- fragments/tables.html -->
<table
  th:fragment="dataTable(items, columns, actions)"
  class="table table-striped table-hover"
>
  <thead class="table-dark">
    <tr>
      <th th:each="column : ${columns}" th:text="#{table.${column}}">Column</th>
      <th th:if="${actions}" th:text="#{table.actions}">Actions</th>
    </tr>
  </thead>
  <tbody>
    <tr th:each="item,stat : ${items}">
      <td th:each="column : ${columns}">
        <span th:text="${item[column]}">Data</span>
      </td>
      <td th:if="${actions}">
        <div class="btn-group" role="group">
          <a
            th:each="action : ${actions}"
            th:href="${action.url.replace('{id}', item.id)}"
            th:class="${action.class}"
            th:text="${action.label}"
            >Action</a
          >
        </div>
      </td>
    </tr>
  </tbody>
</table>

<!-- Empty state -->
<div th:fragment="emptyTable(message, createAction)" class="text-center py-4">
  <div class="alert alert-info">
    <i class="fas fa-info-circle"></i>
    <span th:text="${message}">No items found</span>
  </div>
  <a th:if="${createAction}" th:href="${createAction}" class="btn btn-primary">
    <i class="fas fa-plus"></i>
    <span th:text="#{action.create}">Create</span>
  </a>
</div>
```

### User List with Actions

```html
<div class="container-fluid">
  <div class="d-flex justify-content-between align-items-center mb-3">
    <h2 th:text="#{user.list.title}">Users</h2>
    <a th:href="@{/users/new}" class="btn btn-primary">
      <i class="fas fa-plus"></i>
      <span th:text="#{user.create}">Create User</span>
    </a>
  </div>

  <!-- Users table -->
  <table
    th:if="${not #lists.isEmpty(users)}"
    th:replace="~{fragments/tables :: dataTable(
                   items=${users},
                   columns=${userColumns},
                   actions=${userActions})}"
  ></table>

  <!-- Empty state -->
  <div
    th:if="${#lists.isEmpty(users)}"
    th:replace="~{fragments/tables :: emptyTable(
                   message=#{user.empty},
                   createAction=@{/users/new})}"
  ></div>
</div>

<script th:inline="javascript">
  /*<![CDATA[*/
  window.userColumns = ["name", "email", "role"];
  window.userActions = [
    {
      url: "/users/{id}/view",
      label: "#{action.view}",
      class: "btn btn-sm btn-info",
    },
    {
      url: "/users/{id}/edit",
      label: "#{action.edit}",
      class: "btn btn-sm btn-warning",
    },
    {
      url: "/users/{id}/delete",
      label: "#{action.delete}",
      class: "btn btn-sm btn-danger",
    },
  ];
  /*]]>*/
</script>
```

## Card Components

### User Profile Card

```html
<!-- fragments/cards.html -->
<div th:fragment="userCard(user, showActions)" class="card mb-3">
  <div class="card-header d-flex justify-content-between align-items-center">
    <h5 class="card-title mb-0" th:text="${user.name}">User Name</h5>
    <div th:if="${showActions}" class="dropdown">
      <button
        class="btn btn-sm btn-outline-secondary dropdown-toggle"
        type="button"
        data-bs-toggle="dropdown"
      >
        <i class="fas fa-ellipsis-v"></i>
      </button>
      <ul class="dropdown-menu dropdown-menu-end">
        <li>
          <a
            class="dropdown-item"
            th:href="@{/users/{id}/view(id=${user.id})}"
            th:text="#{action.view}"
            >View</a
          >
        </li>
        <li>
          <a
            class="dropdown-item"
            th:href="@{/users/{id}/edit(id=${user.id})}"
            th:text="#{action.edit}"
            >Edit</a
          >
        </li>
        <li><hr class="dropdown-divider" /></li>
        <li>
          <a
            class="dropdown-item text-danger"
            th:href="@{/users/{id}/delete(id=${user.id})}"
            th:text="#{action.delete}"
            >Delete</a
          >
        </li>
      </ul>
    </div>
  </div>

  <div class="card-body">
    <div class="row">
      <div class="col-md-3 text-center">
        <img
          th:src="@{/images/users/{id}.jpg(id=${user.id})}"
          th:alt="${user.name}"
          class="img-fluid rounded-circle mb-2 user-avatar"
        />
      </div>
      <div class="col-md-9">
        <p class="mb-1">
          <strong th:text="#{user.email}">Email:</strong>
          <span th:text="${user.email}">user@example.com</span>
        </p>
        <p class="mb-1">
          <strong th:text="#{user.role}">Role:</strong>
          <span class="badge bg-primary" th:text="${user.role}">USER</span>
        </p>
        <p class="mb-1">
          <strong th:text="#{user.created}">Created:</strong>
          <span th:text="${#dates.format(user.createdAt, 'MMM dd, yyyy')}"
            >Jan 01, 2024</span
          >
        </p>
        <p class="mb-0 text-muted">
          <small
            th:text="#{user.lastLogin(${#dates.format(user.lastLogin, 'MMM dd, yyyy')})}"
          >
            Last login: Jan 01, 2024
          </small>
        </p>
      </div>
    </div>
  </div>
</div>
```

### Dashboard Cards

```html
<div class="row">
  <!-- Stats cards -->
  <div class="col-xl-3 col-md-6 mb-4" th:each="stat : ${dashboardStats}">
    <div class="card border-left-primary shadow h-100 py-2">
      <div class="card-body">
        <div class="row no-gutters align-items-center">
          <div class="col mr-2">
            <div
              th:class="${stat.iconClass}"
              class="text-xs font-weight-bold text-primary text-uppercase mb-1"
            >
              <i th:class="${stat.icon}"></i>
            </div>
          </div>
          <div class="col-auto">
            <div
              class="text-xs font-weight-bold text-primary text-uppercase mb-1"
              th:text="${stat.label}"
            >
              Label
            </div>
            <div
              class="h5 mb-0 font-weight-bold text-gray-800"
              th:text="${stat.value}"
            >
              Value
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

<script th:inline="javascript">
  /*<![CDATA[*/
  window.dashboardStats = [
    {label: '#{stats.total.users}', value: ${totalUsers}, icon: 'fas fa-users', iconClass: 'fas fa-users fa-2x text-gray-300'},
    {label: '#{stats.active.users}', value: ${activeUsers}, icon: 'fas fa-user-check', iconClass: 'fas fa-user-check fa-2x text-gray-300'},
    {label: '#{stats.new.users}', value: ${newUsers}, icon: 'fas fa-user-plus', iconClass: 'fas fa-user-plus fa-2x text-gray-300'}
  ];
  /*]]>*/
</script>
```

## Modal Components

### Confirmation Modal

```html
<!-- fragments/modals.html -->
<div
  th:fragment="confirmModal(id, title, message, action)"
  class="modal fade"
  th:id="'confirmModal-' + ${id}"
  tabindex="-1"
  aria-labelledby="'confirmModalLabel-' + ${id}"
  aria-hidden="true"
>
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5
          class="modal-title"
          th:id="'confirmModalLabel-' + ${id}"
          th:text="${title}"
        >
          Confirm Action
        </h5>
        <button
          type="button"
          class="btn-close"
          data-bs-dismiss="modal"
          aria-label="Close"
        ></button>
      </div>
      <div class="modal-body">
        <p th:text="${message}">Are you sure?</p>
      </div>
      <div class="modal-footer">
        <button
          type="button"
          class="btn btn-secondary"
          data-bs-dismiss="modal"
          th:text="#{action.cancel}"
        >
          Cancel
        </button>
        <form th:action="${action}" method="post" style="display: inline;">
          <input
            type="hidden"
            th:name="${_csrf.parameterName}"
            th:value="${_csrf.token}"
          />
          <button
            type="submit"
            class="btn btn-danger"
            th:text="#{action.confirm}"
          >
            Confirm
          </button>
        </form>
      </div>
    </div>
  </div>
</div>
```

### Delete Confirmation Usage

```html
<!-- Trigger button -->
<button
  type="button"
  class="btn btn-sm btn-danger"
  data-bs-toggle="modal"
  th:data-bs-target="'#confirmModal-' + ${user.id}"
>
  <i class="fas fa-trash"></i>
  <span th:text="#{action.delete}">Delete</span>
</button>

<!-- Modal -->
<div
  th:replace="~{fragments/modals :: confirmModal(
               id=${user.id},
               title=#{user.delete.confirm},
               message=#{user.delete.message(${user.name})},
               action=@{/users/{id}/delete(id=${user.id})})}"
></div>
```

## Alert Components

### Bootstrap Alerts

```html
<!-- fragments/alerts.html -->
<div
  th:fragment="alert(type, message, dismissible)"
  th:class="'alert alert-' + ${type} + ' ' + ${dismissible ? 'alert-dismissible' : ''}"
  role="alert"
>
  <button
    th:if="${dismissible}"
    type="button"
    class="btn-close"
    data-bs-dismiss="alert"
    aria-label="Close"
  ></button>
  <span th:text="${message}">Alert message</span>
</div>

<!-- Success alert -->
<div
  th:if="${successMessage}"
  th:replace="~{fragments/alerts :: alert(type='success', message=${successMessage}, dismissible=true)}"
></div>

<!-- Error alert -->
<div
  th:if="${errorMessage}"
  th:replace="~{fragments/alerts :: alert(type='danger', message=${errorMessage}, dismissible=true)}"
></div>

<!-- Warning alert -->
<div
  th:if="${warningMessage}"
  th:replace="~{fragments/alerts :: alert(type='warning', message=${warningMessage}, dismissible=true)}"
></div>
```

## Responsive Design

### Responsive Grid Layout

```html
<!-- Responsive user cards -->
<div class="row">
  <div class="col-lg-4 col-md-6 mb-4" th:each="user : ${users}">
    <div
      th:replace="~{fragments/cards :: userCard(user=${user}, showActions=true)}"
    ></div>
  </div>
</div>

<!-- Responsive table -->
<div class="table-responsive">
  <table class="table table-striped table-hover">
    <!-- Table content -->
  </table>
</div>

<!-- Responsive navigation -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
  <div class="container-fluid">
    <!-- Brand and toggler for mobile -->
    <a class="navbar-brand" th:href="@{/}">App</a>
    <button
      class="navbar-toggler"
      type="button"
      data-bs-toggle="collapse"
      data-bs-target="#navbarNav"
    >
      <span class="navbar-toggler-icon"></span>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarNav">
      <!-- Navigation items -->
    </div>
  </div>
</nav>
```

## Custom Bootstrap Theme

### Theme Customization

```css
/* css/custom.css */
:root {
  --bs-primary: #335a7d;
  --bs-secondary: #6c757d;
  --bs-success: #28a745;
  --bs-danger: #dc3545;
  --bs-warning: #ffc107;
  --bs-info: #17a2b8;
  --bs-light: #f8f9fa;
  --bs-dark: #343a40;
}

/* Custom navbar */
.navbar-brand {
  font-weight: bold;
  font-size: 1.25rem;
}

.navbar-nav .nav-link {
  font-weight: 500;
  transition: color 0.3s ease;
}

.navbar-nav .nav-link:hover {
  color: var(--bs-primary) !important;
}

/* Custom cards */
.card {
  border: none;
  box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
  transition: transform 0.15s ease-in-out;
}

.card:hover {
  transform: translateY(-2px);
}

/* Custom buttons */
.btn-primary {
  background-color: var(--bs-primary);
  border-color: var(--bs-primary);
}

.btn-primary:hover {
  background-color: #2a4a63;
  border-color: #2a4a63;
}

/* Custom forms */
.form-control:focus {
  border-color: var(--bs-primary);
  box-shadow: 0 0 0 0.2rem rgba(51, 90, 125, 0.25);
}

.is-invalid {
  border-color: var(--bs-danger);
}

.invalid-feedback {
  color: var(--bs-danger);
  font-size: 0.875rem;
  margin-top: 0.25rem;
}
```

### Dark Mode Support

```html
<!-- Theme toggle in navigation -->
<li class="nav-item dropdown">
  <a
    class="nav-link dropdown-toggle"
    href="#"
    role="button"
    data-bs-toggle="dropdown"
  >
    <i class="fas fa-palette"></i>
    <span th:text="#{nav.theme}">Theme</span>
  </a>
  <ul class="dropdown-menu">
    <li>
      <button class="dropdown-item" onclick="setTheme('light')">
        <i class="fas fa-sun"></i>
        <span th:text="#{theme.light}">Light</span>
      </button>
    </li>
    <li>
      <button class="dropdown-item" onclick="setTheme('dark')">
        <i class="fas fa-moon"></i>
        <span th:text="#{theme.dark}">Dark</span>
      </button>
    </li>
  </ul>
</li>

<!-- Theme switching JavaScript -->
<script th:inline="javascript">
  /*<![CDATA[*/
  function setTheme(theme) {
    document.documentElement.setAttribute("data-bs-theme", theme);
    localStorage.setItem("theme", theme);
  }

  // Load saved theme
  document.addEventListener("DOMContentLoaded", function () {
    const savedTheme = localStorage.getItem("theme") || "light";
    setTheme(savedTheme);
  });
  /*]]>*/
</script>
```

## Integration Examples

### Complete Dashboard Page

```html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head th:replace="~{layout/base :: head}">
    <title th:text="#{dashboard.title}">Dashboard</title>
  </head>

  <body>
    <nav th:replace="~{fragments/navigation :: mainNav}"></nav>

    <main class="container-fluid py-4">
      <!-- Page header -->
      <div class="d-flex justify-content-between align-items-center mb-4">
        <h1 th:text="#{dashboard.title}">Dashboard</h1>
        <div>
          <button
            class="btn btn-outline-primary"
            data-bs-toggle="modal"
            data-bs-target="#newUserModal"
          >
            <i class="fas fa-plus"></i>
            <span th:text="#{user.create}">New User</span>
          </button>
        </div>
      </div>

      <!-- Stats cards -->
      <div th:replace="~{fragments/cards :: dashboardCards}"></div>

      <!-- Recent users table -->
      <div class="card mt-4">
        <div class="card-header">
          <h5 class="card-title mb-0" th:text="#{dashboard.recent.users}">
            Recent Users
          </h5>
        </div>
        <div class="card-body">
          <div
            th:if="${not #lists.isEmpty(recentUsers)}"
            th:replace="~{fragments/tables :: dataTable(
                         items=${recentUsers},
                         columns=${userColumns},
                         actions=${userActions})}"
          ></div>

          <div
            th:if="${#lists.isEmpty(recentUsers)}"
            th:replace="~{fragments/tables :: emptyTable(
                         message=#{dashboard.no.recent.users},
                         createAction=@{/users/new})}"
          ></div>
        </div>
      </div>
    </main>

    <!-- New user modal -->
    <div th:replace="~{fragments/modals :: userFormModal}"></div>

    <footer th:replace="~{fragments/footer :: footer}"></footer>
  </body>
</html>
```

This comprehensive Bootstrap integration provides:

- Responsive design with Bootstrap grid system
- Consistent navigation and layout components
- Form validation with Bootstrap styling
- Interactive components (modals, dropdowns)
- Theme support and customization
- Accessibility features with ARIA attributes
- Mobile-responsive navigation and tables
