{"id":14956782,"url":"https://github.com/mx-space/core","last_synced_at":"2026-05-19T09:08:39.518Z","repository":{"id":36991934,"uuid":"385975421","full_name":"mx-space/core","owner":"mx-space","description":"AI-powered CMS core for personal blogs and creator websites, with AI summaries, translation, moderation, and writing workflows.","archived":false,"fork":false,"pushed_at":"2026-04-15T14:32:42.000Z","size":19217,"stargazers_count":517,"open_issues_count":16,"forks_count":139,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-04-15T16:33:59.836Z","etag":null,"topics":["ai","ai-cms","ai-summary","ai-translation","blog-cms","content-workflow","creator-tools","headless-cms","llm","mongodb","nestjs","personal-blog","redis","self-hosted","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mx-space.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["innei"],"custom":["https://afdian.com/@Innei"]}},"created_at":"2021-07-14T14:47:50.000Z","updated_at":"2026-04-14T02:14:17.000Z","dependencies_parsed_at":"2026-01-08T16:04:23.738Z","dependency_job_id":null,"html_url":"https://github.com/mx-space/core","commit_stats":{"total_commits":3506,"total_committers":25,"mean_commits":140.24,"dds":0.616657159155733,"last_synced_commit":"a659ed2f793cdbe0370d96adaf137341e1acf186"},"previous_names":[],"tags_count":576,"template":false,"template_full_name":null,"purl":"pkg:github/mx-space/core","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mx-space%2Fcore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mx-space%2Fcore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mx-space%2Fcore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mx-space%2Fcore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mx-space","download_url":"https://codeload.github.com/mx-space/core/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mx-space%2Fcore/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31995206,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T20:23:30.271Z","status":"online","status_checked_at":"2026-04-19T02:00:07.110Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","ai-cms","ai-summary","ai-translation","blog-cms","content-workflow","creator-tools","headless-cms","llm","mongodb","nestjs","personal-blog","redis","self-hosted","typescript"],"created_at":"2024-09-24T13:13:31.147Z","updated_at":"2026-05-19T09:08:39.511Z","avatar_url":"https://github.com/mx-space.png","language":"TypeScript","funding_links":["https://github.com/sponsors/innei","https://afdian.com/@Innei"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./.github/branding/logo-icon.png\" alt=\"mx-space\" width=\"120\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eMX Space Core\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  AI-powered CMS Core for personal blogs, creator homepages \u0026 content websites.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/mx-space/core/releases\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/mx-space/core?style=flat-square\" alt=\"Release\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/mx-space/core/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/mx-space/core/ci.yml?style=flat-square\u0026label=CI\" alt=\"CI\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/mx-space/core/blob/master/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-AGPLv3%20%2B%20MIT-blue?style=flat-square\" alt=\"License\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://nodejs.org\"\u003e\u003cimg src=\"https://img.shields.io/badge/node-%3E%3D22-brightgreen?style=flat-square\" alt=\"Node.js\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://hub.docker.com/r/innei/mx-server\"\u003e\u003cimg src=\"https://img.shields.io/docker/pulls/innei/mx-server?style=flat-square\" alt=\"Docker Pulls\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://t.me/+lRRxARqVZC1mYTc9\"\u003e\u003cimg src=\"https://img.shields.io/badge/Telegram-Join-26A5E4?style=flat-square\u0026logo=telegram\u0026logoColor=white\" alt=\"Telegram\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## Overview\n\nMX Space Core is a headless CMS server built with **NestJS**, **PostgreSQL**, and **Redis**. Beyond standard blog features (posts, pages, notes, comments, categories, feeds, search), it ships with a full AI content workflow — summary generation, multi-language translation, comment moderation, and writing assistance — powered by pluggable LLM providers.\n\n### Key Features\n\n| Category | Capabilities |\n|----------|-------------|\n| **Content Management** | Posts, notes, pages, drafts, categories, topics, comments, snippets, projects, friend links, subscriptions |\n| **AI Workflow** | Summary generation, multi-language translation, comment moderation, writing assistance, streaming responses |\n| **LLM Providers** | OpenAI, OpenAI-compatible, Anthropic, OpenRouter |\n| **Real-time** | WebSocket via Socket.IO with Redis adapter for multi-instance broadcast |\n| **Distribution** | RSS/Atom feeds, sitemap, local search, aggregate API |\n| **Auth** | JWT sessions, passkeys, OAuth, API keys (via better-auth) |\n| **Deployment** | Docker (multi-arch), PM2, standalone binary |\n\n## Tech Stack\n\n- **Runtime**: Node.js \u003e= 22 + TypeScript 5.9\n- **Framework**: NestJS 11 + Fastify\n- **Database**: PostgreSQL 16 (Drizzle ORM)\n- **Cache**: Redis (ioredis)\n- **Validation**: Zod 4\n- **WebSocket**: Socket.IO + Redis Emitter\n- **AI**: OpenAI SDK, Anthropic SDK\n- **Editor**: Lexical (via @haklex/rich-headless)\n- **Auth**: better-auth (session, passkey, API key)\n- **Testing**: Vitest + PostgreSQL testcontainers / Redis memory server\n\n## Monorepo Structure\n\n```\nmx-core/\n├── apps/\n│   └── core/                 # Main server application (NestJS)\n├── packages/\n│   ├── api-client/           # @mx-space/api-client — typed SDK for frontend \u0026 third-party clients\n│   ├── cli/                  # @mx-space/cli (mxs) — owner-side CLI for content + config\n│   ├── db-schema/            # @mx-space/db-schema — shared Drizzle schema + Snowflake utilities (private)\n│   ├── mongo-pg-cli/         # @mx-space/mongo-pg-cli — one-shot v11→v12 (MongoDB→PostgreSQL) data migration\n│   └── webhook/              # @mx-space/webhook — signature-verified webhook handler SDK\n├── docker-compose.yml        # Development stack (PostgreSQL + Redis + mx-migrate)\n├── dockerfile                # Multi-stage production build\n└── docker-compose.server.yml # Production deployment template\n```\n\n### Core Architecture (`apps/core/src/`)\n\n```\nsrc/\n├── modules/          # 45 business modules\n│   ├── ai/           #   AI summary, translation, insights, writer, agent, task queue\n│   ├── auth/         #   Better Auth: session, OAuth, passkey, API key\n│   ├── post/         #   Blog posts\n│   ├── note/         #   Short notes with topic support\n│   ├── comment/      #   Nested comments + AI moderation + reader image upload\n│   ├── configs/      #   Runtime configuration\n│   ├── enrichment/   #   URL extraction, screenshot pipeline\n│   ├── reader/       #   Reader identity / image quotas\n│   ├── webhook/      #   Event dispatch to external services\n│   ├── serverless/   #   User-defined serverless functions\n│   └── ...           #   page, draft, category, topic, feed, search, owner, etc.\n├── processors/       # Infrastructure services\n│   ├── database/     #   PostgreSQL connection + repository registry + BaseRepository\n│   ├── redis/        #   Cache, pub/sub, emitter\n│   ├── gateway/      #   WebSocket (admin, web, shared namespaces)\n│   ├── task-queue/   #   Distributed job queue (Redis + Lua)\n│   └── helper/       #   Email, image, JWT, Lexical, URL builder, etc.\n├── database/         # Drizzle ORM\n│   ├── schema/       #   Table definitions\n│   └── migrations/   #   SQL migration files (release-phase, never run on boot)\n├── common/           # Guards, interceptors, decorators, filters, pipes\n├── constants/        # Business events, cache keys, error codes\n├── transformers/     # Response transformation (snake_case, pagination)\n└── utils/            # Utility modules\n```\n\n\u003e Historical MongoDB → PostgreSQL data migration lives in [`packages/mongo-pg-cli`](./packages/mongo-pg-cli). Forward schema migrations live in `apps/core/src/database/migrations/` and run as a one-shot release-phase step (see the [release-phase migration design](./docs/superpowers/specs/2026-05-05-database-migration-release-phase-design.md)).\n\n## Quick Start\n\n### Prerequisites\n\n| Dependency | Version |\n|-----------|---------|\n| Node.js | \u003e= 22 |\n| pnpm | Latest (via Corepack) |\n| PostgreSQL | 16+ |\n| Redis | 7.x |\n\n### Local Development\n\n```bash\n# Enable Corepack for pnpm\ncorepack enable\n\n# Install dependencies\npnpm install\n\n# Start PostgreSQL + Redis (via Docker)\ndocker compose up -d postgres redis\n\n# Start dev server (port 2333)\npnpm dev\n```\n\nThe API is available at `http://localhost:2333`. In development mode, routes have no `/api/v2` prefix.\n\n### Docker Deployment\n\nThe fastest way to get a production instance running:\n\n```bash\n# Clone and enter the project\ngit clone https://github.com/mx-space/core.git \u0026\u0026 cd core\n\n# Edit environment variables\ncp docker-compose.server.yml docker-compose.prod.yml\n# Edit docker-compose.prod.yml — set JWT_SECRET, ALLOWED_ORIGINS, etc.\n\n# Start all services\ndocker compose -f docker-compose.prod.yml up -d\n```\n\nOr use the prebuilt image directly:\n\n```bash\ndocker pull innei/mx-server:latest\n```\n\nThe image supports `linux/amd64` and `linux/arm64`.\n\n## Available Commands\n\nRun from the repository root:\n\n| Command | Description |\n|---------|-------------|\n| `pnpm dev` | Start development server (watch mode) |\n| `pnpm build` | Build the core application |\n| `pnpm bundle` | Create production bundle (tsdown) |\n| `pnpm test` | Run test suite (Vitest) |\n| `pnpm lint` | Run ESLint with auto-fix |\n| `pnpm typecheck` | TypeScript type checking |\n| `pnpm format` | Format code with Prettier |\n\n### Running Tests\n\n```bash\n# Run all tests\npnpm test\n\n# Run a specific test file\npnpm test -- test/src/modules/user/user.service.spec.ts\n\n# Run tests matching a pattern\npnpm test -- --testNamePattern=\"should create user\"\n\n# Watch mode\npnpm -C apps/core run test:watch\n```\n\n## Environment Variables\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `JWT_SECRET` | Secret for JWT signing | Required |\n| `ALLOWED_ORIGINS` | CORS allowed origins (comma-separated) | — |\n| `PG_URL` | Full PostgreSQL connection string | — |\n| `PG_HOST` | PostgreSQL host | `127.0.0.1` |\n| `PG_PORT` | PostgreSQL port | `5432` |\n| `PG_USER` | PostgreSQL user | `mx` |\n| `PG_PASSWORD` | PostgreSQL password | `mx` |\n| `PG_DATABASE` | PostgreSQL database name | `mx_core` |\n| `PG_MAX_POOL_SIZE` | PostgreSQL connection pool size | `20` |\n| `PG_SSL` | Enable PostgreSQL SSL | `false` |\n| `REDIS_HOST` | Redis host | `localhost` |\n| `REDIS_PORT` | Redis port | `6379` |\n| `REDIS_PASSWORD` | Redis password | — |\n| `SNOWFLAKE_WORKER_ID` | Snowflake ID worker ID (0–1023) | Required |\n| `ENCRYPT_ENABLE` | Enable field encryption | `false` |\n| `ENCRYPT_KEY` | 64-char hex encryption key | — |\n| `THROTTLE_TTL` | Rate limit window (seconds) | `10` |\n| `THROTTLE_LIMIT` | Max requests per window | `100` |\n| `PORT` | Server port | `2333` |\n| `TZ` | Timezone | `Asia/Shanghai` |\n| `DISABLE_CACHE` | Disable Redis caching | `false` |\n\nConfiguration can also be provided via CLI arguments or YAML files. See `apps/core/src/app.config.ts` for the full config schema.\n\n## API Response Format\n\nAll responses are automatically transformed by interceptors:\n\n- **Array** → `{ data: [...] }`\n- **Object** → returned as-is\n- **Paginated** (via `@Paginator`) → `{ data: [...], pagination: {...} }`\n- **Bypass** (via `@Bypass`) → raw response\n\nAll response keys are converted to **snake_case** (e.g., `createdAt` → `created_at`).\n\n## Upgrading\n\n### v11 → v12\n\nv12 migrates the database from MongoDB to PostgreSQL. This is a hard cutover: all data must be migrated through the provided CLI before starting the new version. See [Upgrading to v12](./docs/migrations/v12.md).\n\n### v10 → v11\n\nv11 refactors the Aggregate API: `categories` and `pageMeta` are removed from `GET /aggregate`; a new `GET /aggregate/site` endpoint is added for lightweight site metadata. See [Upgrading to v11](./docs/migrations/v11.md).\n\n### v9 → v10\n\nv10 includes a breaking auth system refactor. See [Upgrading to v10](./docs/migrations/v10.md).\n\n## Related Projects\n\n| Project | Description |\n|---------|-------------|\n| [Yohaku](https://github.com/Innei/Yohaku) | Next.js frontend |\n| [mx-admin](https://github.com/mx-space/mx-admin) | Vue 3 admin dashboard |\n| [@mx-space/api-client](./packages/api-client) | TypeScript API client SDK |\n| [@mx-space/cli](./packages/cli) | `mxs` CLI for posts/notes/pages/config (OIDC device auth) |\n| [@mx-space/mongo-pg-cli](./packages/mongo-pg-cli) | One-shot MongoDB → PostgreSQL migration for v11 → v12 |\n| [@mx-space/webhook](./packages/webhook) | Webhook handler SDK (signature-verified) |\n| [@haklex/rich-headless](https://github.com/innei/haklex) | Lexical editor (server-side) |\n\n## License\n\n- **`apps/`** — [AGPLv3 with Additional Terms](./ADDITIONAL_TERMS.md)\n- **Everything else** — [MIT](./LICENSE)\n\nSee [LICENSE](./LICENSE) for full details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmx-space%2Fcore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmx-space%2Fcore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmx-space%2Fcore/lists"}