A collection of open source libraries maintained by builder.group. Let's build together.
Package | Description | NPM Package |
---|---|---|
cli | Straightforward CLI to bundle Typescript libraries with presets, powered by Rollup and Esbuild | @blgc/cli |
config | Collection of ESLint, Vite, and Typescript configurations | @blgc/config |
elevenlabs-client | Typesafe and straightforward fetch client for interacting with the ElevenLabs API using feature-fetch | elevenlabs-client |
eprel-client | Typesafe and straightforward fetch client for interacting with the European Product Registry for Energy Labelling (EPREL) API using feature-fetch | eprel-client |
feature-fetch | Straightforward, typesafe, and feature-based fetch wrapper supporting OpenAPI types | feature-fetch |
feature-form | Straightforward, typesafe, and feature-based form library | feature-form |
feature-logger | Straightforward, typesafe, and feature-based logging library | feature-logger |
feature-react | ReactJs extension for the feature-state and feature-form library, providing hooks and features for ReactJs | feature-state-react |
feature-state | Straightforward, typesafe, and feature-based state management library for ReactJs | feature-state |
figma-connect | Straightforward and typesafe wrapper around the communication between the app/ui (iframe) and plugin (sandbox) part of a Figma Plugin | figma-connect |
google-webfonts-client | Typesafe and straightforward fetch client for interacting with the Google Web Fonts API using feature-fetch | google-webfonts-client |
openapi-ts-router | Thin wrapper around the router of web frameworks like Express and Hono, offering OpenAPI typesafety and seamless integration with validation libraries such as Valibot and Zod | openapi-ts-router |
utils | Straightforward, typesafe, and tree-shakable collection of utility functions | @blgc/utils |
validatenv | Type-safe, straightforward, and lightweight library for validating environment variables using existing validation libraries like Zod, Valibot, and Yup. | validatenv |
validation-adapter | Universal validation adapter that integrates various validation libraries like Zod, Valibot, and Yup | validation-adapter |
validation-adapters | Pre-made validation adapters for the validation-adapter library, including adapters for Zod and Valibot | validation-adapters |
widget-grid | Framework agnostic library for creating and manipulating widget grids | widget-grid |
xml-tokenizer | Straightforward and typesafe XML tokenizer that streams tokens through a callback mechanism | xml-tokenizer |
See
/examples
blgc
stands for BuiLder.Group Community, chosen because similar names like blg
, bldr
and bgc
were already taken.
Maintaining all libraries in a single repository keeps things simple and efficient. A monorepo allows for shared tooling, consistent versioning, and streamlined CI/CD workflows, while making cross-library changes easier. This approach simplifies collaboration and reduces overhead, ensuring all libraries remain in sync.
The only disadvantage is that it's harder to discover individual libraries via SEO since they're all part of one repo. However, the benefits far outweigh this limitation.
Development builds (pnpm build
):
- Includes TypeScript declaration maps (IDE navigation goes directly to source files instead of compiled definitions)
- Easier debugging (no code minification and optimizations)
Production builds (pnpm build:prod
):
- Smaller package size
- No development artifacts in published packages
- Code minification and optimizations enabled
- Prevents npm errors with declaration maps (e.g., EINVALIDTAGNAME in GitHub CLI)
To switch between modes:
- Development:
pnpm build
(includes declaration maps) - Production:
pnpm build:prod
(excludes declaration maps)
The @blgc/types
package provides crucial TypeScript type definitions to ensure full type safety for feature-based libraries. When listed as a devDependency
, these types are excluded from the final NPM package, resulting in broken type checks and missing autocompletions in projects consuming these libraries. By adding it as a dependency
, we ensure that the type definitions are bundled and accessible to downstream projects, maintaining a seamless developer experience.
Why do we use the "wrapper pattern" (withLogger(withStorage(withUndo(createState(0))))
) instead of a declarative API?
While declarative APIs like the following offer better developer experience (DX):
createState({
defaultValue: 0,
features: [withUndo(), withStorage(), withLogger()]
});
We currently use the "wrapper pattern" because it ensures better TypeScript type inference. Each wrapper function modifies the state's type in a specific sequence, which is harder to achieve reliably with a feature array.
We're actively exploring solutions to support both patterns, combining the type safety of the wrapper pattern with the simplicity of declarative APIs. Contributions and ideas are always welcome :)
This Medium post explains the key differences well.
In short, we use objects because they are more flexible and allow for the kind of extensibility we need. Achieving this level of extensibility with classes isn't feasible for our use case, so using objects was the better choice.