Skip to main content
Technology & EngineeringBaas292 lines

Parse Server

Parse Server is an open-source backend framework that provides a scalable and flexible way to build web and mobile applications with a self-hostable backend-as-a-service (BaaS). It offers database management, REST APIs, GraphQL, push notifications, and user authentication.

Quick Summary16 lines
You are an expert in `parse-server`, capable of deploying and integrating it for robust backend functionalities including data storage, user management, file storage, and real-time features in web and mobile applications. You understand its architecture, how to secure it, and how to leverage its powerful client SDKs.

## Quick Example

```bash
npm install express parse-server mongodb @parse/cloud-code-loader
```

```javascript
// cloud/main.js
Parse.Cloud.define('hello', (request) => {
  return 'Hello from Parse Cloud!';
});
```
skilldb get baas-skills/Parse ServerFull skill: 292 lines
Paste into your CLAUDE.md or agent config

You are an expert in parse-server, capable of deploying and integrating it for robust backend functionalities including data storage, user management, file storage, and real-time features in web and mobile applications. You understand its architecture, how to secure it, and how to leverage its powerful client SDKs.

Core Philosophy

Parse Server offers a powerful "backend-as-a-service" (BaaS) experience, but with the crucial advantage of being entirely self-hostable. This means you gain the rapid development benefits of an integrated backend (database, user auth, push, file storage, analytics, cloud functions) without vendor lock-in or relinquishing control over your infrastructure. It abstracts away common backend complexities, allowing you to focus on your application's unique features, primarily on the client-side.

You choose Parse Server when you need a full-featured backend quickly, want to own your data and infrastructure, and value an ecosystem with mature client SDKs for various platforms. It's ideal for rapid prototyping, projects requiring a scalable and flexible data model, or when migrating from commercial BaaS solutions. Its design encourages a lean client-side architecture backed by robust server-side logic encapsulated in Cloud Functions.

Setup

Setting up Parse Server involves two main parts: the server-side deployment (typically Node.js/Express with MongoDB) and the client-side SDK integration.

Server-side Setup (Node.js/Express)

First, install the necessary packages for your Parse Server instance:

npm install express parse-server mongodb @parse/cloud-code-loader

Then, configure and run your Parse Server with Express:

// server.js
const express = require('express');
const { ParseServer } = require('parse-server');
const ParseDashboard = require('parse-dashboard');
const path = require('path');

const app = express();
const port = process.env.PORT || 1337;
const databaseUri = process.env.DATABASE_URI || 'mongodb://localhost:27017/dev';

const parseServerApi = new ParseServer({
  databaseURI: databaseUri,
  cloud: path.join(__dirname, 'cloud/main.js'), // Path to your Cloud Code
  appId: process.env.APP_ID || 'myAppId',
  masterKey: process.env.MASTER_KEY || 'myMasterKey', // Keep this key secret!
  serverURL: process.env.SERVER_URL || `http://localhost:${port}/parse`,
  liveQuery: {
    classNames: ['GameScore', 'ChatMessage'], // Classes to enable LiveQuery on
  },
  // Other configurations like email adapter, push, etc.
});

// Serve the Parse API on the /parse URL prefix
app.use('/parse', parseServerApi.app);

// Optional: Parse Dashboard setup for managing your Parse app
const parseDashboard = new ParseDashboard({
  apps: [{
    serverURL: parseServerApi.options.serverURL,
    appId: parseServerApi.options.appId,
    masterKey: parseServerApi.options.masterKey,
    appName: 'MyApp',
  }],
  users: [{
    user: 'admin',
    pass: 'adminpass' // Change this for production!
  }],
}, { allowInsecureHTTP: true }); // Set to false for production with HTTPS

app.use('/dashboard', parseDashboard);

// Basic route for testing server status
app.get('/', (req, res) => {
  res.status(200).send('Parse Server is running!');
});

app.listen(port, () => {
  console.log(`Parse Server running on http://localhost:${port}`);
  console.log(`Parse Dashboard running on http://localhost:${port}/dashboard`);
});

Create a cloud/main.js file for your Cloud Code (even if empty initially):

// cloud/main.js
Parse.Cloud.define('hello', (request) => {
  return 'Hello from Parse Cloud!';
});

Client-side SDK Setup (JavaScript/TypeScript)

Install the Parse JavaScript SDK:

npm install parse

Initialize the SDK in your client-side application (e.g., in App.js for React, or main script for vanilla JS):

// client.js or App.js
import Parse from 'parse';

// Initialize Parse
Parse.initialize(
  'myAppId', // YOUR_APP_ID (must match server-side appId)
  'myJavaScriptKey' // YOUR_JAVASCRIPT_KEY (optional, but good practice if not using masterKey on server)
);
Parse.serverURL = 'http://localhost:1337/parse'; // YOUR_PARSE_SERVER_URL

// Optional: Enable LiveQuery
// const liveQueryClient = new Parse.LiveQueryClient({
//   applicationId: 'myAppId',
//   serverURL: 'ws://localhost:1337/', // WebSocket URL for LiveQuery
//   javascriptKey: 'myJavaScriptKey'
// });
// liveQueryClient.open();

console.log('Parse SDK initialized.');

Key Techniques

1. Data Modeling and CRUD Operations

Parse Server simplifies interacting with your database (MongoDB). You define "Classes" which are akin to database tables or collections, and "Objects" as records within those classes.

import Parse from 'parse';

// Define a new Parse Object (Class 'GameScore')
async function createGameScore(playerName, score, cheatMode) {
  const GameScore = Parse.Object.extend('GameScore');
  const gameScore = new GameScore();

  gameScore.set('playerName', playerName);
  gameScore.set('score', score);
  gameScore.set('cheatMode', cheatMode);

  try {
    const result = await gameScore.save();
    console.log('New object created with objectId: ' + result.id);
    return result;
  } catch (error) {
    console.error('Failed to create new object, error code: ' + error.message);
  }
}

// Querying Objects
async function queryGameScores() {
  const GameScore = Parse.Object.extend('GameScore');
  const query = new Parse.Query(GameScore);

  // Example: Find scores greater than 1000 and include a player name
  query.greaterThan('score', 1000);
  query.equalTo('cheatMode', false);
  query.limit(10); // Limit results to 10
  query.descending('score'); // Order by score descending

  try {
    const results = await query.find();
    console.log(`Successfully retrieved ${results.length} scores.`);
    for (const score of results) {
      console.log(`Player: ${score.get('playerName')}, Score: ${score.get('score')}`);
    }
    return results;
  } catch (error) {
    console.error('Error while fetching GameScores: ', error);
  }
}

// Updating an Object
async function updateGameScore(objectId, newScore) {
  const GameScore = Parse.Object.extend('GameScore');
  const query = new Parse.Query(GameScore);

  try {
    const gameScore = await query.get(objectId); // Fetch the object by ID
    gameScore.set('score', newScore);
    const result = await gameScore.save();
    console.log('GameScore updated successfully:', result.id);
    return result;
  } catch (error) {
    console.error('Error updating GameScore: ', error);
  }
}

// Deleting an Object
async function deleteGameScore(objectId) {
  const GameScore = Parse.Object.extend('GameScore');
  const gameScore = new GameScore();
  gameScore.id = objectId; // Set the ID to delete

  try {
    await gameScore.destroy();
    console.log('GameScore deleted successfully:', objectId);
  } catch (error) {
    console.error('Error deleting GameScore: ', error);
  }
}

// Example usage:
// createGameScore('Alice', 1500, false);
// createGameScore('Bob', 800, true);
// queryGameScores();
// updateGameScore('someObjectId', 2000);
// deleteGameScore('anotherObjectId');

2. User Authentication and Management

Parse Server provides a full-featured user management system, including signup, login, password reset, and session management.

import Parse from 'parse';

// Sign up a new user
async function signUpUser(username, password, email) {
  const user = new Parse.User();
  user.set('username', username);
  user.set('password', password);
  user.set('email', email);

  try {
    await user.signUp();
    console.log('User signed up successfully:', user.get('username'));
    return user;
  } catch (error) {
    console.error('Error during signup: ' + error.message);
  }
}

// Log in an existing user
async function logInUser(username, password) {
  try {
    const user = await Parse.User.logIn(username, password);
    console.log('User logged in successfully:', user.get('username'));
    return user;
  } catch (error) {
    console.error('Error during login: ' + error.message);
  }
}

// Get the current logged-in user
function getCurrentUser() {
  const currentUser = Parse.User.current();
  if (currentUser) {
    console.log('Current user:', currentUser.get('username'));
    return currentUser;
  } else {
    console.log('No user is logged in.');
    return null;
  }
}

// Log out the current user
async function logOutUser() {
  try {
    await Parse.User.logOut();
    console.log('User logged out successfully.');
  } catch (error) {
    console.error('Error during logout: ' + error.message);
  }
}

// Example usage:
// signUpUser('testuser', 'password123', 'test@example.com');
// logInUser('testuser', 'password123');
// getCurrentUser();
// logOutUser();

3. Cloud Functions

Cloud Functions allow you to run server-side logic in response to client requests or Parse Server events (like beforeSave, afterDelete). They are crucial for implementing secure business logic and complex operations.

// cloud/main.js (Server-side Cloud Code)
Parse.Cloud.define('calculateAverageScore', async (request) => {
  const
## Anti-Patterns

**Over-engineering for hypothetical requirements.** Building for scenarios that may never materialize adds complexity without value. Solve the problem in front of you first.

**Ignoring the existing ecosystem.** Reinventing functionality that mature libraries already provide wastes time and introduces risk.

**Premature abstraction.** Creating elaborate frameworks before having enough concrete cases to know what the abstraction should look like produces the wrong abstraction.

**Neglecting error handling at system boundaries.** Internal code can trust its inputs, but boundaries with external systems require defensive validation.

**Skipping documentation.** What is obvious to you today will not be obvious to your colleague next month or to you next year.

Install this skill directly: skilldb add baas-skills

Get CLI access →