Skip to main content

Intro to Moopsy

Moopsy is a JavaScript framework for building apps that behave reliably and predictably. Moopsy handles communication between the client and the server. It leverages TypeScript to take the guess work out on both ends, and ensure both sides adhere to the contract.

They key to Moopsy is how it enforces the contract, using a centralized set of common TypeScript types, making sure the frontend and the backend are always reading from the same book.

It's fairly lightweight and lighting fast in development and in production. It's also super flexible, presenting as a set of simple packages whose behavior can easily be tweaked rather than an over-arching framework that locks you in.

Philosophy of Moopsy

Moopsy is designed to remove the complexities and work around type-safety, both statically and during runtime. Rather than relying on the developer to ensure that best practices are always followed, Moopsy enforces these best practices (like how it enforces contracts on the frontend and backend) or applies them for you (like how it auto-generates and checks against JSON schemas).

How does Moopsy work?

At the core of Moopsy is the Blueprint. A Blueprint is a TypeScript file that defines the structure of a specific endpoint.

Here's an example Blueprint:

import { MessageContentType } from "../../types/chat/message";

export type ParamsType = {
content: MessageContentType;
chatUUID: string;
idp: string;
};
export type ResponseType = {
messageUUID: string;
};
export const Endpoint = 'chat/send-message';
export const Method = 'POST';

export interface Plug {
params: ParamsType;
response: ResponseType;
method: typeof Method;
endpoint: typeof Endpoint;
}

export const isPublic = false;
export const RateLimitingConfig = {
calls: 4,
per: 1000,
};

Let's walk through what we define here.

  • We define ParamsType, the parameters the client needs to call the endpoint with
  • We define ResponseType, the response the server must send back (this doesn't include Moopsy' built-in error handling behavior)
  • We define Endpoint, a unique name for the endpoint. We recommend this stays in a path-style format
  • We define Method, this is the HTTP type for the method. While Moopsy doesn't actually care about this, it can be useful in the future if you'd ever like to expose your Moopsy methods over REST.
  • We define Plug, where we package up all of our types and constants into a single interface, this just makes it easy for us to pass our types around as we have one type to work with instead of 4 separate ones
  • We define isPublic, an optional variable that determines whether or not the user must be authenticated to call this method (default is false if no value specified, but we've included it here for verbosity)
  • Finally, we define (an optional) RateLimitingConfig, which lets us setup some basic rate limiting

The idea behind Moopsy is both the client and server hold on to a copy of this file, and use it for type validation. The Moopsy client and server APIs are type-strict and will enforce that the typing is being followed.

Does Moopsy make this easy for me?

Yes, at least we hope so! Let's take a look at the default structure for a Moopsy project:

frontend/
backend/
common/

frontend/, holds your frontend code. backend/, holds your backend code. common/, holds any files that need to be common between them. Let's open up common/.

frontend/
backend/
common/
src/
blueprints/
types/

@moopsyjs/devtools automatically ensures that everything inside common/src is copied over to frontend/src and backend/src. It copies each folder as a whole, meaning the common/src/blueprint folder will completely overwrite any frontend/src/blueprint folder. You can add additional folders inside src/ if you'd like, but remember they'll overwrite not merge.

In your blueprints/ folder, you should keep all your blueprints. We recommend maintaing a folder structure that matches the Endpoint field, so the Blueprint for the endpoint chat/send-message should go into common/src/blueprints/chat/send-message.ts.

In your types/ folder, you should keep all your types that you want to be synced over, as well as any types that need to be referenced by a Blueprint. At Hiyllo, we break it down by feature, so all type files related to the chat feature would go in types/chat.

Now what?

Head over to Quick Start and dive in!