logo

Examples

Real usage examples of the runtime, templates and build system

SPA → MPA → Reactive state → Router → DI

This section provides practical examples of how to use the ecosystem in real-world scenarios, covering both SPA and MPA application patterns. The examples demonstrate how the runtime, build system and templates work together to create scalable frontend architectures.

You can explore how to bootstrap applications, configure routing and implement reactive state management without relying on heavy frameworks. SPA examples highlight component-based architecture, dependency injection and lifecycle handling powered by the runtime engine. MPA examples focus on lightweight setups with manual initialization and direct DOM bindings.

Each example is designed to show how different parts of the system can be used independently or combined depending on project requirements. The comparison between SPA and MPA approaches helps to understand trade-offs in terms of complexity, performance and scalability. Special attention is given to the reactive data flow and how state changes propagate to the DOM.

These examples serve as a reference for building both simple pages and complex applications. The goal is to provide clear, minimal and production-oriented patterns that can be adapted to different use cases. By studying these examples, developers can quickly understand how to structure their projects and apply the ecosystem effectively.

SPA Example

Full application powered by runtime: router, DI, lifecycle and reactive state

app.ts
import { bootstrapApplication, provideRouter } from '@razerspine/runtime';

bootstrapApplication({
  providers: [
    provideRouter([
      { path: '/', component: HomePage }
    ])
  ]
});
component.ts
export class HomePage extends BaseComponent {
  increment() {
    this.setState({ count: this.state.count + 1 });
  }
}

Router & Guards

routes.ts
const routes = [
  { path: '/', component: HomePage },
  { path: '/dashboard', component: DashboardPage, canActivate: [authGuard] }
];
guard.ts
const authGuard = () => {
  return isLoggedIn ? true : '/login';
};

MPA Example

Lightweight reactive page without router and component system

home.ts
const { state } = createStore(
  { title: 'Hello MPA', count: 0 },
  () => update()
);

function update() {
  applyBindings(document.body, state);
}
template.pug
h1(data-bind="title")
button(data-click="increment") +
span(data-bind="count")

SPA vs MPA

Comparison
SPA → Router + Components + Lifecycle (automatic)
MPA → Manual setup + no router + independent pages

Reactivity Flow

Flow
createStore → Proxy → state change → applyBindings → DOM update

Template System

Templates
SPA + SCSS + TS → spa-pug-scss-ts
MPA + LESS + JS → mpa-pug-less-js

Templates are resolved automatically based on CLI flags

Advanced Runtime Example

Real-world example with API requests, dependency injection and reactive state

user.service.ts
import { ApiService } from '@razerspine/runtime';

export class UserService {
  private api = new ApiService('https://api.example.com');

  async getUsers() {
    return this.api.get('/users');
  }
}
component.ts
import { BaseComponent, inject } from '@razerspine/runtime';
import { UserService } from './user.service';

export class UsersPage extends BaseComponent {
  private userService = inject(UserService);

  constructor(container) {
    super(container, { users: [], loading: true });
  }

  protected async onInit() {
    const users = await this.userService.getUsers();
    this.setState({ users, loading: false });
  }
}
template.pug
section
  h1 Users

  div(data-show="loading") Loading...

  ul(data-for="user:users")
    li(data-bind="user.name")

Dependency Injection & Navigation

Using injected services for navigation and business logic

login.ts
import { inject, Router } from '@razerspine/runtime';

export class LoginPage {
  private router = inject(Router);

  onLoginSuccess() {
    this.router.navigate('/dashboard');
  }
}

Platform Services

Built-in services for theming and internationalization

platform.ts
import { ThemeService, TranslationService } from '@razerspine/runtime';

const theme = new ThemeService();
theme.init();
theme.setTheme('dark');

const i18n = new TranslationService({
  en: { greeting: { hello: 'Hello' } },
  uk: { greeting: { hello: 'Привіт' } }
});

i18n.init();

Reactive Flow

Internal data flow from user interaction to DOM updates

Flow
user event
  → method call
  → state mutation
  → Proxy intercept
  → update()
  → applyBindings()
  → DOM update

When to Use SPA vs MPA

Use Cases
SPA → dashboards, admin panels, complex UI
MPA → landing pages, marketing sites, SEO-driven content

Getting Started

To create a new project using the CLI, follow the quick start guide.

Open CLI Guide