Skip to content

varshneydevansh/backy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2,716 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Backy

Free, open-source visual website builder and CMS backend. Product name is backy.

License: MIT TypeScript React Supabase


What Backy is

Backy is a backend-first, open-source CMS platform with a drag-and-drop editor.
The goal is to give non-technical and technical teams a complete website-authoring backend with API-first output for any custom frontend.


Features

  • Wix-like visual editor (canvas + absolute layout, components, properties, preview).
  • CMS workflows (sites, pages, blog posts, media, forms, comments).
  • Team and role-based access model.
  • Public rendering and API surface for custom frontends.
  • Theme system (colors, spacing, fonts, tokens).

Repo structure

backy/
├── apps/
│   ├── admin/   # Backy admin UI + editor + management
│   └── public/  # Backy public renderer + public endpoints
├── packages/
│   ├── core/    # Shared types and utilities
│   ├── database/# DB adapters and queries
│   ├── auth/    # Auth/contracts/helpers
│   ├── storage/ # Storage abstraction
│   ├── editor/  # Editor-specific UI logic
│   └── billing/ # Billing layer (future/optional)
├── specs/       # Product and implementation specs
├── supabase/    # Database migrations
└── scripts/     # Setup/build helpers

Quick start

1) Clone

git clone <your-fork>/backy.git backy
cd backy

2) Install

npm install

3) Configure env

# apps/admin/.env
VITE_BACKY_PUBLIC_API_BASE_URL=http://localhost:3001/api
VITE_BACKY_ADMIN_API_BASE_URL=http://localhost:3001/api/admin
VITE_BACKY_ADMIN_API_KEY=dev-admin-key-change-me

4) Start

npm run dev

Admin runs on http://localhost:5173; public app runs on http://localhost:3001.


Deployment model (recommended for production)

Backy is designed to run as two deployable apps:

  1. backy-admin
    • Admin UI
    • Content editor
    • DB/write operations
  2. backy-public
    • Public page rendering
    • Read endpoints
    • Form/comment submission endpoints

For external/custom frontends, use the public endpoints from apps/public directly and treat backy-public as your headless CMS host. AI agents and external frontend teams should start with GET /api/sites/:siteId/agent-handoff; it returns a copyable agentBrief, canonical read order, manifest/OpenAPI/render/SDK pointers, every-component APIability rules, canvas-first creation routes, and design-state round-trip rules required for Backy canvas compatibility. Use specs/custom-frontend-agent-handoff.md as the human-readable companion.

Use npm run test:custom-frontend-connection when connecting a separate website frontend. With BACKY_CUSTOM_FRONTEND_API_BASE_URL=https://<backy-public-domain>/api and BACKY_CUSTOM_FRONTEND_SITE_ID=<site-id-or-slug>, it proves the public site discovery, agent-handoff, manifest, OpenAPI, resolve, and render contracts. Add BACKY_CUSTOM_FRONTEND_URL=https://<frontend-domain>, BACKY_CUSTOM_FRONTEND_REQUIRE_FRONTEND=1, and BACKY_CUSTOM_FRONTEND_REQUIRE_PROBE=1 after deploying the website to prove the rendered DOM still exposes Backy element ids, element types, component-contract pointers, editable-map pointers, and the deployed frontend's public /api/backy-connection self-check reports no forbidden private env names.

If you need the shortest release-critical custom frontend check, run npm run test:custom-frontend-control-plane. It chains the checked starter, custom frontend connection contract, Vercel production-readiness contract, and public-repo hygiene. The command is safe without private values; pass the live BACKY_CUSTOM_FRONTEND_* and BACKY_VERCEL_* environment variables to the underlying gates when certifying a real deployment.

Vercel release runbook

Create two Vercel projects from this repo so admin/editor traffic and public/custom frontend traffic stay operationally separate.

backy-public

  • Root Directory: apps/public
  • Framework Preset: Next.js
  • Build Command: npm --prefix=../.. run build:vercel:public
  • Development Command: npm run dev
  • Runtime config: set BACKY_DATA_MODE=database, BACKY_DATABASE_URL, BACKY_ADMIN_API_KEY, BACKY_ADMIN_SECRET_KEY, storage/provider secrets, NEXT_PUBLIC_BACKY_ADMIN_APP_URL, and exact custom-frontend origins in BACKY_CORS_ALLOWED_ORIGINS.
  • Cron config: apps/public/vercel.json schedules /api/admin/commerce/reconcile?limit=100 at 0 3 * * *.
  • Cron protection: set CRON_SECRET to the same server-only value as BACKY_ADMIN_API_KEY or BACKY_ADMIN_SECRET_KEY. Vercel sends it as a bearer token, and Backy authenticates the scheduled reconciliation request through the admin-key path.

backy-admin

  • Root Directory: apps/admin
  • Framework Preset: Vite
  • Build Command: npm --prefix=../.. run build:vercel:admin
  • Output Directory: dist
  • Runtime config: set VITE_BACKY_PUBLIC_API_BASE_URL=https://<backy-public-domain>/api and VITE_BACKY_ADMIN_API_BASE_URL=https://<backy-public-domain>/api/admin. Production admin auth uses session login plus the httpOnly backy_admin_session cookie against backy-public; do not put admin API keys in Vite/client environment variables.
  • SPA routing and baseline headers are tracked in apps/admin/vercel.json.

Protected topology

  • Keep backy-admin protected with Vercel Deployment Protection, team SSO, or an equivalent access-control layer. It is only the editor/admin shell; it must not receive server-only database, storage, provider, cron, or admin API keys.
  • Keep backy-public public for rendering, discovery, forms, comments, newsletter signup, and custom frontend API reads. Server-only admin APIs still require session cookies or admin API keys.
  • Run custom website frontends as separate Vercel projects when useful. Each frontend should set BACKY_PUBLIC_API_BASE_URL=https://<backy-public-domain>/api, BACKY_SITE_ID=<site-id-or-slug>, and optionally BACKY_SITE_PUBLIC_HOST=<custom-host>.
  • Subdomains such as studio.example.com, blog.example.com, or docs.example.com are modeled as site custom domains. Use one Backy site per independent subdomain when content, navigation, SEO, or design tokens differ.
  • Frontend builders and AI agents should start with GET /api/sites/:siteId/agent-handoff, then read manifest, OpenAPI, render, and frontend-design before creating UI or templates. Do not copy Backy content into a frontend-local JSON source of truth.
  • Before handing a separate website frontend to users, run BACKY_CUSTOM_FRONTEND_API_BASE_URL=https://<backy-public-domain>/api BACKY_CUSTOM_FRONTEND_SITE_ID=<site-id-or-slug> npm run test:custom-frontend-connection. After the custom frontend is deployed, also set BACKY_CUSTOM_FRONTEND_URL=https://<frontend-domain>, BACKY_CUSTOM_FRONTEND_REQUIRE_FRONTEND=1, and BACKY_CUSTOM_FRONTEND_REQUIRE_PROBE=1 so the gate verifies the public page DOM keeps Backy control attributes and the frontend exposes a secret-free connection probe.
  • Keep npm run test:custom-frontend-control-plane green before pausing or handing work to another agent. The only launch gates it intentionally does not complete are operator-owned: granting Vercel access to a private website repository, adding branch/Preview env after Git connection, moving DNS for the final public host, and supplying real live provider certification artifacts.
  • Optional Vercel Agent: after the two projects are linked, enable Vercel Agent Code Review from each project's Project Settings -> AI page. It is a Vercel platform setting; Backy does not need a runtime package or client-visible secret for it.
Vercel project Public status Domains Required env Forbidden env
backy-public Public app with protected admin API routes content.<domain> or the Backy API/rendering domain BACKY_DATA_MODE=database, BACKY_DATABASE_URL/DATABASE_URL or Vercel Marketplace POSTGRES_URL, BACKY_ADMIN_API_KEY, BACKY_ADMIN_SECRET_KEY, provider/storage secrets, CRON_SECRET, NEXT_PUBLIC_BACKY_ADMIN_APP_URL, and exact custom-frontend origins in BACKY_CORS_ALLOWED_ORIGINS Client-exposed copies of database, storage, provider, cron, or admin secrets
backy-admin Protected admin shell admin.<domain> or private Vercel preview/production URL VITE_BACKY_PUBLIC_API_BASE_URL, VITE_BACKY_ADMIN_API_BASE_URL BACKY_DATABASE_URL, storage/provider secrets, CRON_SECRET, BACKY_ADMIN_API_KEY, BACKY_ADMIN_SECRET_KEY, and any VITE_* admin key
Custom frontend Public website/app www.<domain>, blog.<domain>, studio.example.com, or another site-specific domain BACKY_PUBLIC_API_BASE_URL, BACKY_SITE_ID, optional BACKY_SITE_PUBLIC_HOST Backy admin URLs, admin/session secrets, provider secrets, database URLs, or copied Backy content as a second source of truth

Backy-hosted routes in apps/public currently support /sites/<site-slug> paths and custom-domain lookup through the public site APIs. For separate custom frontend projects, resolve the site by BACKY_SITE_ID first, then use BACKY_SITE_PUBLIC_HOST only as metadata for canonical URLs, SEO, and domain ownership until host-based rendering is promoted through the production-hardening gate.

Secure admin account setup

The local seeded accounts are for development only. Production admin access should not depend on committed emails, passwords, or client-visible keys.

  • Configure Supabase Auth or another provider-backed login on backy-public with server-side env only: BACKY_SUPABASE_URL plus BACKY_SUPABASE_ANON_KEY or a server-only service-role key when needed by the provider path.
  • For a fresh production database, create the first real owner through POST /api/admin/auth/bootstrap-owner using a server-only BACKY_OWNER_BOOTSTRAP_TOKEN. The endpoint creates the Supabase Auth user, Backy owner profile, and initial workspace membership, then refuses to create another active owner.
  • Create the real owner/editor users in the Backy database and keep their email addresses aligned with the identity provider. Backy grants workspace roles from its own user records after provider authentication succeeds.
  • Keep MFA configured for production with BACKY_ADMIN_MFA_TOTP_SECRET or user recovery codes stored in the persistent settings store; use BACKY_ADMIN_MFA_CODE only for controlled development or disposable certification runs.
  • Keep BACKY_ADMIN_API_KEY, BACKY_ADMIN_SECRET_KEY, CRON_SECRET, database URLs, storage/provider secrets, and payment keys on backy-public server-side env. Do not configure them on backy-admin, custom frontends, NEXT_PUBLIC_*, or VITE_* variables.
  • Do not enable BACKY_ALLOW_PRODUCTION_LOCAL_ADMIN_AUTH or BACKY_ALLOW_PRODUCTION_DEMO_MODE for a release. The production build guard rejects those flags so a demo-auth deployment cannot be promoted accidentally.
  • Use Vercel Deployment Protection or SSO on backy-admin even though API/session enforcement also lives on backy-public; the editor shell should not be broadly discoverable.

Example first-owner bootstrap request. Keep the token and password out of Git, shell history, screenshots, and frontend env:

curl -X POST https://<backy-public-domain>/api/admin/auth/bootstrap-owner \
  -H "content-type: application/json" \
  -H "authorization: Bearer $BACKY_OWNER_BOOTSTRAP_TOKEN" \
  --data '{"email":"you@example.com","password":"use-a-long-private-password","fullName":"Your Name"}'

After the first owner is created, immediately remove BACKY_OWNER_BOOTSTRAP_TOKEN from the backy-public production environment and redeploy so the active production runtime no longer carries the bootstrap secret. The endpoint also refuses a second active owner, but the token should still be treated as one-use only.

If no transactional email provider is configured, the hosted Forgot Password form will not send an email. It returns the same neutral response for every address to avoid account enumeration and reports local-outbox as not_configured. To regain access, use an owner-assisted reset in the identity provider: in Supabase, open Authentication -> Users, select the owner email, set a new password, and then sign in through backy-admin. Configure BACKY_EMAIL_PROVIDER=resend with BACKY_RESEND_API_KEY, or SMTP/HTTP delivery env, before relying on emailed recovery or invite delivery.

Run npm run test:vercel-release-config && npm run test:vercel-preview-readiness && npm run test:vercel-production-readiness && npm run test:custom-frontend-connection && npm run test:repo-public-hygiene before release to verify the checked-in Vercel topology, launch homepage links, local Vercel CLI auth, packaging ignores, project linkage, GitHub repository connection, env-boundary warnings, production promotion rules, custom frontend connection rules, public repo hygiene, and expected remote project names. For strict operator validation, run BACKY_VERCEL_REQUIRE_CLI=1 BACKY_VERCEL_REQUIRE_PROJECT_LINKS=1 BACKY_VERCEL_REQUIRE_REMOTE_PROJECTS=1 BACKY_VERCEL_REQUIRE_REMOTE_ENV=1 npm run test:vercel-preview-readiness after creating/linking backy-public and backy-admin and configuring the required Vercel env on both projects.

Use Vercel CLI 47.2.2+ for preview deploys; the local global CLI may be older, so npx vercel@latest is the safest release command. The repo root and app roots include .vercelignore files so local .next, dist, cache, Vercel link, and node_modules folders are not uploaded as source.

Deploy from the repo root after linking that root to the target Vercel project. The Vercel project Root Directory still points at the app, so the build command must jump back to the monorepo root and build workspace packages first:

npx vercel@latest link --project backy-public --yes
npx vercel@latest deploy --target=preview --yes

npx vercel@latest link --project backy-admin --yes
npx vercel@latest deploy --target=preview --yes \
  --build-env VITE_BACKY_PUBLIC_API_BASE_URL=https://<backy-public-preview>/api \
  --build-env VITE_BACKY_ADMIN_API_BASE_URL=https://<backy-public-preview>/api/admin

Do not use the current prebuilt standalone output as release proof for backy-public; it can produce static assets without the Next.js API routes Backy needs for /api/sites/:siteId/agent-handoff, manifest, OpenAPI, render, forms, and admin API traffic.

Production promotion gate

Never promote a preview or production alias while BACKY_DATA_MODE=demo, while database/provider/storage env is missing, or while the public production URL cannot serve Backy JSON contracts. A Vercel deployment can be marked Ready even when the public alias points at a stale static build, so production proof must hit the final public domain directly.

Vercel production builds run a public env guard before Next.js builds. Missing BACKY_DATA_MODE=database, database URL, admin keys, cron secret, admin app URL, or CORS origins now fail the production build early instead of producing a Ready deployment with crashing API routes. The guard also rejects production builds that leave BACKY_ALLOW_PRODUCTION_DEMO_MODE or BACKY_ALLOW_PRODUCTION_LOCAL_ADMIN_AUTH enabled. Run npm run test:vercel-public-production-env-guard when changing the guard or release scripts.

Before promoting or sharing a production URL, set BACKY_DATA_MODE=database on backy-public, configure real Supabase/Postgres, storage/provider, admin/session, cron, and CORS env, then run:

BACKY_VERCEL_PRODUCTION_URL=https://<backy-public-production-domain> \
BACKY_VERCEL_REQUIRE_LIVE_PRODUCTION=1 \
npm run test:vercel-production-readiness

The live gate fetches:

  • /api/sites?identifier=site-demo
  • /api/sites?limit=1
  • /api/sites/site-demo/agent-handoff
  • /api/sites/site-demo/manifest
  • /api/sites/site-demo/openapi
  • /api/sites/site-demo/render?path=/

All endpoints must return JSON from the final public domain. The discovery checks prove the production database exposes a published Backy site through public bootstrap, while the site-scoped checks prove handoff, manifest, OpenAPI, and render contracts. A 401 Vercel protection page, 404 NOT_FOUND, static HTML, empty public site discovery, or missing production-readiness topology is a failed production proof. Use BACKY_VERCEL_PRODUCTION_SITE_ID=<site-id-or-slug> when certifying a non-demo production site.

When you need to certify that production admin auth is live too, provide credentials only through local shell/Vercel CI secrets and add the admin proof flag:

BACKY_VERCEL_PRODUCTION_URL=https://<backy-public-production-domain> \
BACKY_VERCEL_REQUIRE_LIVE_PRODUCTION=1 \
BACKY_VERCEL_REQUIRE_LIVE_ADMIN_AUTH=1 \
BACKY_VERCEL_ADMIN_EMAIL=<owner-or-admin-email> \
BACKY_VERCEL_ADMIN_PASSWORD=<private-password> \
npm run test:vercel-production-readiness

If the account requires MFA, also set BACKY_VERCEL_ADMIN_MFA_CODE or BACKY_VERCEL_ADMIN_TWO_FACTOR_CODE. The readiness smoke posts to /api/admin/auth/login, restores /api/admin/auth/session, and logs out through /api/admin/auth/logout without printing credential values, session tokens, or cookies.

The public repository should also stay neutral: do not commit local absolute paths, personal email addresses, generated Vercel deployment URLs, Vercel project/team/deployment ids, or user-specific domains. npm run test:repo-public-hygiene guards the generic cases; local operators can add private marker checks with BACKY_REPO_HYGIENE_PRIVATE_MARKERS without committing those markers.


Documentation and tracking


License

This project is licensed under MIT. See LICENSE.


Built for people who want full control without SaaS lock-in.

About

Wix like backend CMS with Wordpress like simplicity

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors