docs v0.1


Magic Formula

+ Simplicity of plain HTML, JS, CSS
+ Flexibility of modular components
+ Stability of precompiled languages
=MAGIC.

essencekit turns pure creativity into precise reality.


Installation

Prerequisites

Ensure your system has:

Quick Start

git clone git@github.com:essencekit/essencekit.git
cd essencekit
npm install && npm link

essencekit build

Your generated site will appear in the Pub folder.


Directory Structure


Component System

To create a component, simply add a new folder and HTML file under App/Components. Each component can have unlimited sub‑components.

Component structure example:

App/
    └── Components/
        └── SomeComponent/
            ├── SubComponent/
            │   └── OneMoreComponent.html
            ├── SomeComponent.html
            ├── AnotherComponent.html
            └── config.json

Components can extend others by specifying a parent in config.json.


State

essencekit provides simple state management for handling both global and local states easily.

Global State Example

A minimal global state for theme switching:

<button id="toggle-theme">Toggle Theme</button>

<script>
    window.addEventListener('globalStateReady', () => {
        document.getElementById('toggle-theme').onclick = () => {
            const newTheme = globalState.getState().theme === 'dark' ? 'light' : 'dark';
            globalState.setState({ theme: newTheme });
            document.body.setAttribute('data-theme', newTheme);
        };
    });
</script>

Local State Example

Local state for managing interactive elements:

<form id="chat-form">
    <input name="prompt" placeholder="Your message..." />
    <button type="submit">Send</button>
</form>
<div id="response"></div>

<script type="module">
        import State from '@ASSETS@/State/Manager.js';

        const chatForm = document.getElementById('chat-form');
        const chatState = new State({ messages: [] });

        chatForm.onsubmit = (e) => {
            e.preventDefault();
            const prompt = e.target.prompt.value;

            chatState.setState({
                messages: [...chatState.getState().messages, prompt],
            });

            document.getElementById('response').innerText = 'Sent: ' + prompt;
            e.target.prompt.value = '';
        };
</script>

Preserving State Across Pages

You can persist state using localStorage, ensuring state continuity between page loads:

// Saving state to localStorage
localStorage.setItem('chatMessages', JSON.stringify(chatState.getState().messages));

// Loading state from localStorage
const savedMessages = JSON.parse(localStorage.getItem('chatMessages') || '[]');
const chatState = new State({ messages: savedMessages });

Use these minimal states to keep interactions clear, responsive, and maintainable.


Template Engine

1. Call a component – pass it whatever data you need

@{SomeComponent, {"someKey": "data"}}

2. Inside SomeComponent you can access that key (or any config value) with:

@[someKey]

3. Chain another component – a component can invoke another component the same way:

@{AnotherComponent}

Conditional & loops:

@if(some.condition)
    ...
@else
    ...
@endif

@each(item in some.list)
    ...
@end

Project Lifecycle

To build and deploy your essencekit site, run:

essencekit build

This compiles and outputs the generated website into the Pub/dev folder by default.

Namespaces and Strict Mode

To deploy with specific configurations, use namespaces (like prod):

essencekit build prod

Using the prod namespace activates strict mode, preventing deployments with rule violations. The build will halt on errors, ensuring your production environment remains stable.

Custom post‑processing is supported. Minification is enabled by default.

The final result is a fully static site composed of HTML, JS, and CSS.


Rules

Rules in essencekit ensure best practices, consistency, and stability across your project. Rules are defined under the App/Rules directory and configured within your App/config.json:

Configuration Example (App/config.json):

{
    "rules": {
        "enabled": true,
        "strict": true,
        "sources": [
            "Rules/customRules.js"
        ]
    }
}

Rule Definition Example (App/Rules/customRules.js):

export default [
    {
        name: 'title-required',
        description: 'Component config must have a title.',
        check(html, component) {
            if (!component?.config?.title) {
                return `Missing title in component: ${component.name}`;
            }
        }
    }
];

Each rule consists of:

Use strict mode to enforce compliance during production builds, keeping your deployments safe and consistent.

You can skip rules entirely if they're not needed for your project.


PostProcess

Post‑processing in essencekit optimizes the final HTML output. Minification is enabled by default, but you can add custom steps as needed.

Post‑processors live under App/PostProcess and are configured in App/config.json.

Configuration Example (App/config.json):

{
    "postProcess": {
        "enabled": true,
        "sources": [
            "PostProcess/smila.js"
        ]
    }
}

PostProcessor Example (App/PostProcess/smila.js):

export default function (html) {
    // Insert a smiley just before the closing tag
    return html.replace('</body>', '😊</body>');
}

Use post‑processors to keep your builds clean, performant, and optimized for production.


Playground

Explore essencekit features with examples in the repository's App folder. Deploy and test freely.


Configuration Levels

Configurations hierarchy:


.env Configuration

Set API keys here. Copy .env.example to .env to start configuring your API keys.


Global Config

Example (App/config.json):

{
    "rules": {
        "enabled": true,
        "strict": true,
        "sources": [
            "essencekit-rules-basic",
            "Rules/customRules.js",
            "Rules/htmlLintRules.js"
        ]
    },
    "auth": {
        "endpoint": "http://localhost:3000/api/auth/login"
    },
    "apiGroups": {
        "main": "https://jsonplaceholder.typicode.com",
        "openai": "https://api.openai.com/v1"
    },
    "apiAuth": {
        "openai": {
            "type": "Bearer",
            "token": "OPENAI_KEY"
        }
    }
}

Component Config

Example (App/Components/Index/config.json):

{
    "extends": "BasePage",
    "title": "essencekit Home Page",
    "description": "Minimalist web framework focused on speed, simplicity, and fun.",
    "render": true,
    "auth": true,
    "api": [
        {
            "dataGroup": "main",
            "dataSource": "/posts",
            "postType": true,
            "postName": "sendPost"
        }
    ]
}

Only components with render: true are rendered. It is possible to skip config.json altogether and simply call the component from another component.


API System

Global Configuration

Define your APIs in the global configuration file: App/config.json

{
    "apiGroups": {
        "openai": "https://api.openai.com/v1",
        "main": "https://jsonplaceholder.typicode.com"
    },
    "apiAuth": {
        "openai": {
            "type": "Bearer",
            "token": "OPENAI_KEY"
        }
    }
}

Component Configuration

Use APIs within your components by defining them in your component config:

GET Example

{
    "api": [
        {
            "dataGroup": "main",
            "dataSource": "/posts",
            "getType": "static",
            "injectAs": "posts"
        }
    ]
}

Template Usage:

@if(posts.length)
    <ul>
        @each(post in posts)
        <li>@[post.title]</li>
        @end
    </ul>
@else
    <p>No posts available.</p>
@endif

POST Example

Define the POST endpoint in your component config:

{
    "extends": "BasePage",
    "title": "essencekit Home Page",
    "description": "essencekit is a minimalist web framework focused on speed, simplicity, and fun.",
    "render": true,
    "auth": true,
    "api": [
        {
            "dataGroup": "main",
            "dataSource": "/posts",
            "postType": true,
            "postName": "sendBlessing"
        }
    ]
}

Template usage with a form:

<form onsubmit="essenceAPI.sendBlessing({
    title: this.title.value,
    message: this.message.value,
    userId: 1}).then(res => console.log('✅ Sent:', res)); return false;">
        <input name="title" placeholder="Type a title..." />
        <input name="message" placeholder="Type a blessing..." />
        <button type="submit">Bless essencekit</button>
</form>

Future Implementation

Currently, only getType: "static" is implemented.

Soon, getType: "dynamic" will allow personalized refetching of data upon reload or after a defined expiration period without needing to redeploy the application.


Naming Conventions


Monorepo as Launchpad

The entire essencekit ecosystem begins in a unified monorepo — a springboard for rapid development, seamless iteration, and tight integration. This setup accelerates early momentum and simplifies contributions. As the project evolves, the community will vote on whether to keep it unified or modularize into separate packages. The structure adapts to growth — not the other way around.


Routing

essencekit doesn't include built‑in routing, giving you full control to integrate your server’s rewrite rules. A dedicated router package might come later.


Overriding Principle

essencekit allows overriding core classes effortlessly: simply mirror the class path inside the App folder and modify imports. Maintain the same namespace but use your custom logic.

Example:

Original:
Core/Compiler/Renderer.js

Override:
App/Compiler/Renderer.js

Currently, only the Renderer class is override‑ready. More extensibility options are on the way.


Authentication Demo

To test authentication with the Auth component, set up the demo auth server — or use your own.


AI Workflows (Coming Soon)

Stay tuned for AI‑driven workflows.


Philosophy & Community

essencekit is community‑driven:

Check and contribute to essencekit’s future: GitHub Issues

Contact us through our social networks for support.


And One More Thing...

All documentation is a suggestion, not a rulebook.

Experiment, explore, and share your insights on Twitter, Reddit, or GitHub.