Skip to main content

Documentation Index

Fetch the complete documentation index at: https://learn.nexudus.com/llms.txt

Use this file to discover all available pages before exploring further.

The Members Portal uses Bootstrap 5.3 with SCSS customisation, CSS Modules for component-scoped styles, and CSS custom properties for runtime theming. This page explains how these layers work together and how to make changes at each level.

Architecture overview

┌──────────────────────────────────────────────────────┐
│  Runtime branding colours (per-location)             │  ← Highest priority
│  Injected via /api/scss-to-css endpoint              │
├──────────────────────────────────────────────────────┤
│  _user.scss                                          │  ← Project-level overrides
├──────────────────────────────────────────────────────┤
│  Component styles (.module.scss + global SCSS)       │
├──────────────────────────────────────────────────────┤
│  custom/ — Bootstrap component extensions            │
├──────────────────────────────────────────────────────┤
│  _variables.scss — Theme colour palette              │
├──────────────────────────────────────────────────────┤
│  _defaults.scss — Base colour defaults               │
├──────────────────────────────────────────────────────┤
│  Bootstrap 5.3 core                                  │  ← Lowest priority
└──────────────────────────────────────────────────────┘
Styles are compiled into a single CSS bundle. The compilation order in style.scss determines which layer can override which.

Folder structure

All SCSS source files live under src/assets/scss/:
src/assets/scss/
├── style.scss              # Main entry – imports everything in order
├── _defaults.scss          # Default colour palette ($primary, $secondary, …)
├── _variables.scss         # Derived theme colours, contrast values, CSS vars
├── _variables-dark.scss    # Dark-mode variable overrides
├── _dark-mode.scss         # Dark-theme component rules
├── _mobile.scss            # Mobile-only responsive overrides
├── _user.scss              # Project-level custom rules (safe to edit)
├── icon.css                # Icon font definitions
├── custom/                 # Bootstrap component extensions
│   ├── _utilities.scss     # Extra utility classes
│   ├── _buttons.scss
│   ├── _card.scss
│   ├── _navbar.scss
│   ├── forms/
│   │   ├── _form-check.scss
│   │   └── _form-control.scss
│   └── …
└── components/             # Global component styles
    ├── _general.scss
    ├── _avatar.scss
    ├── _navbar-mobile.scss
    ├── _sidebar-admin.scss
    ├── _utilities.scss
    ├── _stepper.scss
    └── vendor/             # Third-party library overrides
        ├── dayPicker.scss
        ├── flatpickr.scss
        └── …

Default colour palette

Default colours are defined in _defaults.scss using the !default flag, which means they can be overridden by any value set before the import:
// _defaults.scss
$primary:   #ff5b13 !default;
$secondary: #0f0d76 !default;
$success:   #008d42 !default;
$danger:    #dc2626 !default;
$warning:   #da7500 !default;
_variables.scss then derives contrast colours, subtle variants, and border colours from these base values and exports them as a $theme-colors map. Bootstrap uses this map to generate CSS custom properties like --bs-primary, --bs-primary-bg-subtle, etc.

How components are styled

Components use one of three patterns (often combined):

CSS Modules (scoped styles)

Component-specific styles live in a .module.scss file next to the component. Class names are locally scoped at build time so they never leak.
// ArkSmallCard.tsx
import styles from './ArkSmallCard.module.scss'

export default function ArkSmallCard({ image }: Props) {
  return <img className={styles.fullImage} src={image} />
}
// ArkSmallCard.module.scss
.fullImage {
  height: calc(100% - 100px);
  object-fit: cover;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
}
Use CSS custom properties inside .module.scss files to reference theme colours: color: var(--bs-primary);

Bootstrap utility classes

Most layout and spacing is handled with Bootstrap 5 utility classes directly in JSX:
<div className="d-flex justify-content-between align-items-center mt-3 px-4">
  <h5 className="text-truncate fs-5 fw-bold text-body">{title}</h5>
</div>
The project extends Bootstrap’s utility API in custom/_utilities.scss with additional helpers such as fixed-pixel heights (h-40px), viewport heights (vh-100), and more.

Global SCSS (unscoped)

Some components import a plain .scss file for global styles. These affect the entire page and are typically used for animation keyframes or third-party library overrides:
import './Typewriter.scss'
Prefer CSS Modules over global imports for new components. Global styles can cause unintended side-effects.

Runtime branding (per-location colours)

Each location can set its own brand colours in the Nexudus dashboard. The portal loads these at runtime through a two-step process:
  1. The client fetches /api/scss-to-css?businessId=<id>&hash=<colorHash>.
  2. The endpoint compiles a virtual SCSS file that overrides $primary, $secondary, etc. before importing the full style.scss.
  3. The compiled CSS is cached in Vercel Blob storage with a hash-based filename.
  4. An edge function serves the cached file with CDN headers for fast delivery.
The virtual SCSS that gets compiled looks like this:
$runtime: production;
$primary: #<locationColor>;
$secondary: #<locationColor>;
// … other overrides from the location's colour settings

@import 'style.scss';
Because _defaults.scss uses !default, the runtime values take precedence.

Dark mode

Dark mode is controlled via the data-bs-theme attribute on the <html> element. The _dark-mode.scss file redefines CSS custom properties when this attribute is set:
[data-bs-theme='dark'] {
  --bs-body-bg: #222529;
  --bs-body-color: #b0b0b8;
  --bs-border-color: rgba(255, 255, 255, 0.07);
  // … full dark palette
}
Theme switching is managed by the useLayoutContext hook:
const { updateTheme } = useLayoutContext()
updateTheme('dark')  // 'light' | 'dark' | 'auto'
The preference is saved to localStorage and restored on load.
When writing component styles, always use CSS custom properties (var(--bs-body-bg)) instead of hard-coded colour values. This ensures your styles work in both light and dark modes.

Extending Bootstrap utilities

Custom utility classes are registered in custom/_utilities.scss using Bootstrap’s utility API. To add a new utility:
// custom/_utilities.scss
$utilities: map-merge(
  $utilities,
  (
    "my-custom-util": (
      property: opacity,
      class: custom-opacity,
      values: (
        25: .25,
        50: .5,
        75: .75,
      )
    ),
  )
);
This generates classes like .custom-opacity-25, .custom-opacity-50, etc. with responsive variants if you add responsive: true.

Overriding Bootstrap component styles

Bootstrap component customisations live in custom/ as partial SCSS files (e.g., _buttons.scss, _card.scss). These are imported after Bootstrap core, so they can override default styles. To adjust a Bootstrap component:
1

Find the right partial

Look in src/assets/scss/custom/ for an existing file that matches the component (e.g., _buttons.scss for buttons).
2

Add your overrides

Write your SCSS rules in that file. You can use Bootstrap variables and mixins:
// custom/_buttons.scss
.btn {
  border-radius: 0.5rem;
  font-weight: 600;
}
3

Verify the import

Make sure the file is imported in style.scss. All existing partials are already imported.

Adding styles to a new component

1

Create a CSS Module file

Add a .module.scss file next to your component:
src/components/MyComponent/
├── MyComponent.tsx
└── MyComponent.module.scss
2

Write scoped styles

// MyComponent.module.scss
.wrapper {
  padding: 1rem;
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius);
  background: var(--bs-body-bg);
}
3

Import and use in the component

import styles from './MyComponent.module.scss'

export default function MyComponent() {
  return (
    <div className={styles.wrapper}>
      <p className="text-body fs-6 mb-0">Content</p>
    </div>
  )
}
Combine CSS Modules for component-specific layout with Bootstrap utilities for spacing and typography. This keeps styles scoped while reusing the design system.

The _user.scss file

_user.scss is imported last in style.scss and is intended for project-level custom rules that don’t belong to a specific component or Bootstrap override. It currently contains helpers like .sticky-top-20, .no-select, and .disabled-component. Add rules here when you need a global utility that doesn’t fit into Bootstrap’s utility API or a component module.

Key conventions

PracticeRationale
Use CSS Modules for new componentsPrevents style leaking between components
Use var(--bs-*) for coloursEnsures light/dark mode and branding compatibility
Never hard-code colour values in componentsRuntime branding would not apply
Put Bootstrap overrides in custom/Keeps overrides organized and discoverable
Put vendor/library overrides in components/vendor/Separates third-party concerns from project styles
Use !default for new SCSS variablesAllows runtime and theme-level overrides