Backend Guide
Write server-side logic with functions, conditionals, loops, and API endpoints.
Functions
Functions are the core of your backend logic. Define a function with a unique function_id, a list of params, and a body that executes when it is called.
crescent.function({
function_id: 'greet_user',
params: ['name', 'age'],
body: function (name, age) {
return 'Hello ' + name + '! You are ' + age + ' years old.';
}
});
// Call the function
crescent.get_function('greet_user').call('Alice', 25);Reusable logic
function_id and can be retrieved anywhere with crescent.get_function(). Define them once and call them from any page or API endpoint.Conditionals
Branch your logic using crescent.conditional(). Each branch has a check function and a list of actions to run when it passes.
function grant_access() { console.log('Access granted'); }
function limited_access() { console.log('Limited access'); }
function deny_access() { console.log('Access denied'); }
const check = crescent.conditional({
conditional_id: 'age_gate',
if: {
check: function () { return age >= 18; },
actions: [grant_access]
},
else_if: [
{
check: function () { return age >= 13; },
actions: [limited_access]
}
],
else: {
actions: [deny_access]
}
});
check.evaluate();Branch checks
check is any function that returns true or false. If it returns a conditional instance, its evaluate() result is used instead.Loops
Iterate over collections with crescent.loop(). Use loop_type: 'for_in' to iterate an array, or 'for'/'while' for counter-driven loops. Call run() to execute and collect results.
const loop = crescent.loop({
loop_id: 'render_items',
loop_type: 'for_in',
iterable: ['apple', 'banana', 'cherry'],
actions: [
function (item) {
console.log(item);
}
]
});
loop.run();
// Counter loop: 0, 1, 2, ..., 9
crescent.loop({
loop_id: 'count_to_ten',
loop_type: 'for',
start: 0,
end: 10,
step: 1,
actions: [
function (i) { console.log(i); }
]
}).run();API Endpoints
Create an HTTP server with crescent.api_make(), register endpoints with add_endpoint(), and start listening with start().
const api = crescent.api_make({
api_id: 'main',
port: 3000
});
api.add_endpoint('GET', '/users', function (req, res) {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ users: ['Alice', 'Bob'] }));
});
api.add_endpoint('POST', '/users', function (req, res) {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ created: true, user: req.body }));
});
api.start();Request handling
res.writeHead() and res.end(). Incoming JSON bodies are parsed into req.body for you.Combining It All
Functions, conditionals, loops, and APIs compose together. A common pattern is an API endpoint that validates input with a function and returns the result.
// Create a backend function
crescent.function({
function_id: 'validate_email',
params: ['email'],
body: function (email) {
return email.includes('@');
}
});
// Use it in an API endpoint
const api = crescent.api_make({
api_id: 'main',
port: 3000
});
api.add_endpoint('POST', '/signup', function (req, res) {
const valid = crescent.get_function('validate_email').call(req.body.email);
res.writeHead(valid ? 200 : 400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify(valid ? { status: 'ok' } : { error: 'Invalid email address' }));
});
api.start();Next Steps
- Database Guide — persist data with the built-in database
- Authentication Guide — protect your endpoints