# Code Structure

SSE encourages you to separate code into TypeScript classes that can be easily managed and organized.

These include;

* Site-level classes, which contain site-wide functionality
* Page-level classes, which contain page-specific functionality
* Component-level classes, which contain code specific to a reusable component

## Base Classes (Recommended)

**New in v2.0:** SSE provides base classes with automatic context detection. This is the recommended approach for pages and components.

### PageBase for Pages

Pages extend `PageBase` to get automatic Webflow context detection:

* **onPrepare()** - Synchronous setup during `<head>` load
* **onLoad()** - Asynchronous execution after DOM ready
* **this.pageInfo** - Automatic Webflow context (pageId, siteId, collectionId, itemSlug, etc.)

### ComponentBase for Components

Components extend `ComponentBase` to get automatic element context:

* **onPrepare()** - Synchronous setup during `<head>` load
* **onLoad()** - Asynchronous execution after DOM ready
* **this.element** - The HTMLElement the component is bound to
* **this.context** - Component metadata (name, id, dataAttributes)

## The IModule Interface (Advanced)

For advanced use cases, you can still implement the `IModule` interface directly. This gives you full control but requires manual context detection.

### Legacy Lifecycle Methods

When implementing `IModule` directly:

* **setup()** - Runs synchronously at the end of `</head>`
* **exec()** - Runs asynchronously after DOM is loaded

Let's look at how these approaches work in practice.

## Site Class

Exists at `/src/site.ts`

The Site class still uses `IModule` directly since it doesn't need automatic context detection:

```typescript
import { IModule, Page } from "@sygnal/sse-core";

export class Site implements IModule {

  constructor() {
  }

  setup() {
    // Site-wide setup code
  }

  exec() {
    console.log("Site loaded.")
  }

}
```

## Page Classes (Recommended Approach)

**New in v2.0:** Pages should extend `PageBase` for automatic Webflow context detection.

All Page classes are stored in `/src/pages` folder. By convention, Pages end in `Page`.

Here's an example using the recommended `PageBase` approach:

```typescript
import { PageBase, page } from "@sygnal/sse-core";

@page('/')
export class HomePage extends PageBase {

  protected onPrepare(): void {
    // Synchronous setup - access automatic context
    console.log('Page ID:', this.pageInfo.pageId);
    console.log('Collection:', this.pageInfo.collectionId);
  }

  protected async onLoad(): Promise<void {
    // Asynchronous execution after DOM ready
    console.log('Item Slug:', this.pageInfo.itemSlug);
    console.log("Home page loaded.");
  }

}
```

### Available Page Context

When using `PageBase`, you automatically get access to:

* `this.pageInfo.path` - Current page path
* `this.pageInfo.pageId` - Webflow page ID
* `this.pageInfo.siteId` - Webflow site ID
* `this.pageInfo.collectionId` - CMS collection ID (if applicable)
* `this.pageInfo.itemId` - CMS item ID (if applicable)
* `this.pageInfo.itemSlug` - CMS item slug (if applicable)
* `this.pageInfo.queryParams` - URL query parameters
* `this.pageInfo.hash` - URL hash
* `this.pageInfo.domain` - Webflow domain
* `this.pageInfo.lang` - Page language

## Component Classes (Recommended Approach)

**New in v2.0:** Components should extend `ComponentBase` for automatic element context.

All Component classes are stored in `/src/components` folder. By convention, Components end in `Component`.

Here's an example using the recommended `ComponentBase` approach:

```typescript
import { ComponentBase, component, PageBase } from "@sygnal/sse-core";

@component('navigation')
export class NavigationComponent extends ComponentBase {

  protected onPrepare(): void {
    // Access element and context automatically
    console.log('Component:', this.context.name);
    console.log('Element:', this.element);
  }

  protected async onLoad(): Promise<void> {
    // Access current page info if needed
    const page = PageBase.getCurrentPage();
    if (page) {
      const info = page.getPageInfo();
      console.log('On page:', info.pageId);
    }

    // Add event listeners
    this.element.addEventListener('click', () => {
      console.log('Navigation clicked');
    });
  }

}
```

Use the public `getPageInfo()` accessor (the `pageInfo` property is protected) whenever a component needs Webflow page context.

### Available Component Context

When using `ComponentBase`, you automatically get access to:

* `this.element` - The HTMLElement the component is bound to
* `this.context.name` - Component name from `data-component` attribute
* `this.context.id` - Component ID from `data-component-id` attribute
* `this.context.dataAttributes` - All data-\* attributes on the element

## Usage Notes

Execution order:

* Site code executes on all pages first (both `setup()` and `exec()`)
* Page code executes second (both `onPrepare()` and `onLoad()`)
* Component code executes last (both `onPrepare()` and `onLoad()`)

{% hint style="success" %}
Components are fully implemented in v2.0 with automatic discovery and initialization!
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://engine.sygnal.com/usage/code-structure.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
