CLI tool
webiny/webiny-js avatar
webiny/webiny-js

Webiny: a self-hosted CMS you extend in TypeScript on your own AWS account

Open-source, self-hosted CMS platform on AWS serverless (Lambda, DynamoDB, S3). TypeScript framework with multi-tenancy, lifecycle hooks, GraphQL API, and AI-assisted development via MCP server. Built for developers at large organizations.

8,037 stars675 forksTypeScriptNOASSERTION

At a glance

What is it?
Webiny is an open-source, self-hosted content platform that deploys into your AWS account as Lambda, DynamoDB, S3 and CloudFront resources provisioned by Pulumi. It is aimed at developers who want a CMS they extend with code rather than configure through a UI, and the cost of that choice is that you own the infrastructure.
Who is it for?
Adopt Webiny if you have AWS account ownership, a TypeScript team, and a requirement for tenant isolation or code-level extension points that a hosted CMS cannot give you. Do not adopt it if you want a vendor to run the database, if your team is not comfortable reading Pulumi stacks and CloudWatch, or if you need to be editing content the same afternoon.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem Webiny solves: content platforms that stop at configuration

Most CMS products give you a plugin API and a settings screen. When your requirement falls outside what the plugin API exposes, you either fork the product or work around it. Webiny's README frames the project as the opposite of that: an open-source content platform that is a TypeScript framework you extend with code, not a closed product you configure through a UI. The extension points listed are lifecycle hooks, dependency injection, GraphQL schema extensions, admin UI extension points, and infrastructure extensions. The audience is stated directly. The README says it is built for developers at large organizations, and describes production use by teams managing hundreds of millions of content records, petabytes of assets, and thousands of editors. Those are the vendor's own claims and I have not verified them. What matters for evaluation is the shape of the offer: you get the source, the infrastructure templates, and the type definitions, and you are expected to write code against them. If your team's instinct on hitting a wall is to open a support ticket, this is a mismatch. If your instinct is to open the extension folder, the design will feel familiar.

What actually runs in your AWS account after deploy

The architecture diagram in the README shows four core services inside your AWS account. Lambda runs the API and business logic. DynamoDB stores content. S3 holds assets. CloudFront serves them as a CDN. OpenSearch is listed as optional, for full-text search at scale, and VPC deployment with multi-AZ is also optional. Pulumi provisions all of it. The README states that the IaC templates are open-source and that you can modify Lambda memory, add CloudWatch alarms, change VPC configuration, and add custom AWS resources. The split of responsibility is explicit: you control the infrastructure, you do not manage servers, patching, scaling, or capacity planning. That is a real division of labour and it is the reason the project exists in this form. It also means the operational surface is AWS, not Webiny. When something is slow, the answer lives in a Lambda concurrency setting or a DynamoDB access pattern, and you need to be able to read those signals yourself. The optional OpenSearch dependency is worth noting for planning: the README presents it as the path to full-text search at scale, which implies the default DynamoDB-backed search has limits you will meet as content volume grows.

Multi-tenancy as a first-class data boundary

Multi-tenancy is listed as native tenant isolation covering data, users, assets, and permissions, from a single deployment. The README states one instance can host thousands of tenants, that tenants are created and managed programmatically through the GraphQL API, and that hierarchical structures are supported, with examples given as Root to Brand to Market, or Root to Client to Site. This is the feature that most distinguishes Webiny from a typical headless CMS, where multi-tenancy is usually bolted on through separate projects or a tenant field you filter on manually. Here the isolation is described as being at the data layer, which is a different guarantee from application-level filtering. If you are building a SaaS product that white-labels a CMS, or an agency running many client sites from one deployment, this is the part of the README to read closely and then verify against the actual GraphQL tenant APIs in the docs, because the README gives the shape of the capability rather than the schema. The hierarchical model is also a design commitment: it assumes your tenant relationships are tree-shaped. If your tenancy model is a graph, with content shared across branches, that assumption will need testing before you build on it.

Getting a project running: three commands and a config file

The README's Quick Start lists Node.js 22 or later, Yarn, and an AWS account with programmatic access as prerequisites. The commands are:

npx create-webiny-project my-project cd my-project yarn webiny deploy

The README states that the first deploy takes 5 to 15 minutes because of AWS provisioning, and that afterwards you get an admin panel URL where you create the first admin account. Local development uses two watch commands, yarn webiny watch admin for a React dev server on localhost:3001, and yarn webiny watch api for a local Lambda execution environment. Onboarding a new team member is described as cloning the repository, running yarn, and developing. Customization lives in an extensions folder and is registered in webiny.config.tsx. The README names four extension types, and gives a partial example file, extensions/NotifyOnPublish.ts, described as sending a Slack notification when content is published. That example is truncated in the supplied material, so I cannot quote the hook signature or confirm which lifecycle event it binds to. Treat the config filename and the extensions folder as confirmed, and the exact hook API as something to read in the docs before you plan work around it.

The MCP server and what type checking does for generated code

Webiny ships an MCP server and what the README calls AI skills, intended to give coding agents such as Claude Code, Cursor, and Kiro context about the platform's architecture, extension points, and patterns. The listed use cases are concrete: create content models with field types and validation, build lifecycle hooks, extend the GraphQL API with custom queries, scaffold admin UI extensions in React, wire integrations through lifecycle events, and set up multi-tenant configurations programmatically. The README's argument for why this works better here than on other platforms is worth taking seriously as an engineering claim rather than marketing. It says the framework is strongly typed with explicit extension points, so generated code either fits the type system or it does not compile, and there is no ambiguous plugin API for the model to guess at. That is a coherent position: TypeScript compilation is a cheap filter on plausible-looking nonsense. It is not a correctness guarantee. Code can type-check and still be wrong about tenant scoping, permission checks, or which lifecycle event fires when. The README's setup instructions for the MCP server are deliberately thin, stating only that it runs locally inside your project and pointing to tool-specific instructions in the docs. Budget time for that step; it is not a one-liner in the material provided.

Where Webiny is the wrong tool

The clearest limitation is the one the README states as a feature: everything runs in your AWS account. That means the AWS account is a prerequisite, not an option, and the deployment model is tied to AWS serverless services specifically. If your organization runs on another cloud, or has a policy against Lambda-based workloads, or cannot grant a developer programmatic access to provision DynamoDB tables and CloudFront distributions, Webiny does not have a path for you in the material provided. The second limitation is the extension model itself. A framework that expects you to write lifecycle hooks and GraphQL resolvers is not a tool a marketing team can adopt without engineers. The README's own positioning, built for developers at large organizations, is a filter as much as a description. The third is operational maturity. Serverless removes patching and capacity planning but replaces them with distributed tracing across Lambda, DynamoDB, and CloudFront, plus Pulumi state to manage. The README does not describe a rollback story, a migration path between major versions, or how content schema changes are applied to existing data. Those gaps are not evidence the project handles them badly; they are simply not covered in the supplied material, and they are the questions to ask before a production commitment.

How this differs from Strapi and Payload

The nearest comparisons are Strapi and Payload, both open-source headless CMS options in TypeScript or JavaScript. The difference in approach is where the runtime lives. Strapi and Payload are typically deployed as a Node.js application against a database you choose, commonly PostgreSQL or MongoDB, and the CMS process is something you host and keep alive. Webiny decomposes the same functionality into Lambda functions, DynamoDB tables, and S3 buckets, and provisions them through Pulumi. That changes the operational profile: there is no long-running server to size or patch, and scaling is handled by the AWS services rather than by you adding instances. It also changes the debugging profile, since a request may cross several managed services. The extension models differ too. Strapi's plugin system and Payload's config-and-collections approach both expect you to work within their defined surfaces. Webiny's README describes dependency injection, GraphQL schema extension, and infrastructure extension, which reaches further down into the platform. If you want a CMS you can run on a single VPS with a Postgres database and understand end to end, Strapi or Payload will be less machinery. If you want tenant isolation and infrastructure you can modify in code, and you are already on AWS, Webiny's model is the one that matches.

Licence, upgrades and what to check before adopting

The README displays an MIT licence badge and links to a LICENSE file, but the repository metadata supplied to me reports the licence as NOASSERTION, which means the licence could not be determined automatically. That discrepancy is the first thing to resolve, by reading the actual LICENSE file in the repository rather than the badge. If the licence is split, with some packages under different terms, that matters for white-labelling, which the README lists as a use case. I am not giving legal advice; read the file and involve counsel if you plan to redistribute. On maintenance, the release cadence visible in the material is steady rather than rapid: v6.4.8, v6.4.9, and v6.4.10 landed across August and September 2026, with the last push to the next branch on 2026-09-10. That suggests active patch-level maintenance. It does not tell you the cost of a major version upgrade, and the README does not describe one. The upgrade cost you should actually budget for is not the npm version bump but the Pulumi infrastructure diff that accompanies it, since a framework release may change the AWS resources your stack declares. Run a deploy against a non-production AWS account and read the Pulumi preview before applying it to production. That is the concrete step that turns the README's claims into something you can evaluate.

Editorial conclusion

Adopt Webiny if you have AWS account ownership, a TypeScript team, and a requirement for tenant isolation or code-level extension points that a hosted CMS cannot give you. Do not adopt it if you want a vendor to run the database, if your team is not comfortable reading Pulumi stacks and CloudWatch, or if you need to be editing content the same afternoon. Before committing, verify three things: that the repository's actual license file matches the MIT badge in the README, that a first deploy into your own account completes inside the 5 to 15 minute window the README claims, and that the MCP server setup instructions for your specific AI tool are current in the docs rather than only in the README's summary.

Official sources

  1. Issues
  2. Project website
  3. README
  4. Releases
  5. webiny/webiny-js on GitHub
Community notes

Community notes