Backend

Backend overview

pleate-backend is a set of reusable Django apps on MongoDB that give every pleate component a ready REST API, and pleate-client connects the two with typed calls and React hooks.

The components in this library are only half of a product: a LoginForm needs an account system, a DataTable needs a paginated endpoint, a Composer needs a model that streams. The Backend section documents three packages that provide that other half, designed together so that the props a component takes are exactly what the API returns.

PackageLanguageWhat it is
pleate-backendPythonReusable Django 6.1 apps with Django REST Framework and an OpenAPI schema, on MongoDB.
pleate-clientTypeScriptA typed fetch client, Server-Sent Events, list helpers and React hooks that return props for pleate components.
apps/backend-demoPythonAn example Django project wired with every app, plus a Product resource that shows how to add your own.

How a request travels

Take the login screen. LoginForm calls onSubmit, which comes from useLogin().loginFormProps. The hook calls client.auth.login(), which fetches a CSRF cookie if needed and posts JSON to /api/auth/login. Django checks the rate limits, the password and the 2FA state, writes the session to MongoDB and answers either the user or {mfa_required: true}. The hook flips to the second step and the page renders TwoFactorForm with twoFactorFormProps. Errors come back in one format, so the same hook can put field messages under the right inputs.

  1. pleate component

    Your Next.js app

    <LoginForm>, <DataTable>, <Composer>…

  2. Hook

    pleate-client/react

    useLogin(), useList(), useChat()…

  3. Client

    pleate-client

    createPleateClient(): CSRF, errors, SSE, uploads

  4. REST API

    HTTP, same origin

    /api/auth, /api/files, /api/ai… JSON and SSE

  5. Django app

    pleate-backend

    pleate_backend.accounts, .files, .ai_chat…

  6. MongoDB

    Replica set

    django-mongodb-backend, GridFS for files

Browser layers on a white card, server layers tinted. Everything above the REST API runs in the browser.
app/login/page.tsx
"use client";
import { LoginForm } from "pleate/auth/login-form";
import { TwoFactorForm } from "pleate/auth/two-factor-form";
import { useLogin } from "pleate-client/react";

export default function Login() {
  const login = useLogin({ onSuccess: () => location.assign("/") });
  return login.mfaRequired
    ? <TwoFactorForm {...login.twoFactorFormProps} />
    : <LoginForm {...login.loginFormProps} />;
}

The apps

Each feature is its own Django app, mounted under its own prefix by pleate_backend.urls. Remove an app from INSTALLED_APPS and its routes, its /auth/me fields and its section of the data export disappear with it.

AppPrefixBacks
core/apiHealth, CSRF, errors, pagination, filters, realtime, cache, tasks
accounts/api/authLoginForm, SignupForm, ForgotPasswordForm, ResetPasswordForm, SessionList
mfa/api/auth/mfaTwoFactorForm, TwoFactorSetup
oauth/api/auth/oauthOAuthButtons
rbac/api/rbacRoles, object permissions, feature flags
apikeys/api/api-keysApiKeyList
files/api/filesFileUpload
notifications/api/notificationsNotificationBell, NotificationCenter
emailsTransactional emails for every other app
audit/api/activityTimeline, DataTable of activity
ratelimitThrottles and RateLimit headers
webhooks/api/webhooksOutgoing and incoming webhooks
ai_chat/api/aiChatThread, Composer, ModelPicker, PromptSuggestions, Reasoning
marketing/api/marketingNewsletter, ContactForm, waitlist
billing/api/billingPricing
staff/api/staffBack office tables and StatCard
usage/api/usageUsageMeter
search/api/searchCommandPalette

Why Django on MongoDB

The backend uses django-mongodb-backend, the official MongoDB backend for the Django ORM, instead of talking to MongoDB through PyMongo or an ODM such as MongoEngine. The choice is about what comes for free:

  • The Django ORM. Models, migrations, querysets, select_related, signals and transactions, the API every Django developer already knows. Your own models sit next to pleate's and can point at its User with a plain ForeignKey.
  • Django auth. Password hashing (Argon2), permissions, groups, sessions and authenticate() work unchanged, so roles and object permissions build on them instead of reinventing them.
  • The admin. Every app registers its models, so staff can browse users, files, bans or webhook deliveries on day one.
  • Django REST Framework and OpenAPI. Serializers, permissions, throttles, filters and drf-spectacular all need the ORM. The OpenAPI schema is what generates the TypeScript types of pleate-client.
  • The ecosystem. django-filter, django-storages, django-anymail and Celery plug in as they do on PostgreSQL. With PyMongo or MongoEngine each of these would need its own glue.

Where to go next

InstallationFrom an empty folder to a Next.js app talking to Django: Python package, settings, URLs, services, workers and the client.ConventionsEvery endpoint follows the same rules for lists, errors, CSRF, authentication, rate limits and language, so one client handles them all.AuthenticationEmail and password accounts with sessions, password reset, email verification and change, data export and account deletion.Two factorTOTP authenticator apps and single use backup codes, as a second step of the password and OAuth logins.OAuthSign in with Google, GitHub, Apple or any OpenID Connect provider, with PKCE, account linking and the 2FA step.Roles and permissionsRoles on top of Django groups, object level permissions, percentage rollouts and DRF permission classes that compose.API keysPersonal keys with read or write scopes and expiry, hashed at rest and accepted as Bearer tokens by every endpoint.Lists and tablesA plain DRF ViewSet, the useList hook and DataTable: server side search, sorting, filters and pagination in a few lines.FilesPrivate uploads with progress, type sniffing, image cleaning, quotas, downloads and direct S3 uploads.NotificationsOne notify() call reaches the in app inbox, email and Web Push, routed by user preferences and streamed live over SSE.EmailsTransactional emails from templates, localized, queued on Celery and delivered by SMTP or any provider through django-anymail.Activity logAn audit trail of who did what, when and from where, recorded automatically for account events and on demand for yours.Rate limiting and cacheSliding window throttles with standard headers, login lockouts, a caching decorator and ETags, all on the Django cache.Background tasksCelery runs emails, webhook deliveries and housekeeping. One worker with beat is all a project needs.WebhooksSigned outgoing webhooks with retries, delivery logs and an SSRF guard, plus helpers to receive webhooks exactly once.AI chatConversations with streamed answers, reasoning, sources, stop and regenerate, on Anthropic, OpenAI or any compatible server.MarketingNewsletter with double opt in, a contact form with a honeypot and a waitlist with referrals.BillingSubscriptions with Stripe Checkout, the customer portal and webhooks, configured as a list of plans that maps onto Pricing.StaffA back office API: users, roles, sessions, IP bans and the numbers for a dashboard.PreferencesTheme, palette, motion and bottom bar saved on the account, validated and merged one key at a time.UsageThe user's plan and how much of each limit they use: storage, AI tokens, API keys and webhooks, ready for UsageMeter.SearchOne query over the user's own files, conversations and notifications, shaped for a command palette.InternationalizationError messages and emails in the user's language: English, Italian and Spanish ship with the package.Client and hooksReference of pleate-client: every module of createPleateClient and every React hook with what it returns.Testingpytest against a real MongoDB for the backend, Vitest and the mock backend for the frontend.DeploymentEnvironment variables, processes, Redis, SSE and a security checklist for going to production.