Frontend Customization

Learn how to customize your Spiderly Angular application including theming, layout, service overrides, and UI components.

Overview

Spiderly offers full flexibility when it comes to frontend customization. While you're not required to use the default Angular-based UI or the Spiderly Angular library, doing so provides the best integration and experience.

This guide covers how to customize key elements of your Spiderly app, including: app name, logo, favicon, theme colors, layout, service overrides, and UI components.

Change the App Name

Open the Frontend\src\environments\environment.ts file and change the value of companyName to your the desired app name.

Locate the Frontend\src\assets\images\logo\logo.svg file and replace it with your own logo.svg.

If your logo file is not named logo.svg or you want to use a custom path, open the Frontend\src\app\business\services\config.service.ts file and override the logo path like this:

export class ConfigService extends ConfigBaseService {
  // ... other overrides
  override logoPath: string = 'assets/your-logo-path.png';
  // ...
}

Change the Favicon

Locate the Frontend\src\assets\images\logo\favicon.ico file and change it with your own favicon.ico.

Change Theme Colors

Open the Frontend\src\assets\primeng-theme.ts file and edit the theme values, such as the primary.

For more information and advanced theming options, visit the PrimeNG Theming Guide.

Using theme colors as Tailwind utilities

The generated Frontend\src\assets\tailwind.css imports tailwindcss-primeui, which bridges your PrimeNG theme to Tailwind. This means utilities such as bg-primary-50, text-primary-600, and border-surface-200 resolve to the live theme variables defined in primeng-theme.ts — change a color there and every utility follows.

The bridge import must stay before @import "tailwindcss/utilities"; it registers the surface/primary color tokens, and Tailwind only picks up tokens that exist when the utilities import runs. Tokens registered afterwards are silently ignored, leaving *-surface-* / *-primary-* as dead classes.

Tailwind CSS v4 defaults a bare border (with no color modifier) to currentColor, not a gray. Spiderly omits Tailwind's Preflight reset on purpose (to avoid clobbering PrimeNG base styles), so always pair a border with a color — e.g. border border-surface-200.

Enable Dark Theme

Open the Frontend\src\index.html file and add the dark class to the html tag, like this:

<!doctype html>
<html lang="en" class="dark">
  <head>
    // ...
  </head>
</html>

For more information and advanced dark theme options, visit the PrimeNG Dark Theme Guide.

Showing or Hiding a Field on the Details Page

Every field the generator renders into {YourEntityName}BaseDetailsComponent is exposed through a show{PropertyName}For{YourEntityName} input that defaults to true. Pass it from your details page to hide a field outright, or bind it to a condition to toggle the field at runtime — without editing the generated component.

Open the Frontend\src\app\pages\your-entity-name\your-entity-name-details.html file, locate the <your-entity-name-base-details> component, and add the input:

<your-entity-base-details
// ... other attributes
[show{{YourPropertyName}}For{{YourEntityName}}]="false"
></your-entity-base-details>

Names are PascalCase — for example [showEmailForUser]="false" hides the email field, while [showIsDisabledForUser]="isAdmin" shows it only when isAdmin is true.

Calendar fields additionally expose showTimeOn{PropertyName}For{YourEntityName} (defaults to false) to also render the time picker — e.g. [showTimeOnBirthDateForUser]="true".

Customize Routes

The spiderly add-new-entity CLI command automatically adds routes to Frontend\src\app\app.routes.ts. If you need to customize them, the generated routes look like this:

{
    path: 'your-entity-name-list', // URL for the list page (e.g., /product-list)
    loadComponent: () => import('./pages/your-entity-name/your-entity-name-list.component').then(c => c.YourEntityNameListComponent),
    canActivate: [AuthGuard],
},
{
    path: 'your-entity-name-list/:id', // URL for the details page (e.g., /product-list/123)
    loadComponent: () => import('./pages/your-entity-name/your-entity-name-details.component').then(c => c.YourEntityNameDetailsComponent),
    canActivate: [AuthGuard],
},

Customize the Navigation Menu

The spiderly add-new-entity CLI command automatically adds a menu item to Frontend\src\app\business\layout\layout.component.ts. If you need to customize it, the generated menu item looks like this:

{
    label: this.translocoService.translate('YourEntityNameList'),
    icon: 'pi pi-fw pi-list', // Refer to https://primeng.org/icons#list for available icons
    routerLink: ['/your-entity-name-list'],
},

Switching to a Top Menu Layout

By default, Spiderly generates your app with a side menu layout. However, if you'd prefer a top menu layout, you can easily update it by following these steps:

  1. Open the Frontend\src\app\business\layout\layout.component.html file.
  2. Update the layout component by setting the [isSideMenuLayout] attribute to false:
<spiderly-layout [menu]="menu" [isSideMenuLayout]="false"></spiderly-layout>

If you want to add custom actions (buttons, links, or any other content) to the header area, positioned to the left of the profile avatar, you can do so like this:

<spiderly-layout [menu]="menu" [isSideMenuLayout]="false">
  <div ACTIONS>Your custom actions</div>
</spiderly-layout>

Inject Content into the Login Screen

The login component (<spiderly-login>) exposes a loginExtra projection slot for consumer-supplied content — a bot-protection widget (e.g. Cloudflare Turnstile), a legal notice, or an extra field. Projected content renders in both the email-entry and code-verification states, so a single-use challenge widget stays mounted across the resend flow.

<spiderly-login [providerIcons]="providerIcons">
  <app-turnstile-widget loginExtra />
</spiderly-login>

Spiderly stays vendor-neutral — it only ships the slot. Attaching a token to the login request (e.g. an X-Turnstile-Token header) is done with a standard Angular HTTP interceptor in your own app, so the framework never depends on a specific bot-protection provider.

Service Overrides

Spiderly's Angular library uses base service classes that you extend in your project.

ConfigService

Extend ConfigServiceBase and override properties in Frontend\src\app\business\services\config.service.ts:

export class ConfigService extends ConfigBaseService {
  override logoPath: string = 'assets/my-custom-logo.png';
  override primaryColor: string = '#3498db';
  override companyName: string = 'My Company';
}

AuthService

Extend AuthServiceBase and override methods in Frontend\src\app\business\services\auth.service.ts:

  • onAfterLoginExternal() - Executes after external authentication (e.g., Google)
  • onAfterLogout() - Runs after logout completion
  • onAfterRefreshToken() - Triggers following token refresh
  • onAfterNgOnDestroy() - Custom cleanup during component destruction

Example

export class AuthService extends AuthServiceBase {
  override onAfterLoginExternal(): void {
    // Custom post-login logic
    this.analyticsService.trackLogin();
    this.router.navigate(['/dashboard']);
  }

  override onAfterLogout(): void {
    // Custom logout cleanup
    this.cacheService.clear();
    super.onAfterLogout();
  }
}

Generated Files

Spiderly generates several Angular/TypeScript files with the .generated.ts suffix. These files are regenerated on each build and should not be modified.

All generated files are located in Frontend\src\app\business\:

FilePurpose
entities\entities.generated.tsTypeScript classes mirroring your C# DTOs
services\api\api.service.generated.tsStrongly-typed API service methods
components\base-details.generated.tsBase detail components for entity forms
services\validators\validators.generated.tsForm validators matching your C# validation rules
enums\enums.generated.tsTypeScript enums matching your C# enums

To customize behavior, use the non-generated counterparts (e.g., api.service.ts extends ApiGeneratedService).

If you want to understand how these files are generated or create advanced customizations, you can explore the Angular generator source code in the Spiderly repository.

Using the Spiderly Data View Component

If you want to display data in a cleaner, card-based layout instead of a plain table — while still keeping filtering capabilities — you can use the spiderly-data-view Angular component.

In your html file:

<spiderly-data-view
  [getTableDataObservableMethod]="getYourEntityNameTableDataObservableMethod"
  [filters]="filters"
>
  <ng-template #cardBody [templateType]="templateType" let-item let-index="index">
    {{item.name}}
  </ng-template>
</spiderly-data-view>

In your ts file:

import { Component, OnInit } from '@angular/core';
import { TranslocoService } from '@jsverse/transloco';
import { ApiService } from 'src/app/business/services/api/api.service';
import {
  Filter,
  DataViewCardBody,
  Role,
  SpiderlyControlsModule,
  SpiderlyDataViewComponent,
  SpiderlyTemplateTypeDirective,
} from 'spiderly';

@Component({
  selector: 'your-component-name',
  templateUrl: './your-component-name.component.html',
  imports: [SpiderlyTemplateTypeDirective, SpiderlyDataViewComponent, SpiderlyControlsModule],
})
export class YourEntityNameDataViewComponent implements OnInit {
  templateType?: DataViewCardBody<YourEntityName>;
  filters: Filter<YourEntityName>[];

  getYourEntityNameTableDataObservableMethod = this.apiService.getYourEntityNameTableData;

  constructor(
    private apiService: ApiService,
    private translocoService: TranslocoService,
  ) {}

  ngOnInit() {
    this.filters = [
      { name: this.translocoService.translate('Name'), filterType: 'text', field: 'name' },
      {
        name: this.translocoService.translate('Id'),
        filterType: 'numeric',
        field: 'id',
        showMatchModes: true,
      },
      {
        name: this.translocoService.translate('CreatedAt'),
        filterType: 'date',
        field: 'createdAt',
        showMatchModes: true,
      },
    ];
  }
}