Understanding Ecopages Core
Before diving into the specifics of writing code for Ecopages, it's important to understand how the core of Ecopages works. This knowledge will help you make better decisions when structuring your project and writing your code.
Integration System
Ecopages uses a flexible integration system to extend its functionality. Each integration plugin can provide:
- Template extensions
- Custom loaders
- Build hooks
For example, the KitaJS integration might set up template extensions like this:
.setIncludesTemplates({
head: 'head.kita.tsx',
html: 'html.kita.tsx',
seo: 'seo.kita.tsx',
})This configuration tells Ecopages which files to use for specific parts of the page structure.
CSS Processing
By default, Ecopages uses plain css for styling.
We currently provide a simple Postcss and Tailwind (v4 and v3) plugin that provides a powerful and flexible system for managing your styles via a preset system.
You can customize this in your eco.config.ts file:
import { ConfigBuilder } from '@ecopages/core';
import { postcssProcessorPlugin } from '@ecopages/postcss-processor';
import { tailwindV4Preset } from '@ecopages/postcss-processor/presets/tailwind-v4';
const config = await new ConfigBuilder()
// ... other configurations
.setProcessors([
postcssProcessorPlugin(
tailwindV4Preset({
referencePath: path.resolve(import.meta.dir, 'src/styles/tailwind.css'),
}),
),
])
.build();Script and CSS Loading
Ecopages handles script and CSS loading efficiently by analyzing component dependencies.
Explicit Dependencies
To ensure that your components have the necessary scripts and styles, you must explicitly declare them in the component's config.dependencies property. This allows Ecopages to:
- Deduplicate: If multiple components share the same script, Ecopages only ships it once.
- Order: Dependencies are loaded in the correct order based on the component tree.
- Optimize: Only the code used on a specific page is sent to the browser.
import { BaseLayout } from '@/layouts/base-layout';
import { eco, html } from '@ecopages/core';
const HomePage = eco.component({
dependencies: {
// Scripts must be explicitly declared
scripts: ['./home-page.script.ts'],
// Stylesheets must be explicitly declared
stylesheets: ['./home-page.css'],
// Child components to crawl for their own dependencies
components: [BaseLayout],
},
render: () => html`
<div class="main-content">
<h1>Welcome to Ecopages</h1>
</div>
`
});Lazy Dependencies
You can also defer loading of scripts and stylesheets until they are needed using the lazy options. This is useful for improving initial page load performance.
The supported triggers are:
on:idle: Loads when the browser is idle.on:visible: Loads when the element enters the viewport.on:interaction: Loads when the user interacts with the element (e.g. mouseover, click, focus).
const MyComponent = eco.component({
dependencies: {
lazy: {
'on:visible': true, // or provide a specific selector string
scripts: ['./heavy-script.ts'],
}
},
render: () => html`<div>Heavy Content</div>`
});Robots.txt Generation
Ecopages automatically generates a robots.txt file based on your configuration. You can customize this in your eco.config.ts file.
Import CSS as String in JS Files
Ecopages provides a way to load CSS directly into your JavaScript files as strings using Bun's plugins. This feature is enabled when you use the @ecopages/postcss-processor plugin in your eco.config.ts.
Import MDX as a Component
Ecopages allows you to import MDX files as components. This is useful for creating reusable content and components that can be used across your site.
This capability is provided by the MDX Integration, which automatically handles MDX transformations using @mdx-js/esbuild internally.
import Component from '@/components/mdx-component';
const MyPage = () => html`${Component()}`;
Project Structure
Ecopages expects a specific project structure:
my-project/
├── src/
│ ├── pages/
│ ├── layouts/
│ ├── components/
│ └── includes/
├── public/
├── eco.config.ts
└── package.json
src/components/: Stores reusable components (Recommended)src/pages/: Contains your page files (e.g.,.mdx,.kita.tsx,.lit.tsx) (Default)src/layouts/: Holds layout components (Recommended)src/includes/: Contains include templates (e.g.,head.kita.tsx,html.kita.tsx) (Default)public/: Static assets that will be copied to the build directory (Default)eco.config.ts: Ecopages configuration file (Mandatory)
This structure helps Ecopages efficiently process and build your site. While Ecopages provides these sensible defaults, every directory path is fully customizable via your eco.config.ts.
Runtime Origin and API Requests
When fetching data in staticPaths or staticProps, Ecopages provides different approaches. For most cases, calling your data functions directly is recommended for better performance and reliability.
Direct Function Calls (Recommended)
For the best performance during static generation, call your data layer functions directly:
import { eco } from '@ecopages/core';
import { getAllBlogPosts, getBlogPost } from '@/data/blog';
export default eco.page({
staticPaths: async () => {
const posts = getAllBlogPosts();
return {
paths: posts.map(post => ({
params: { slug: post.slug }
}))
};
},
staticProps: async ({ pathname }) => {
const slug = pathname.params.slug;
const post = getBlogPost(slug);
if (!post) {
throw new Error(`Post not found: ${slug}`);
}
return { props: { post } };
},
render: ({ post }) => html`...`
});Runtime Support
Currently, Ecopages is designed to work exclusively with the Bun runtime. While the architecture supports multiple runtime adapters, at the moment only the Bun adapter is implemented and maintained.
This means you'll need to:
- Have Bun installed in your development environment https://bun.sh/docs/installation
- Use Bun's package manager for dependencies
- Take advantage of Bun's built-in features like TypeScript support and fast bundling
Server and API Handlers
Ecopages provides a simple and intuitive way to create API endpoints and handle server-side logic. You can find more details in the Server API documentation.
import { EcopagesApp } from '@ecopages/core/adapters/bun/create-app';
import appConfig from './eco.config';
const app = new EcopagesApp({ appConfig });
app.get('/api/hello', async () => {
return new Response(JSON.stringify({ message: 'Hello world!' }));
});
await app.start();Additional Features
- Hot Reload: Ecopages supports hot reloading during development, making the development process more efficient.
- Static Site Generation: Ecopages generates static HTML files, improving performance and reducing server load.
- TypeScript Support: Ecopages is built with TypeScript and provides excellent TypeScript support out of the box.