Cloud code is the JavaScript that runs inside your app's Parse Server: functions your clients call, triggers on saves and deletes, background jobs, and your own HTTP routes.
The repository
Every app has a private GitHub repository. In Core › Cloud Code, link your GitHub account and accept the invitation, then clone it:
cloud/
main.js ← loaded by Parse Server: require your other files from here
functions.js
app.js ← your own Express routes ("Advanced Cloud Code")
public/ ← static files, served at your app's public URL
package.json ← npm dependencies, installed on every build
index.js ← runs the app locally (see below)
Keep cloud/main.js as the entry point: SashiDo loads that path.
Deploy
Push to the repository's master branch. SashiDo builds the code (installing the dependencies in package.json) and deploys it, one deployment at a time. Follow it in Runtime › Builds and Runtime › Deployments; a failed build keeps the previous version running, and its log says why.
From a terminal or CI: POST /apps/{id}/build and /deploy with the Management API, or ask your AI assistant to deploy and wait (deploy_app, wait_for_deployment).
Functions
// cloud/functions.js
Parse.Cloud.define('averageRating', async (request) => {
const { movie } = request.params;
if (!movie) throw new Parse.Error(Parse.Error.INVALID_QUERY, 'movie is required');
const reviews = await new Parse.Query('Review').equalTo('movie', movie).find();
return reviews.reduce((sum, r) => sum + r.get('stars'), 0) / (reviews.length || 1);
});
// a client
const rating = await Parse.Cloud.run('averageRating', { movie: 'Arrival' });
request.user is the logged-in caller (or undefined), request.master says whether the master key was used. Queries in a function run with the caller's permissions unless you pass { useMasterKey: true }.
Triggers
| Trigger | Runs | Typical use |
|---|---|---|
beforeSave |
Before an object is saved | Validate, normalize, set the ACL |
afterSave |
After it's saved | Counters, notifications, sync to other systems |
beforeDelete / afterDelete |
Around a delete | Refuse, clean up related objects |
beforeFind / afterFind |
Around a query | Limit what a query may return |
Parse.Cloud.beforeSave('Review', (request) => {
const stars = request.object.get('stars');
if (!(stars >= 1 && stars <= 5)) {
throw new Parse.Error(Parse.Error.VALIDATION_ERROR, 'stars must be 1 to 5');
}
});
Throwing refuses the operation, and the client gets the error. Triggers run on every matching request, so keep them fast: see Performance.
Background jobs
Long or periodic work (cleanups, reports, imports) goes in a job:
Parse.Cloud.job('cleanupOldSessions', async (request) => {
const { message } = request;
message('Starting');
// ... work in batches
return 'Done';
});
Schedule it in Core › Jobs (once, or repeating), or run it from the dashboard. Each run's status and message are kept, and through MCP your assistant can run a job and wait for its result.
Your own routes and static files
cloud/app.js exports an Express app, mounted at the root of your app's public URL (https://pg-app-<id>.scalabl.cloud/):
// cloud/app.js
const express = require('express');
const app = express();
app.post('/webhooks/stripe', express.raw({ type: 'application/json' }), async (req, res) => {
// verify the signature, then handle the event
res.sendStatus(200);
});
module.exports = app;
cloud/main.js keeps the line module.exports.app = require('./app');. Files in public/ are served as they are, e.g. public/index.html at the public URL. With a custom domain (App Settings › Emails & Hosting › Host Name, with a free SSL certificate) both answer on your domain.
Webhooks
Functions and triggers can also run on your own server: Core › Webhooks points a function name or a class trigger at a URL. Parse calls it with the request and checks the answer; your server verifies the X-Parse-Webhook-Key header (the Webhook Key in App Settings › Security & Keys).
Secrets and configuration
Set API keys and settings as environment variables (dashboard Runtime › Environment Variables) and read them with process.env.STRIPE_KEY. Never commit them to the repository.
Logs
console.log and console.error in cloud code go to Core › Logs, next to Parse's own errors (e.g. a function that threw). Your assistant can read them with get_logs and get_error_logs.
Run it locally
Run your cloud code on your machine with a local Parse Server, and test functions and triggers automatically before you push: see Local development and testing.
Write code for your version
The Parse Server version is in Runtime › Parse Server Version. Since Parse Server 3, functions and triggers are async and return or throw; response.success() and response.error() are gone. plan_parse_server_upgrade through MCP lists, file by file, what your code needs before a version upgrade.