How Raytha Functions work
A Raytha Function is a short piece of JavaScript that lives inside your site. It can answer a web address (for example /llms.txt or a JSON feed), supply a value to a template, or run in the background when a content item is created, saved or deleted. This page shows how to create one in the admin and how to manage it. For the programming side, see the developer docs.
What you need
- The Manage System Settings permission. Automation > Functions only appears in the sidebar with it.
- Basic JavaScript, or a recipe to start from. The editor includes ready-made recipes.
Warning Functions run on your server and can use the same internal API the admin uses: reading and changing content and users, sending email, and making web requests. Only give Manage System Settings to people you would trust with full control of the site, and review code you paste in.
Create your first function
This function answers a web address with a line of text.
- Open Automation > Functions and click New function.
- Enter a Name, for example "Hello text". The Developer name fills in as
hello_text. You can adjust it before saving; it cannot be changed afterwards. - Leave Trigger as HTTP request.
- In Public path type
hello.txt. - Replace the code with:
function get(query) { return new TextResult("Hello from Raytha"); } - Tick Active and click Create.
You should see "Function created". Open https://example.com/hello.txt (with your own address) in a browser and you should see "Hello from Raytha". The function also answers at /raytha/functions/execute/hello_text, which is useful when you do not want a public path.
The five triggers
The Trigger decides when the function runs and which function name inside your code Raytha calls.
| Trigger | Runs when | Your code defines |
|---|---|---|
| HTTP request | Someone requests the function's address. GET calls get(query), POST calls post(payload, query). | get and/or post |
| Liquid template | A template calls it while a page renders. | Any function name you choose |
| Content item created | After a content item is created, in the background. | run(payload) |
| Content item updated | After a content item is saved, in the background. | run(payload) |
| Content item deleted | After a content item is moved to the trash, in the background. | run(payload) |
If the editor shows "… functions need a get() or post() function. Nothing will run until the code defines one." under the code box, the code is missing the entry point for that trigger. The message is a hint; Raytha still lets you save.
HTTP request
The function can return JSON, text, HTML, XML, a redirect or a status code, using helpers such as JsonResult, TextResult, HtmlResult, RedirectResult and StatusCodeResult. It is public: anyone on the internet can call it. If it should be private, check CurrentUser inside the code. When a function is not Active, or does not exist, the address answers as if it were missing.
Public path is optional and only exists for this trigger. Use letters, numbers and - _ . /, up to 200 characters. Only the last segment may contain a dot, so feeds/posts.xml works. A path that another page, view or function already uses is refused, and so are paths Raytha reserves for itself. After you save, the field shows "Live at" with a link.
Liquid template
Call the function from any web template and its return value is printed in place:
{{ raytha_function("price_helper", "format_price", amount=19.5) }}
The three values are the developer name, the name of the function inside your code, and any arguments you want to pass. If the function fails, the template prints nothing and the page still renders.
Content item triggers
These run after the change has been saved, so they never slow down or block the editor. The function receives the content item. The return value is ignored. Use them for tasks such as telling a chat room that a post was created.
Edit, pause and delete
- Edit: click a function's name in the list, change it, and click Save. The list shows Name, Developer name, Trigger and Status.
- Pause: clear Active and save.
- Delete: use Delete function at the bottom of the page. This cannot be undone.
- Change the trigger: pick another Trigger. If the function had a public path, the editor warns "Only HTTP request functions answer at a public path. Saving removes /path." and the path is dropped on save.
Go back to an earlier version
Each time you save with changed code, Raytha keeps the previous code as a revision. Open the Revisions tab beside the editor, find the date and the person who saved it, and click Revert. You should see "Reverted to that revision". The tab's count shows how many revisions exist. A revert replaces the current code, and the code it replaced is itself kept as a revision.
The Reference tab
The Reference tab next to the code lists the entry points for the chosen trigger, the helpers and objects your code can use (content, site pages, menus, users, media, email, HttpClient, CurrentUser), recipes, and the limits. Each snippet has an insert button that puts the code at your cursor. The recipes cover an llms.txt file, a JSON feed of posts, a contact form that emails you, an email when a post is created, a proxy for an outside API, and a Liquid helper.
Test a function
The 2.0.0 editor has no Run or Test button. Test by triggering the real thing:
- HTTP request: open the address in a browser, or send a request with
curl. A mistake in your code shows as an HTTP 500 with the error message. - Liquid template: add the call to a template and load a page that uses it. Errors render nothing, so test the function with a visible fallback value first.
- Content triggers: create or edit a draft item and open Settings > Background tasks. Errors are recorded on that function's task, which you can expand with the arrow at the start of the row.
console.log output is discarded, so you cannot debug with it. Return the value you want to inspect from an HTTP function instead.
Limits
| Limit | Default |
|---|---|
| Run time | 10 seconds. A function still running then is stopped and the caller gets a timeout error. |
| Running at the same time | 5 across the whole site. A caller that waits more than 10 seconds for a free slot gets a 503 response. |
| Language | Plain JavaScript. There is no require, import, fetch or setTimeout. Use HttpClient for web requests. |
The person who runs the server can change these with RAYTHA_FUNCTIONS_TIMEOUT, RAYTHA_FUNCTIONS_MAX_ACTIVE and RAYTHA_FUNCTIONS_QUEUE_TIMEOUT. Setting RAYTHA_FUNCTIONS_MAX_ACTIVE to 0 turns functions off entirely.
Gotchas
- The Developer name is permanent. Templates and addresses refer to it. Choose it once and avoid renaming by delete and recreate.
- "A function with the developer name … does not exist" for a function you can see in the list usually means it is not Active, or its trigger is not HTTP request.
- HTTP functions are public. Do not return private data unless the code checks
CurrentUser. - A content trigger that edits content can trigger itself. Saving an item fires "Content item updated", so a function on that trigger that saves an item may run again. Guard it with a check on the data, and watch Settings > Background tasks the first time.
- Web requests from a function to an internal address are blocked unless the server allows them. See Configuration.
- Keep secrets out of the code. The code is visible to everyone with Manage System Settings and is stored in revisions.