Skip to content

getelena/next-example-project

Repository files navigation

Elena + Next.js Example

A minimal example demonstrating how to use Elena web components (@elenajs/core) inside a Next.js 15 application with TypeScript.

What is Elena?

Elena is a lightweight (2kB) library for building Progressive Web Components that work natively in the browser. This example uses both @elenajs/core and @elenajs/components, an example component library built on top of Elena.

What This Example Demonstrates

Examples live in src/app/page.tsx and cover:

  • Variants: default, primary, and danger button styles
  • Interactive counter: React state (useState) driving Elena button click handlers
  • Dynamic attribute binding: cycling through variants reactively via JSX expressions

Prerequisites

  • Node.js v20+
  • pnpm v10+

Getting Started

# Install dependencies
pnpm install

# Start the development server
pnpm start

Open http://localhost:3000 in your browser.

Available Scripts

Command Description
pnpm start Start the Next.js dev server
pnpm build Type-check and build for production
pnpm preview Preview the production build locally

Project Structure

src/
├── app/
│   ├── layout.tsx          # Root layout, mounts ElementsRegistry and imports CSS
│   ├── page.tsx            # Main page, all Elena examples live here
│   ├── counter.tsx         # Interactive counter (client component)
│   ├── variant-cycler.tsx  # Dynamic variant cycling (client component)
│   └── globals.css         # Application styles
├── elements-registry.tsx   # Client component that lazy-loads all Elena elements
└── elena.d.ts              # TypeScript JSX declarations for Elena elements
tsconfig.json               # TypeScript configuration
next.config.ts              # Next.js configuration

How Elena Web Components Are Loaded

Because Elena components access the DOM on hydration, Next.js needs to be configured in a way that supports this. To achieve this, create a "use client" component with useEffect to defer Elena hydration to the browser:

// src/elements-registry.tsx
"use client";

import { useEffect } from "react";

export default function ElementsRegistry() {
  useEffect(() => {
    import("@elenajs/components");
  }, []);

  return null;
}

Mount it once in the root layout so components are available everywhere. Elena components can then be used directly in Server Components for markup and styles, with interactivity handled by client components.

TypeScript Support

Create a type declaration file to wire Elena’s types into React’s JSX namespace:

// src/elena.d.ts
import type { CustomElements } from "@elenajs/components";

type ElenaIntrinsicElements = {
  [K in keyof CustomElements]: CustomElements[K] & {
    onClick?: (e: MouseEvent) => void;
    onFocus?: (e: FocusEvent) => void;
    onBlur?: (e: FocusEvent) => void;
    children?: React.ReactNode;
  };
};

declare module "react" {
  namespace JSX {
    interface IntrinsicElements extends ElenaIntrinsicElements {}
  }
}

About

An example demonstrating how to use Elena inside a Next.js 15 application with TypeScript.

Topics

Resources

License

Stars

Watchers

Forks

Contributors