📚 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)
Need more help?