Open-source project
appwrite/sdk-generator avatar
appwrite/sdk-generator

Appwrite SDK Generator: one OpenAPI model, many client and server SDKs

Generating SDKs for multiple programming languages and platforms ⚙️

329 stars210 forksTwigMIT

At a glance

What is it?
A PHP library that turns OpenAPI 2.0, 3.0 and 3.1 documents into SDK codebases through Twig templates. It fits teams that maintain a spec and want generated clients in several languages at once, not teams looking for a hosted generator.
Who is it for?
Adopt it if you already maintain an OpenAPI document and need several language SDKs kept in step, and if a PHP and Twig toolchain is acceptable in your build. Do not adopt it for a single language, or if you need a hosted generator with a dashboard and no local runtime.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Twig, according to GitHub's language statistics.

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

DEEP OPEN-SOURCE ANALYSIS

What Appwrite SDK Generator is for

Maintaining SDKs by hand across a dozen languages is mostly duplication. A method signature changes in the API, and someone has to update the same call in TypeScript, Dart, Kotlin, Go and Rust, then keep the packaging metadata for each ecosystem in sync. The Appwrite SDK Generator takes the other route: the API description is the source of truth, and the SDK code is rendered from it. The README describes it as a PHP library for auto-generating SDK libraries for multiple languages and platforms, with predefined language settings expressed as Twig templates. The audience is therefore narrow and specific. It is for teams that already publish a machine-readable API description and want generated clients to follow it. It is not a tool for writing an API description for you, and it is not a runtime library that your application imports. The repository is not archived, and the last push was on 2026-08-28, the same day as the 4.7.4 release.

The OpenAPI-to-Twig rendering pipeline

Three pieces do the work. Utopia OpenAPI parses OpenAPI 2.0, 3.0 and 3.1 documents into one canonical model, so the templates do not each need to understand three input dialects. Language classes such as Appwrite\SDK\Language\PHP hold per-language and per-platform options. The SDK class ties a language instance to a parsed specification and writes the rendered result to a target directory. Templates under templates/ supply the actual code shape for each language, which is why the project's primary language is listed as Twig. The README states that both the openapi3 and swagger2 formats produce identical SDKs, so choosing a format argument changes parsing, not output. One detail worth noticing: the generator also handles artifacts that have no API operations at all. The README shows constructing a minimal canonical specification with an empty paths array, then passing it to an SDK instance with the Skills language. That is a narrow but real use of the same pipeline for files that are not conventional clients.

Installing with Composer and generating your first SDK

Installation is Composer-based. The README gives a direct command and a Docker equivalent for both UNIX and Windows shells. The Docker form mounts the working directory at /app, so the vendor directory lands in your checkout rather than inside the container.

bash
docker run --rm --interactive --tty --volume "$(pwd)":/app composer install --ignore-platform-reqs

Once dependencies are in place, the repository ships example.php as the entry point for generation. Run it with no arguments and it generates every target using the default console platform spec. Passing a target narrows that to one SDK, and a platform and format can follow.

bash
php example.php web client
php example.php node server

According to the README, the platform argument accepts console, client or server and defaults to console, while the format argument accepts openapi3 or swagger2 and defaults to openapi3. Output goes to a directory under examples/ named after the target, so a run of php example.php node server should leave generated Node.js code in examples/node/. If you write your own driver instead of using example.php, the pattern is to require vendor/autoload.php, parse a spec with Parser::parse(), construct a language instance, and hand both to SDK. Note that the README's PHP snippet is truncated mid-call, so the full option list for a language class has to come from the source under src/ rather than from the README.

Target coverage and the version floors it implies

The README lists client targets for Web, Flutter, Apple, Android and React Native, and server targets for Node.js, PHP, Python, Ruby, Dart, Go, Swift, .NET, Kotlin and Rust. Each row carries a supported version and a package manager, which is the part that actually constrains adoption. The floors are not uniform and some are aggressive: PHP requires 8.2 or later, Rust 1.83 or later, Go is listed at 1.26.5, and Dart appears twice with different ranges depending on whether it is the Flutter client (Dart >=3.7 <4) or the server SDK (Dart >=2.17 <4). Node.js appears with a build requirement of 18 or later for the Web client and Node.js 20 in CI for the server SDK. If your organization pins older toolchains, that table decides whether a target is usable before any code is generated. The README also lists several input formats as not ready: RAML 1.0 and 0.8, Postman 2.0 and 1.0, and API Blueprint 1A. Those entries are in the supported-specs list with a not-ready marker, so they should be read as roadmap rather than capability.

Enums, identifier naming and where generated code gets awkward

Enum handling shows the generator's limits clearly. Wire values are converted into identifiers per language, and when a value cannot form a valid identifier the generator falls back to a deterministic positional name such as Value1. That keeps generation from failing, but it also means the generated constant carries no meaning. The documented escape hatch is to describe the enum as titled oneOf branches, which lets you attach a semantic name to each value. The README gives a ProvinceType example with Khmer script values, which is exactly the case where automatic naming breaks down. Two other constraints are worth weighing. Twig linting runs through djLint with formatting disabled, and pyproject.toml states the reason in a comment: formatting breaks code generation syntax. Only linting is used, and the configuration ignores a long list of rules because they fire falsely on generated-language constructs such as Rust generics and TypeScript generics. That ignore list is a maintenance surface in itself. The second constraint is that the project is a PHP library with a Twig template layer. Anyone changing generated output has to work in both PHP and Twig, and the templates are the part most likely to need edits when a target language changes.

How it differs from Stainless and Fern

The related searches around this project include Stainless and Fern, and the comparison is fair because all three generate SDKs from API descriptions. The difference is in packaging and control. Stainless and Fern are hosted services: you point them at a spec and they manage the generation pipeline and, in Fern's case, the generated package publishing. Appwrite SDK Generator runs locally as a PHP library with Composer dependencies, and the language definitions are Twig templates in the repository that you can read and edit. That is the trade. You get full control over the emitted code and no external service in your release path, and you take on the toolchain, the template maintenance and the CI wiring yourself. For a team that already runs PHP in CI, that cost is small. For a team that does not, adding a PHP runtime plus Composer plus uv for the Twig linter is real overhead for a build step. The other difference is scope: this generator is built around Appwrite's own specification layout, and the README's primary example fetches a spec from the appwrite/specs repository. Using it on an unrelated API is supported by the OpenAPI parsing layer, but the templates were written against Appwrite's API shape.

Licence and the cost of keeping templates current

The repository is MIT licensed, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained. That is the whole of the licence implication here; the terms are in LICENSE.md and anything beyond reading them is a question for your own counsel. The upgrade cost is the more practical concern. Generated output is only as good as the templates, and the templates have to track the target languages: Dart and Flutter version ranges, Node.js CI versions, Rust and Go releases. The release history shows this in miniature, with 4.7.2, 4.7.3 and 4.7.4 all landing on 2026-08-27 and 2026-08-28. Frequent patch releases are normal for a generator whose inputs move. If you fork the templates to customize output, you inherit the job of rebasing those forks on each release, and the diff surface is the whole templates/ tree. Budget for that before adopting, not after.

Editorial conclusion

Adopt it if you already maintain an OpenAPI document and need several language SDKs kept in step, and if a PHP and Twig toolchain is acceptable in your build. Do not adopt it for a single language, or if you need a hosted generator with a dashboard and no local runtime. Before committing, verify three things: that your spec parses through Utopia OpenAPI, that the target you need appears in the README's target tables with a supported version you can build against, and that the generated output in examples/ matches the coding standards your project enforces.

Frequently asked questions

What is the Appwrite SDK Generator?

It is a PHP library that auto-generates SDK libraries for multiple languages and platforms, using predefined language settings written as Twig templates. Utopia OpenAPI parses OpenAPI 2.0, 3.0 and 3.1 documents into one canonical model, and the generator renders services, methods, models, enums and union types from it.

Is there an alternative to the Stainless SDK generator?

Yes. Fern and Stainless are hosted generators, while Appwrite SDK Generator runs locally as a PHP library whose language definitions are Twig templates in the repository. The trade is control over the emitted code and no external service in the release path, against maintaining the PHP and Twig toolchain yourself.

How can I create my own SDK with Appwrite SDK Generator?

Install dependencies with Composer, then run example.php with a target and optional platform and format, for example php example.php node server. The README states the platform defaults to console and the format defaults to openapi3, and output is written under examples/ named after the target.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
For maintainers

Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/appwrite-sdk-generator.svg)](https://hysenlabs.com/projects/appwrite-sdk-generator)
Community notes

Community notes