diff --git a/README.md b/README.md index f87d020fa..a2bf02557 100644 --- a/README.md +++ b/README.md @@ -21,28 +21,24 @@

Typesafe APIs Made Simple πŸͺ„

-**oRPC is a powerful combination of RPC and OpenAPI**, makes it easy to build APIs that are end-to-end type-safe and adhere to OpenAPI standards, ensuring a smooth and enjoyable developer experience. +**oRPC is a powerful combination of RPC and OpenAPI**, makes it easy to build APIs that are end-to-end type-safe and adhere to OpenAPI standards --- ## Highlights -- **End-to-End Type Safety πŸ”’**: Ensure complete type safety from inputs to outputs and errors, bridging server and client seamlessly. -- **First-Class OpenAPI πŸ“„**: Adheres to the OpenAPI standard out of the box, ensuring seamless integration and comprehensive API documentation. -- **Contract-First Development πŸ“œ**: (Optional) Define your API contract upfront and implement it with confidence. -- **Exceptional Developer Experience ✨**: Enjoy a streamlined workflow with robust typing and clear, in-code documentation. -- **Multi-Runtime Support 🌍**: Run your code seamlessly on Cloudflare, Deno, Bun, Node.js, and more. -- **Framework Integrations 🧩**: Supports Tanstack Query (React, Vue, Solid, Svelte), Pinia Colada, and more. -- **Server Actions ⚑️**: Fully compatible with React Server Actions on Next.js, TanStack Start, and more. -- **Standard Schema Support πŸ—‚οΈ**: Effortlessly work with Zod, Valibot, ArkType, and others right out of the box. -- **Fast & Lightweight πŸ’¨**: Built on native APIs across all runtimes – optimized for speed and efficiency. -- **Native Types πŸ“¦**: Enjoy built-in support for Date, File, Blob, BigInt, URL and more with no extra setup. -- **Lazy Router ⏱️**: Improve cold start times with our lazy routing feature. -- **SSE & Streaming πŸ“‘**: Provides SSE and streaming features – perfect for real-time notifications and AI-powered streaming responses. -- **Reusability πŸ”„**: Write once and reuse your code across multiple purposes effortlessly. -- **Extendability πŸ”Œ**: Easily enhance oRPC with plugins, middleware, and interceptors. -- **Reliability πŸ›‘οΈ**: Well-tested, fully TypeScript, production-ready, and MIT licensed for peace of mind. -- **Simplicity πŸ’‘**: Enjoy straightforward, clean code with no hidden magic. +- **πŸ”— End-to-End Type Safety**: Ensure type-safe inputs, outputs, and errors from client to server. +- **πŸ“˜ First-Class OpenAPI**: Built-in support that fully adheres to the OpenAPI standard. +- **πŸ“ Contract-First Development**: Optionally define your API contract before implementation. +- **βš™οΈ Framework Integrations**: Seamlessly integrate with TanStack Query (React, Vue, Solid, Svelte), Pinia Colada, and more. +- **πŸš€ Server Actions**: Fully compatible with React Server Actions on Next.js, TanStack Start, and other platforms. +- **πŸ”  Standard Schema Support**: Works out of the box with Zod, Valibot, ArkType, and other schema validators. +- **πŸ—ƒοΈ Native Types**: Supports native types like Date, File, Blob, BigInt, URL, and more. +- **⏱️ Lazy Router**: Enhance cold start times with our lazy routing feature. +- **πŸ“‘ SSE & Streaming**: Enjoy full type-safe support for SSE and streaming. +- **🌍 Multi-Runtime Support**: Fast and lightweight on Cloudflare, Deno, Bun, Node.js, and beyond. +- **πŸ”Œ Extendability**: Easily extend functionality with plugins, middleware, and interceptors. +- **πŸ›‘οΈ Reliability**: Well-tested, TypeScript-based, production-ready, and MIT licensed. ## Documentation diff --git a/apps/content/.vitepress/config.ts b/apps/content/.vitepress/config.ts index edba99f55..876f2117f 100644 --- a/apps/content/.vitepress/config.ts +++ b/apps/content/.vitepress/config.ts @@ -5,9 +5,8 @@ import llmstxt from 'vitepress-plugin-llms' export default defineConfig({ lang: 'en-US', - title: 'oRPC', - description: - 'oRPC makes it easy to build APIs that are end-to-end type-safe and adhere to OpenAPI standards, ensuring a smooth and enjoyable developer experience.', + title: 'oRPC - Typesafe APIs Made Simple πŸͺ„', + description: 'Easy to build APIs that are end-to-end type-safe and adhere to OpenAPI standards', lastUpdated: true, cleanUrls: true, markdown: { @@ -51,6 +50,7 @@ export default defineConfig({ { text: 'Docs', link: '/docs/getting-started', activeMatch: '/docs/(?!openapi/)' }, { text: 'OpenAPI', link: '/docs/openapi/getting-started', activeMatch: '/docs/openapi/' }, { text: 'Examples', link: '/examples/openai-streaming', activeMatch: '/examples/' }, + { text: 'Blog', link: '/blog/v1-announcement', activeMatch: '/blog/' }, { text: 'About', items: [ @@ -205,6 +205,9 @@ export default defineConfig({ '/examples/': [ { text: 'OpenAI Streaming', link: '/examples/openai-streaming' }, ], + '/blog/': [ + { text: 'V1 Announcement', link: '/blog/v1-announcement' }, + ], }, }, head: [ diff --git a/apps/content/blog/v1-announcement.md b/apps/content/blog/v1-announcement.md new file mode 100644 index 000000000..5b47a74b2 --- /dev/null +++ b/apps/content/blog/v1-announcement.md @@ -0,0 +1,134 @@ +--- +title: oRPC v1 Announcement - Typesafe APIs Made Simple πŸͺ„ +description: oRPC v1 is now available - tRPC, ts-rest, next-safe-action, and more alternatives! +titleTemplate: ':title' +--- + +# oRPC v1 Announcement - Typesafe APIs Made Simple πŸͺ„ + +oRPC is a thing help you build type-safe APIs with TypeScript. It's has own goal but can fairly be compared to other libraries like tRPC, ts-rest, next-safe-action, etc. or even serve as an alternative to them. + +## My Story + +My oRPC journey started in early 2024 after I lost my job. Finding a new one was hard, and I realized a standard job wasn't really what I wanted. I had always dreamed of being an "indie hacker" – someone who makes useful things for others. + +But looking back at my past work, I noticed something: I often spent more time complaining about the tools I used than focusing on what users needed. Maybe I cared too much about the tools themselves. + +Because I was often frustrated with existing tools, I changed my plan. I thought, "What if I make a tool for developers, one that fixes the problems I always had?" I hoped that if I built a tool I liked, other developers would like it too. + +That's how oRPC started. I began working hard on it around September 17, 2024. It wasn't easy; I had to rebuild oRPC three times to get the base right. After about three months, I shared an early version on Reddit ([see post](https://www.reddit.com/r/nextjs/comments/1h13upv/new_introducing_orpc_a_dropin_replacement_for/)). + +At first, oRPC was just a side project. Then, a turning point came when someone privately offered **$100** to support it. I was surprised and really motivated! A month after that, I decided to stop my other projects and work on oRPC full-time, even though I didn't have another job. My life became: code, eat, sleep, repeat. + +I had so many ideas for oRPC. I realized it would take all my focus and time, probably until the end of 2025, to make it happen. + +But !!! Today is a **big step** on that journey. I'm happy and proud to announce that the core of oRPC is now stable, and Version 1.0 is officially out! + +::: info +V1 means the public API is stable and ready for production use. +::: + +## The Idea behind oRPC + +oRPC philosophy is **powerful simplicity**. Define your API endpoints almost as easily as writing standard functions, yet automatically gain: + +- End-to-end type safety (includes **errors**) +- Server Action compatibility +- Full OpenAPI specification generation +- Contract-first workflow support +- Standard function call compatibility + +```ts +const getting = os + .use(dbProvider) + .use(requiredAuth) + .use(rateLimit) + .use(analytics) + .use(sentryMonitoring) + .use(retry({ times: 3 })) + .route({ method: 'GET', path: '/getting/{id}' }) + .input(z.object({ id: z.string() })) + .use(canGetting, input => input.id) + .errors({ + SOME_TYPE_SAFE_ERROR: { + data: z.object({ something: z.string() }) + } + }) + .handler(async ({ input, errors, context }) => { + // do something + }) + .actionable() // server action compatible + .callable() // regular function compatible +``` + +Beyond built-in features, oRPC [metadata](https://orpc.unnoq.com/docs/metadata) system allows for community-driven extensions and future possibilities. + +## Highlights + +- **πŸ”— End-to-End Type Safety**: Ensure type-safe inputs, outputs, and errors from client to server. +- **πŸ“˜ First-Class OpenAPI**: Built-in support that fully adheres to the OpenAPI standard. +- **πŸ“ Contract-First Development**: Optionally define your API contract before implementation. +- **βš™οΈ Framework Integrations**: Seamlessly integrate with TanStack Query (React, Vue, Solid, Svelte), Pinia Colada, and more. +- **πŸš€ Server Actions**: Fully compatible with React Server Actions on Next.js, TanStack Start, and other platforms. +- **πŸ”  Standard Schema Support**: Works out of the box with Zod, Valibot, ArkType, and other schema validators. +- **πŸ—ƒοΈ Native Types**: Supports native types like Date, File, Blob, BigInt, URL, and more. +- **⏱️ Lazy Router**: Enhance cold start times with our lazy routing feature. +- **πŸ“‘ SSE & Streaming**: Enjoy full type-safe support for SSE and streaming. +- **🌍 Multi-Runtime Support**: Fast and lightweight on Cloudflare, Deno, Bun, Node.js, and beyond. +- **πŸ”Œ Extendability**: Easily extend functionality with plugins, middleware, and interceptors. +- **πŸ›‘οΈ Reliability**: Well-tested, TypeScript-based, production-ready, and MIT licensed. + +## tRPC alternative + +I used tRPC extensively and really liked it. However, I needed OpenAPI support for my projects. Although I found `trpc-openapi` to add OpenAPI to tRPC, it didn't work with Edge runtimes and has since been deprecated. This was very frustrating, prompting me to look for alternatives. + +Also, setting up tRPC sometimes felt too complicated, especially for smaller projects like Cloudflare Durable Objects where I just needed a simple API. Another point is that tRPC mostly supports React Query. That was okay for me, but less helpful if you want to use Vue, Solid, or Svelte. + +I did some **simple** benchmarks between oRPC and tRPC, and results show (full report [here](https://github.com/unnoq/orpc-benchmarks)): + +- oRPC is **1,6 times typecheck faster** (5.9s vs 9.3s) +- oRPC is **2,8 times runtime faster** (295k reqs vs 104k reqs / 20 sec) +- oRPC is **1,26 times less max cpu usage** (102% vs 129%) +- oRPC is **2,6 times less max ram usage** (103MB vs 268MB) +- oRPC is **2,6 smaller in bundle size** ([32.5 kB](https://bundlejs.com/?q=%40orpc%2Fserver%2Cnode%3Ahttp%2C%40orpc%2Fclient%2C%40orpc%2Fclient%2Ffetch%2C%40orpc%2Fserver%2C%40orpc%2Fserver%2Fnode&treeshake=%5B*%5D%2C%5B*%5D%2C%5B*%5D%2C%5B*%5D%2C%5B*%5D%2C%5B*%5D&text=%22const+router+%3D+%7B%5Cn++ping%3A+os.handler%28%28%29+%3D%3E+%27pong%27%29%2C%5Cn%7D%5Cn%5Cnconst+handler+%3D+new+RPCHandler%28router%2C+%7B%5Cn++strictGetMethodPluginEnabled%3A+false%2C%5Cn%7D%29%5Cn%5Cnexport+const+server+%3D+createServer%28async+%28req%2C+res%29+%3D%3E+%7B%5Cn++const+%7B+matched+%7D+%3D+await+handler.handle%28req%2C+res%29%5Cn%5Cn++if+%28%21matched%29+%7B%5Cn++++res.statusCode+%3D+404%5Cn++++res.end%28%27Not+Found%27%29%5Cn++%7D%5Cn%7D%29%5Cn%5Cnconst+link+%3D+new+RPCLink%28%7B%5Cn++url%3A+%27https%3A%2F%2Fexample.com%27%2C%5Cn%7D%29%5Cn%5Cnexport+const+orpc%3A+RouterClient%3Ctypeof+router%3E+%3D+createORPCClient%28link%29%22) vs [84.5 kB](https://bundlejs.com/?q=%40trpc%2Fclient%2C%40trpc%2Fserver%2C%40trpc%2Fserver%2Fadapters%2Fstandalone%2Csuperjson&treeshake=%5B*%5D%2C%5B*%5D%2C%5B*%5D%2C%5B*%5D&share=MYewdgzgLgBLC8MCWYlQCoCUAKBhAdMAE4CmAhlCQBQDeAUDHEWZAGYhEC2JRAXDBACuABx4ArCOAA0dAL4BKOnVCRYZYcMwhBlIjERR8RbbtoMYwlAHN%2Bh4ceAkAJoNL4AjoJ4BPKlXn6AHwwAOTC4FYh8jIKSiQAHuFEsCrQAjwAbjz6MMTklAAS6OjYAMqZPGaMxjo8-OqaJjwyjHkUJLjglPFQ-jD0jNUkUK5g-bLmsjGKdAlJKeBpUETCwDltlFh4uAA2SCRgUAA8UN6iIKwwDVq1RIFVMHtgANYQ-ADa5owQwntQADIoZ4PQa5cBONBIcD8EDCIIwWH4U6ifTwRAhIQAIwgxCQwigULAIRaoKYXn4AAsoFBhKVBNjcfjCYCXiDSa4dvwQlSaW8APR8hJkTi-EiEECcYlfUnLFgQdhcOoCETiSRgEmghQawasMg7CAkSnU4Qs4EDUmMDlcnnCfmC%2BLC0XiyXa0Gytgcbh8ZWiIgSaTSxha6XBxgAXWmQA)) + +:::warning +Benchmark results can vary across environments and depend heavily on factors like your project's size, complexity, and setup. Many conditions can influence the outcome β€” so treat these numbers as a helpful reference, not a guarantee. +::: + +::: info +You can read more about comparion [here](/docs/comparison) +::: + +## ts-rest alternative + +After running into the OpenAPI issues with tRPC, I tried ts-rest. While it helped with OpenAPI, I soon found it was missing features I relied on from tRPC, like flexible middleware and easy handling of certain data types (like Dates or Files). After using it for some APIs, I felt it wasn't the complete solution I wanted. This frustration was a key reason I started building oRPC. + +::: info +You can read more about comparion [here](/docs/comparison) +::: + +## next-safe-action alternative + +I also experimented with `next-safe-action` to test server actions in Next.js, hoping they might be a good replacement for the tRPC style. However, I found they didn't quite fit my needs. I believe a dedicated RPC library like oRPC still provides a better developer experience for building APIs. + +## Sponsors + +In this long journey, I specially thank all my sponsors, they help me to keep going. + +- [Zuplo - Serverless API Gateway, designed for developers](https://zuplo.link/orpc) +- [ζ‘δΈŠγ•γ‚“](https://github.com/SanMurakami) +- [あわわわとーにゅ](https://github.com/u1-liquid) +- [motopods](https://github.com/motopods) +- [Maxie](https://github.com/MrMaxie) +- [Stijn Timmer](https://github.com/Stijn-Timmer) +- [Robbe95](https://github.com/Robbe95) +- And my first sponsor (private) to start my story + +If you're interesting in sponsoring oRPC, you can do it [here](https://github.com/sponsors/unnoq). + +

+ + + +

diff --git a/apps/content/docs/comparison.md b/apps/content/docs/comparison.md index 421c9691a..7dcc8a9c9 100644 --- a/apps/content/docs/comparison.md +++ b/apps/content/docs/comparison.md @@ -11,28 +11,28 @@ This comparison table helps you understand how oRPC differs from other popular T - 🟑 Lacks features, or requires third-party integrations - πŸ›‘ Not supported or not documented -| Feature | oRPC | tRPC | ts-rest | -| ---------------------------------------- | ---- | ---- | ------- | -| End-to-end Input/Output Typesafe | βœ… | βœ… | βœ… | -| End-to-end Errors Typesafe | βœ… | 🟑 | βœ… | -| End-to-end File/Blob Typesafe | βœ… | 🟑 | πŸ›‘ | -| End-to-end Streaming Typesafe | βœ… | βœ… | πŸ›‘ | -| Tanstack Query Integration (React) | βœ… | βœ… | 🟑 | -| Tanstack Query Integration (Vue) | βœ… | πŸ›‘ | 🟑 | -| Tanstack Query Integration (Solid) | βœ… | πŸ›‘ | 🟑 | -| Tanstack Query Integration (Svelte) | βœ… | πŸ›‘ | πŸ›‘ | -| Vue Pinia Colada Integration | βœ… | πŸ›‘ | πŸ›‘ | -| With Contract-First Approach | βœ… | πŸ›‘ | βœ… | -| Without Contract-First Approach | βœ… | βœ… | πŸ›‘ | -| OpenAPI Support | βœ… | 🟑 | 🟑 | -| Server Actions Support | βœ… | βœ… | πŸ›‘ | -| Lazy Router | βœ… | βœ… | πŸ›‘ | -| Native Types (Date, URL, Set, Maps, ...) | βœ… | βœ… | πŸ›‘ | -| Streaming response (SSE) | βœ… | βœ… | πŸ›‘ | -| Standard Schema | βœ… | βœ… | πŸ›‘ | -| Plugins-able (CORS, ...) | βœ… | βœ… | πŸ›‘ | -| Dedicated Zod Schemas | βœ… | N/A | πŸ›‘ | -| Use Native Modules on each runtime | βœ… | βœ… | 🟑 | -| Batch Request | βœ… | βœ… | πŸ›‘ | -| WebSockets | πŸ›‘ | βœ… | πŸ›‘ | -| Nest.js integration | πŸ›‘ | 🟑 | βœ… | +| Feature | oRPC docs | oRPC | tRPC | ts-rest | +| -------------------------------------------- | -------------------------------------------------------------------------------------------- | ---- | ---- | ------- | +| End-to-end Typesafe Input/Output | | βœ… | βœ… | βœ… | +| End-to-end Typesafe Errors | [1](/docs/client/error-handling), [2](/docs/error-handling#type%E2%80%90safe-error-handling) | βœ… | 🟑 | βœ… | +| End-to-end Typesafe File/Blob | [1](/docs/file-upload-download) | βœ… | 🟑 | πŸ›‘ | +| End-to-end Typesafe Streaming | [1](/docs/event-iterator) | βœ… | βœ… | πŸ›‘ | +| Tanstack Query Integration (React) | [1](/docs/tanstack-query/react) | βœ… | βœ… | 🟑 | +| Tanstack Query Integration (Vue) | [1](/docs/tanstack-query/vue) | βœ… | πŸ›‘ | 🟑 | +| Tanstack Query Integration (Solid) | [1](/docs/tanstack-query/solid) | βœ… | πŸ›‘ | 🟑 | +| Tanstack Query Integration (Svelte) | [1](/docs/tanstack-query/svelte) | βœ… | πŸ›‘ | πŸ›‘ | +| Vue Pinia Colada Integration | [1](/docs/pinia-colada) | βœ… | πŸ›‘ | πŸ›‘ | +| With Contract-First Approach | [1](/docs/contract-first/define-contract) | βœ… | πŸ›‘ | βœ… | +| Without Contract-First Approach | | βœ… | βœ… | πŸ›‘ | +| OpenAPI Support | [1](/docs/openapi/openapi-handler) | βœ… | 🟑 | 🟑 | +| OpenAPI Support for multiple schema | [1](/docs/openapi/openapi-handler) | βœ… | πŸ›‘ | πŸ›‘ | +| OpenAPI Bracket Notation Support | [1](/docs/openapi/bracket-notation) | βœ… | πŸ›‘ | πŸ›‘ | +| Server Actions Support | [1](/docs/server-action) | βœ… | βœ… | πŸ›‘ | +| Lazy Router | [1](/docs/router#lazy-router) | βœ… | βœ… | πŸ›‘ | +| Native Types (Date, URL, Set, Maps, ...) | [1](/docs/rpc-handler#supported-data-types) | βœ… | 🟑 | πŸ›‘ | +| Streaming response (SSE) | [1](/docs/event-iterator) | βœ… | βœ… | πŸ›‘ | +| Standard Schema (Zod, Valibot, ArkType, ...) | | βœ… | βœ… | πŸ›‘ | +| Built-in Plugins (CORS, CSRF, Retry, ...) | | βœ… | πŸ›‘ | πŸ›‘ | +| Batch Request/Response | [1](/docs/plugins/batch-request-response) | βœ… | βœ… | πŸ›‘ | +| WebSockets | (working) | πŸ›‘ | βœ… | πŸ›‘ | +| Nest.js integration | | πŸ›‘ | 🟑 | βœ… | diff --git a/apps/content/index.md b/apps/content/index.md index ab063644e..48cc0db94 100644 --- a/apps/content/index.md +++ b/apps/content/index.md @@ -1,13 +1,12 @@ --- title: oRPC - Typesafe APIs Made Simple πŸͺ„ +description: Easy to build APIs that are end-to-end type-safe and adhere to OpenAPI standards titleTemplate: ':title' -head: - - ['meta', { property: 'og:description', content: 'oRPC makes it easy to build APIs that are end-to-end type-safe and adhere to OpenAPI standards, ensuring a smooth and enjoyable developer experience.' }] layout: home hero: name: oRPC text: Typesafe APIs Made Simple πŸͺ„ - tagline: Easy to build APIs that are end-to-end type-safe and adhere to OpenAPI standards, ensuring a smooth and enjoyable developer experience. + tagline: Easy to build APIs that are end-to-end type-safe and adhere to OpenAPI standards image: light: /code-light.png dark: /code-dark.png @@ -20,54 +19,42 @@ hero: text: Playgrounds link: /docs/playgrounds features: - - icon: πŸ”’ + - icon: πŸ”— title: End-to-End Type Safety - details: Ensure complete type safety from inputs to outputs and errors, bridging server and client seamlessly. - - icon: πŸ“„ + details: Ensure type-safe inputs, outputs, and errors from client to server. + - icon: πŸ“˜ title: First-Class OpenAPI - details: Adheres to the OpenAPI standard out of the box, ensuring seamless integration and comprehensive API documentation. - - icon: πŸ“œ + details: Built-in support that fully adheres to the OpenAPI standard. + - icon: πŸ“ title: Contract-First Development - details: (Optional) Define your API contract upfront and implement it with confidence. - - icon: ✨ - title: Exceptional Developer Experience - details: Enjoy a streamlined workflow with robust typing and clear, in-code documentation. - - icon: 🌍 - title: Multi-Runtime Support - details: Run your code seamlessly on Cloudflare, Deno, Bun, Node.js, and more. - - icon: 🧩 + details: Optionally define your API contract before implementation. + - icon: βš™οΈ title: Framework Integrations - details: Supports Tanstack Query (React, Vue, Solid, Svelte), Pinia Colada, and more. - - icon: ⚑ + details: Seamlessly integrate with TanStack Query (React, Vue, Solid, Svelte), Pinia Colada, and more. + - icon: πŸš€ title: Server Actions - details: Fully compatible with React Server Actions on Next.js, TanStack Start, and more. - - icon: πŸ—‚οΈ + details: Fully compatible with React Server Actions on Next.js, TanStack Start, and other platforms. + - icon: πŸ”  title: Standard Schema Support - details: Effortlessly work with Zod, Valibot, ArkType, and others right out of the box. - - icon: πŸ’¨ - title: Fast & Lightweight - details: Built on native APIs across all runtimes – optimized for speed and efficiency. - - icon: πŸ“¦ + details: Works out of the box with Zod, Valibot, ArkType, and other schema validators. + - icon: πŸ—ƒοΈ title: Native Types - details: Enjoy built-in support for Date, File, Blob, BigInt, URL and more with no extra setup. + details: Supports native types like Date, File, Blob, BigInt, URL, and more. - icon: ⏱️ title: Lazy Router - details: Improve cold start times with our lazy routing feature. + details: Enhance cold start times with our lazy routing feature. - icon: πŸ“‘ title: SSE & Streaming - details: Provides SSE and streaming features – perfect for real-time notifications and AI-powered streaming responses. - - icon: πŸ”„ - title: Reusability - details: Write once and reuse your code across multiple purposes effortlessly. + details: Enjoy full type-safe support for SSE and streaming. + - icon: 🌍 + title: Multi-Runtime Support + details: Fast and lightweight on Cloudflare, Deno, Bun, Node.js, and beyond. - icon: πŸ”Œ title: Extendability - details: Easily enhance oRPC with plugins, middleware, and interceptors. + details: Easily extend functionality with plugins, middleware, and interceptors. - icon: πŸ›‘οΈ title: Reliability - details: Well-tested, fully TypeScript, production-ready, and MIT licensed for peace of mind. - - icon: πŸ’‘ - title: Simplicity - details: Enjoy straightforward, clean code with no hidden magic. + details: Well-tested, TypeScript-based, production-ready, and MIT licensed. ---