In Cossack, src/App.ts is a special component that acts as the root wrapper for your entire application. Unlike regular pages or layouts, the App component is never destroyed during client-side navigation.
Purpose
Use the App component for:
- Global State: Store data that needs to persist across all pages (e.g., user session, theme preference, shopping cart).
- Persistent UI: Render elements that stay fixed while the page changes (e.g., a music player, global toast notifications, floating action buttons).
- Providers: Wrap your application in context providers if you are using libraries that require them.
Usage
The App component is a standard Cossack component defined in packages/framework/src/App.ts. It must implement a template method that accepts children.
import { Cossack, Page, State } from '@cossackframework/core'; import { html, type TemplateResult } from '@cossackframework/renderer'; @Page({ transport: 'http' }) export class App extends Cossack { @State() theme: 'light' | 'dark' = 'light'; toggleTheme() { this.theme = this.theme === 'light' ? 'dark' : 'light'; } render() { return html` <div id="app-wrapper" class="${this.theme}"> <nav>Global Nav</nav> <!-- The current page (and its layouts) are rendered here --> ${this.children} <GlobalFooter /> </div> `; } }
Lifecycle
Server-Side Rendering (SSR):
- The
Appcomponent is instantiated and bootstrapped for every request. - It wraps the rendered HTML of the requested page.
- Its initial state is serialized into
window.__INITIAL_STATE__._app_state.
- The
Client-Side Hydration:
- On the first load, the client creates a single instance of
Appand hydrates it with the server-sent state.
- On the first load, the client creates a single instance of
Navigation:
- When the user navigates to a new page (e.g., via a link), the
Appinstance remains active. - Only the
children(the page content) are swapped out. - This preserves any state stored in the
Appcomponent (like thethemevariable in the example above).
- When the user navigates to a new page (e.g., via a link), the
Styling
Since the App component wraps everything, it's the perfect place to apply global CSS classes or manage themes dynamically.
if (!this.isServer) { document.body.className = this.theme; }