---
title: "Pages"
description: "Define pages with eco.page — static paths, data fetching, metadata, and rendering."
order: 4
---

# Creating Pages in Ecopages

Pages are the core of your Ecopages project. They represent the different routes and content of your website. This guide uses **Ecopages JSX** (`.tsx` routes owned by `@ecopages/ecopages-jsx`), which matches the [Installation](/docs/getting-started/installation) default. Other integrations use the same `eco.page` API with different file extensions.

## Basic Page Structure

A typical page is a single `.tsx` file under `src/pages`:

```tsx
import { BaseLayout } from '@/layouts/base-layout';
import { eco } from '@ecopages/core';

export default eco.page({
	layout: BaseLayout,
	metadata: () => ({
		title: 'Home page',
		description: 'This is the homepage of the website',
	}),
	render: () => (
		<>
			<h1>Ecopages</h1>
			<p>Welcome to my Ecopages website!</p>
		</>
	),
});
```

Key elements:

1. **`eco.page`**: Factory for a file-based route page.
2. **`layout`**: Declared layout component (`eco.layout()` or `eco.component()`). EcoPages wraps `render` output automatically.
3. **`metadata`**: Page title, description, and social metadata.
4. **`dependencies`**: Page-level scripts and components discovery cannot follow (`export *` barrels, packages). Local component and CSS imports are discovered automatically.
5. **`render`**: Returns JSX for the page body (inside the layout and document shell).

See [Creating Layouts](/docs/core/layouts) for single and nested layout stacks.

## Using Components in Pages

Import declared components directly. Ecopages discovers local `eco.component()`, `eco.layout()`, and `eco.html()` imports automatically. Every discovered entry must be a declared component — plain functions are rejected at render time.

```tsx
import { RadiantCounter } from '@/components/radiant-counter';
import { BaseLayout } from '@/layouts/base-layout';
import { eco } from '@ecopages/core';

export default eco.page({
	layout: BaseLayout,
	render: () => (
		<>
			<h1>Ecopages</h1>
			<RadiantCounter count={5} />
		</>
	),
});
```

**Note:** You do not need to repeat the page `layout` in `dependencies.components` — `eco.page()` merges declared layouts into the dependency graph for you. Use explicit `dependencies.components` only when discovery cannot follow the import (`export *` barrels, packages).

## Working with Data

For build-time and request-time data, see [Data Fetching](/docs/core/data-fetching).

## Lazy Loading Components

Lazy loading is configured on `dependencies.scripts` entries:

```tsx
import { eco } from '@ecopages/core';

export const MyComponent = eco.component({
	dependencies: {
		scripts: [{ src: './my-component.script.ts', lazy: { 'on:interaction': 'mouseenter,focusin' } }],
	},
	render: (props) => <my-component {...props} />,
});
```

See [Components](/docs/core/components) for more patterns.
