📚 StoneJS Developer Guide

Complete reference for building modern web applications with the StoneJS Framework

📝 Templates & Components

EJS Templating

StoneJS uses EJS (Embedded JavaScript) for templating:

Syntax Purpose Example
<%= Output (escaped) <%= user.name
<%- Output (unescaped HTML) <%- htmlContent
<% JavaScript logic <% if (user) {
<%# Comment <%# Developer note

Conditional Rendering

<% if (user.isAdmin) { <button>Admin Panel</button> <% } else if (user.isLoggedIn) { <button>My Profile</button> <% } else { <a href="/login">Sign In</a> <% }

Loops and Iteration

<%%js> const users = await $db.query('SELECT * FROM users'); <ul> <% users.forEach(user => { %> <li> <strong><%= user.name </strong> <small><%= user.email </small> </li> <% }); </ul>

Component System

Create reusable components with include():

1. Create a Component

<!-- pages/components/user-card.html --> <%%js> const user = $context.get('user'); const showEmail = $context.get('showEmail') || false; <div class="user-card"> <img src="<%= user.avatar %>" alt="<%= user.name "> <h3><%= user.name </h3> <% if (showEmail) { <p><%= user.email </p> <% } </div>

2. Use the Component

<%%js> const users = await $db.query('SELECT * FROM users LIMIT 5'); <div class="user-grid"> <% for (const user of users) { %> <%%js> $context.set('user', user); $context.set('showEmail', true); <%- await include('components/user-card') %> <% } </div>

Passing Data to Components

Components access data through $context:

<%%js> // Set data before including $context.set('title', 'Welcome'); $context.set('message', 'Hello, World!'); $context.set('variant', 'success'); <%- await include('components/alert-box') %>

Section Tags

StoneJS provides special section tags to control when code executes during the component lifecycle:

Tag When It Runs Purpose & Use Case
<%%doc> Never (removed at runtime) Documentation and developer comments. Use for component docs, prop descriptions, usage notes.
<%%once> Once on server startup Expensive initialization that only needs to run once. Examples: loading config files, compiling templates, setting up constants.
<%%init> Start of each request (before rendering) Request initialization logic. Examples: cache checks, authentication, data fetching that needs to happen before rendering starts.
<%%js> During template rendering Inline JavaScript that runs as template renders. Use for variables needed in the HTML. Can have multiple blocks.
<%%cleanup> After response sent to client Post-request cleanup and logging. Examples: log metrics, close connections, update analytics. Doesn't block response.

Example Component with All Sections:

<%%doc> User Card Component Displays user information in a styled card Props: user (object), showEmail (boolean) <%%once> // Runs once on server startup const CARD_TEMPLATE = loadCardTemplate(); const DEFAULT_AVATAR = '/images/default-avatar.png'; <%%init> // Runs at start of each request (before rendering) if (await $cache.cacheSelf({ expiresIn: '5 minutes' })) { return; // Serve cached version } trackComponentUsage('user-card'); <%%js> // Runs during rendering (can access $context) const user = $context.get('user'); const showEmail = $context.get('showEmail') || false; const avatar = user.avatar || DEFAULT_AVATAR; <div class="user-card"> <img src="<%= avatar %>" alt="<%= user.name "> <h3><%= user.name </h3> <% if (showEmail) { <p><%= user.email </p> <% } </div> <%%cleanup> // Runs after response sent (doesn't block response) logComponentRender('user-card', Date.now() - startTime); updateUsageStats();

💡 Pro Tip: Use <%%init> for cacheSelf() and expensive operations. Use <%%js> for simple variables needed in HTML. Use <%%cleanup> for logging that shouldn't delay the response.

Best Practices

  • Keep components small and focused
  • Pass data explicitly via $context.set()
  • Use <%= %> (escaped) by default for security
  • Only use <%- (unescaped) for trusted HTML
  • Store reusable components in pages/components/
  • Use descriptive component names (user-card, not card)

Global Context → Component Examples Section Tags Guide

Need more help?

View All Demos Getting Started GitHub Repository