README.md
Rama main · réplica de lectura del repositorio original.
<!--
~ Shields.io Config
~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ Default params:
~ style=for-the-badge
~ labelColor=404C5C
~ cacheSeconds=maxAge
~
~ Brand palette:
~ Success 4CAF50 · Error E53935 · Warning FFAB40
~ Purple 9C27B0 · Blue-grey 404C5C · Light-blue 039BE5 · Pink E040FB
-->
<p align="center">
<a href="https://aglyn.com" title="Go to aglyn.com">
<img src="docs/assets/readme/cover.png" alt="Aglyn — one platform, zero black boxes" width="100%" />
</a>
</p>
<h3 align="center">The clickable screen to create online.</h3>
<p align="center">
<i>Aglyn™ is a multi-tenant website-builder platform that turns a live, clickable canvas<br>
into a real business website — no code, no ceremony, no expensive rebuilds.</i>
</p>
<p align="center">
<a href="https://aglyn.com"><strong>aglyn.com</strong></a> ·
<a href="https://app.aglyn.com">Console</a> ·
<a href="https://docs.aglyn.com">Docs</a> ·
<a href="CONTRIBUTING.md">Contributing</a> ·
<a href="https://app.aglyn.com/manage/report-issue">Report a bug</a>
</p>
<p align="center">
<img src="https://img.shields.io/badge/Aglyn-Secure_Website-9C27B0?style=for-the-badge&labelColor=404C5C&color=9C27B0&logoHeight=40&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCI+PGRlZnM+PGNsaXBQYXRoIGlkPSJiIj48cmVjdCB3aWR0aD0iMjQiIGhlaWdodD0iMjQiLz48L2NsaXBQYXRoPjwvZGVmcz48ZyBpZD0iYSIgY2xpcC1wYXRoPSJ1cmwoI2IpIj48cmVjdCB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIGZpbGw9IiM0MDRjNWMiLz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzLjEyOCAyLjYyOSkiPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgMC43KSI+PHBhdGggZD0iTTE3LjQyMiwxOC41ODNIMTUuMjY5bC0yLjY3My01LjhINS40NTNMMi44LDE4LjU4M0guNTU3bDguMTg0LTE4aC42MTVabS01Ljc0OC03Ljg1M0w5LjA0OCw0Ljg4OCw2LjQsMTAuNzMxWiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNTU3IC0wLjU4MykiIGZpbGw9IiMwMzliZTUiLz48L2c+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMSAwLjM0NikiPjxwYXRoIGQ9Ik0xNy40MjIsMTguNTgzSDE1LjI2OWwtMi42NzMtNS44SDUuNDUzTDIuOCwxOC41ODNILjU1N2w4LjE4NC0xOGguNjE1Wm0tNS43NDgtNy44NTNMOS4wNDgsNC44ODgsNi40LDEwLjczMVoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjU1NyAtMC41ODMpIiBmaWxsPSIjOWMyN2IwIi8+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDIpIj48cGF0aCBkPSJNMTcuNDIyLDE4LjU4M0gxNS4yNjlsLTIuNjczLTUuOEg1LjQ1M0wyLjgsMTguNTgzSC41NTdsOC4xODQtMThoLjYxNVptLTUuNzQ4LTcuODUzTDkuMDQ4LDQuODg4LDYuNCwxMC43MzFaIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41NTcgLTAuNTgzKSIgZmlsbD0iI2ZmZiIvPjwvZz48L2c+PC9nPjwvc3ZnPg==" alt="Aglyn secure website"/>
<img src="https://img.shields.io/github/license/aglyn/aglyn?style=for-the-badge&labelColor=404C5C&color=4CAF50" alt="License" />
<img src="https://img.shields.io/github/package-json/v/aglyn/aglyn?style=for-the-badge&labelColor=404C5C&color=039BE5&label=version" alt="Version" />
</p>
<p align="center">
<img src="https://img.shields.io/badge/Next.js-16-000000?style=for-the-badge&labelColor=404C5C&logo=nextdotjs" alt="Next.js" />
<img src="https://img.shields.io/badge/React-19-087EA4?style=for-the-badge&labelColor=404C5C&logo=react" alt="React" />
<img src="https://img.shields.io/badge/TypeScript-6/7-3178C6?style=for-the-badge&labelColor=404C5C&logo=typescript&logoColor=white" alt="TypeScript" />
<img src="https://img.shields.io/badge/Firebase-12-FFCA28?style=for-the-badge&labelColor=404C5C&logo=firebase&logoColor=white" alt="Firebase" />
<img src="https://img.shields.io/badge/MUI-9-007FFF?style=for-the-badge&labelColor=404C5C&logo=mui&logoColor=white" alt="MUI" />
<img src="https://img.shields.io/badge/MobX-6-FF9955?style=for-the-badge&labelColor=404C5C&logo=mobx&logoColor=white" alt="MobX" />
<img src="https://img.shields.io/badge/Nx-23-143055?style=for-the-badge&labelColor=404C5C&logo=nx&logoColor=white" alt="Nx" />
<img src="https://img.shields.io/badge/Node-%E2%89%A524-5FA04E?style=for-the-badge&labelColor=404C5C&logo=nodedotjs&logoColor=white" alt="Node 24+" />
</p>
<hr/>
## ✨ What is Aglyn?
Aglyn takes the pain out of getting a professional website off the ground. Instead of hiring
engineers or wrestling with templates, you build on a **live, clickable canvas** — the _Besigner™_ —
where what you click is what you ship. Every element, page, and interaction is editable in place, and
publishing is instant across a globally-served, multi-tenant runtime.
It's a full platform, not just an editor: organizations, billing, a plugin marketplace, a digital
asset manager, e-commerce, bookings, email, workflows, and a documented REST API all live under one
roof.
> **Three surfaces, one platform**
> · [`aglyn.com`](https://aglyn.com) — the marketing site
> · [`app.aglyn.com`](https://app.aglyn.com) — where you build, manage orgs & billing
> · `aglyn.app` + your own custom domain — where your published site is served to the world
## 📸 Take a look
<p align="center">
<img src="docs/assets/readme/besigner-editor.png" alt="The Aglyn Besigner — a clickable, in-place editing canvas" width="100%" />
</p>
<p align="center"><i><b>The Besigner™</b> — a clickable, in-place canvas where design and content live on the same surface. What you click is what you ship.</i></p>
<table>
<tr>
<td width="50%" align="center" valign="top">
<img src="docs/assets/readme/console-dashboard.png" alt="Aglyn console dashboard" width="100%" />
<br /><sub><b>Console dashboard</b> — traffic, users, campaigns & activity at a glance</sub>
</td>
<td width="50%" align="center" valign="top">
<img src="docs/assets/readme/console-commerce.png" alt="Aglyn commerce products hub" width="100%" />
<br /><sub><b>Built-in commerce</b> — products, pricing, orders & POS</sub>
</td>
</tr>
</table>
## 🚀 Highlights
| | |
|---|---|
| 🖱️ **Besigner canvas** | A clickable, in-place visual editor — design and content on the same surface. |
| 🌐 **True multi-tenancy** | One runtime serves every customer site, on `aglyn.app` or a custom domain, with ISR. |
| 🧩 **Plugin platform** | Commerce, Bookings, Contacts, Email, Events, Workflows, Redirects & more — installable per org, with a review-queued marketplace. |
| 🎨 **Theme & layout builder** | Design tokens, themes, and layout templates that stay consistent across every page. |
| 🖼️ **Digital Asset Manager** | Drag-and-drop media, folders, custom metadata, and stable CDN URLs that survive replace & move. |
| 🛒 **Built-in commerce** | Products, pricing, POS, and digital goods powered by Stripe. |
| 🔐 **Security first** | Firebase Auth with email-verify gates, durable rate limiting, CSRF protection, and rules-tested Firestore. |
| ⚡ **Modern stack** | Next.js App Router, React 19, server components, and an Nx-orchestrated monorepo. |
| 🔌 **Customer REST API** | Scoped `aglyn_sk_` API keys for programmatic access on Business plans. |
| 📚 **Docs that ship with the code** | Four Docusaurus instances (docs, api, learn, help) kept in sync with features. |
## 🏗️ Inside the monorepo
An [Nx](https://nx.dev) workspace organized into deployable **apps** and shareable **libs**.
```
aglyn/
├─ apps/
│ ├─ 🛠️ console → dashboard, editor, billing (app.aglyn.com)
│ ├─ 🚀 tenant → runtime for published sites (aglyn.app + custom domains)
│ └─ 📖 docs → Docusaurus documentation
│
├─ libs/
│ ├─ aglyn → core platform library
│ ├─ aglyn-node-renderer → server-side page renderer
│ ├─ besigner/ → the clickable visual editor (core + designer)
│ ├─ tenant/runtime → shared tenant runtime (host events + composition)
│ ├─ plugins/ → bookings · commerce · contacts · data · email
│ │ events-calendar · inbox · logic · marketing
│ │ marketplace · mui · redirects · workflows
│ └─ shared/ → data · ui · util building blocks
│ ├─ data/ → enums · forms · mdi · regex · types
│ ├─ ui/ → jsx · jsx-forms · theme · color-picker · json-editor · next · …
│ └─ util/ → dom · email · errors · fbserver · http · logger · …
│
└─ cloud/ → Firebase (functions, Firestore/Storage rules, Remote Config)
```
**Library conventions** — each lib is one of four types, so dependencies stay predictable:
- **Feature** — smart UI with data access, for a specific business use case.
- **UI** — presentational ("dumb") components only.
- **Data-access** — back-end interaction and state management.
- **Utility** — low-level helpers shared broadly.
## 🧰 Tech stack
| Area | Tools |
|---|---|
| **Framework** | Next.js 16 (App Router, RSC) · React 19 |
| **Language** | TypeScript (dual `typescript@6` bridge + `@typescript/native@7` for `tsc`) |
| **UI** | MUI 9 · MobX 6 · Data-Driven Forms 4 |
| **Backend** | Firebase (Auth, Firestore, Storage, Remote Config) · Cloud Functions · `firebase-admin` 14 |
| **Payments & email** | Stripe · Resend |
| **Monorepo** | Nx 23 |
| **Testing** | Jest 30 (unit) · Playwright + Firebase emulators (e2e) |
| **Runtime** | Node ≥ 24 |
## ⚡ Quick start
> **Prerequisites:** Node ≥ 24, npm, and the [Firebase CLI](https://firebase.google.com/docs/cli)
> for local emulation.
```bash
# 1. Install dependencies
npm install
# 2. Copy the example environment and fill in the blanks
cp .env.example .env
# 3. Serve an app (console, tenant, or docs)
npx nx serve console
```
The dev server hot-reloads on http://localhost:4200. Use `--prod` for a production build.
### Run against the Firebase emulators
```bash
# Start the emulators (imports/exports local data)
firebase emulators:start --import=./.firebase --export-on-exit
# Serve the console wired to the emulators
npm run serve:console:emulated
```
Default emulator hosts: Firestore `localhost:8082`, Auth `localhost:9099`. See
[`docs/E2E_LOCAL.md`](docs/E2E_LOCAL.md) for the full local end-to-end recipe.
## 🐳 Self-hosting
Run the whole platform on your own infrastructure with Docker — any cloud, a
VPS, or bare metal — pointed at **your own Firebase project** and your own
Stripe/Resend keys:
```bash
cp .env.selfhost.example .env.selfhost # fill it in
docker compose up --build
```
Console on `:4200`, published sites on `:4500`, your reverse proxy in front.
The full runbook — Firebase project setup, security-rules deploy, DNS, and the
honest limits (Firebase is required; the in-console custom-domain flow is
Vercel-only) — lives in [`docs/SELF_HOSTING.md`](docs/SELF_HOSTING.md).
## 🛠️ Common commands
| Task | Command |
|---|---|
| Serve an app | `nx serve <app>` (`--prod` for production) |
| Build an app | `nx build <app>` → output in `dist/` |
| Unit tests | `nx test <app>` · affected only: `nx affected:test` |
| E2E tests | `nx e2e <app-e2e>` · affected only: `nx affected:e2e` |
| Lint | `nx lint` · workspace: `npm run lint` |
| Type-check | `npm run typecheck` |
| Format | `npm run format` |
| Dependency graph | `nx graph` |
| Check/reclaim dev-cache disk | `npm run clean:next` · delete: `npm run clean:next:prune` |
> **Tools suddenly failing with `ENOSPC`, hanging, or killing your shell?** Check the disk before
> anything else — `apps/*/.next/dev/cache/turbopack` grows across a long dev session and has twice
> filled a 460 GB volume. Nothing in the error will mention the disk. See
> [Build performance](docs/BUILD_PERFORMANCE.md#if-your-tools-start-failing-for-no-reason-check-the-disk-first-agl-1425).
Scaffolding new projects:
```bash
nx g @nx/next:app <app-name> # new Next.js app
nx g @nx/react:lib <lib-name> # new React library
nx g @nx/react:component <name> --project=<app>
```
Libraries are shareable and imported as `@aglyn/<name>` (e.g. `@aglyn/shared-ui-jsx`).
## 📖 Documentation
📚 **Full product & developer docs live at [docs.aglyn.com](https://docs.aglyn.com).**
Repo-local deep-dives live in [`docs/`](docs), including:
- [Self-hosting](docs/SELF_HOSTING.md) · [Multi-tenant Firestore](docs/MULTI_TENANT_FIRESTORE.md) · [Platform provisioning](docs/PLATFORM_PROVISIONING.md)
- [Plugin loading](docs/PLUGIN_LOADING.md) · [Plugin platform gaps](docs/PLUGIN_PLATFORM_GAPS.md)
- [Rate limiting](docs/RATE_LIMITING.md) · [Security content review](docs/SECURITY_CONTENT_REVIEW.md) · [Analytics event taxonomy](docs/ANALYTICS.md)
- [Email setup](docs/EMAIL_SETUP.md) · [Stripe go-live](docs/STRIPE_GO_LIVE.md) · [Commerce token signing](docs/COMMERCE_TOKEN_SIGNING.md)
- [Vercel deployments](docs/VERCEL_DEPLOYMENTS.md) · [Build performance](docs/BUILD_PERFORMANCE.md) · [TypeScript 7](docs/TYPESCRIPT7.md)
- [Backfills, migrations and seeds](docs/BACKFILLS_AND_SEEDS.md) · [Commerce backfills](docs/COMMERCE_BACKFILLS.md) · [CRM lifecycle backfill](docs/CRM_LIFECYCLE_BACKFILL.md)
## 🤝 Contributing
We follow [Conventional Commits](https://www.conventionalcommits.org) — commit messages are linted.
```
<type>[(optional-scope)]: <description>
[optional body]
[optional footer(s)]
```
Common types: `feat` (new feature → minor), `fix` (bug patch → patch), plus `build`, `chore`, `ci`,
`docs`, `style`, `refactor`, `perf`, `test`, and `revert`. A `!` after the type/scope or a
`BREAKING CHANGE:` footer signals a major change.
See [CONTRIBUTING.md](CONTRIBUTING.md), the [Code of Conduct](CODE_OF_CONDUCT.md), and
[SECURITY.md](SECURITY.md) before opening a PR.
## 🌍 Terminology
- **Organization** — the entity that owns sites, members, and billing.
- **Workspace** — the UX word for an organization's working area.
- **Tenant** — a site at runtime (the served, published surface only).
- **Besigner** — Aglyn's clickable visual editor.
- **Plugin / Add-on** — pluggable, first- or third-party modules that extend an org or app while
respecting its architecture.
- **Extension** — deeper, non-standard integrations that modify default behavior; typically
third-party authored.
<hr/>
<h3 align="center">Connect with us</h3>
<p align="center">
<a href="https://www.linkedin.com/company/aglyn" title="LinkedIn">
<img src="https://img.shields.io/badge/LinkedIn-Follow-0A66C2?logo=linkedin&style=for-the-badge&labelColor=F1F1F1&logoColor=0A66C2&color=0A66C2" alt="LinkedIn" />
</a>
<a href="https://x.com/AglynSoftware" title="X">
<img src="https://img.shields.io/badge/@AglynSoftware-Follow-000000?logo=x&style=for-the-badge&labelColor=F1F1F1&logoColor=000000&color=000000" alt="X" />
</a>
<a href="https://www.facebook.com/AglynSoftware/" title="Facebook">
<img src="https://img.shields.io/badge/Facebook-Follow-1877F2?logo=facebook&style=for-the-badge&labelColor=F1F1F1&logoColor=1877F2&color=1877F2" alt="Facebook" />
</a>
<a href="https://www.instagram.com/aglyn_software/" title="Instagram">
<img src="https://img.shields.io/badge/Instagram-Follow-E4405F?logo=instagram&style=for-the-badge&labelColor=F1F1F1&logoColor=E4405F&color=E4405F" alt="Instagram" />
</a>
</p>
<p align="center">
<a href="https://www.tiktok.com/@aglyn_software" title="TikTok">
<img src="https://img.shields.io/badge/TikTok-Follow-000000?logo=tiktok&style=for-the-badge&labelColor=F1F1F1&logoColor=000000&color=000000" alt="TikTok" />
</a>
<a href="https://www.youtube.com/Aglyn" title="YouTube">
<img src="https://img.shields.io/badge/YouTube-Subscribe-FF0000?logo=youtube&style=for-the-badge&labelColor=F1F1F1&logoColor=FF0000&color=FF0000" alt="YouTube" />
</a>
<a href="https://www.crunchbase.com/organization/aglyn" title="Crunchbase">
<img src="https://img.shields.io/badge/Crunchbase-Aglyn-0288D1?logo=crunchbase&style=for-the-badge&labelColor=F1F1F1&logoColor=0288D1&color=0288D1" alt="Crunchbase" />
</a>
<a href="https://github.com/aglyn" title="GitHub org">
<img src="https://img.shields.io/badge/GitHub-aglyn-181717?logo=github&style=for-the-badge&labelColor=F1F1F1&logoColor=181717&color=404C5C" alt="GitHub" />
</a>
</p>
<h2 align="center">About Aglyn</h2>
<p align="center">
Aglyn LLC is a distributed technology company building the clickable way to create online.
We're improving the no-code web-development market by shrinking the distance between an idea and a
live, professional website — easing maintenance and minimizing the expensive engineering work a
business site usually demands.
</p>
<hr/>
<p align="center">
<a href="LICENSE"><strong>Apache License 2.0</strong></a> · © Aglyn LLC
</p>