Skip to content

Packages vs Plugins Architecture

This document explains the distinction between packages and plugins in the Checkstack monorepo.

The Checkstack platform uses a two-tier architecture for code organization:

DirectoryPurposeExamples
core/Essential platform components that cannot be removedAuth, Catalog, Queue, Notifications
plugins/Replaceable providers and strategiesAuth providers (GitHub, LDAP), Queue backends (BullMQ)

Use this guide when deciding where to place new code:

  • ✅ The platform depends on this functionality to operate
  • ✅ It provides core infrastructure (auth, storage, messaging)
  • ✅ It defines shared contracts that other components depend on
  • ✅ It cannot be swapped for an alternative at runtime
  • ✅ Removing it would break the platform

Examples:

  • auth-*: Authentication is fundamental
  • catalog-*: Entity management is core to the platform
  • queue-*: Job queue abstraction layer
  • notification-*: Platform notifications
  • healthcheck-*: Platform health monitoring
  • theme-*: UI theming infrastructure
  • ✅ It’s a provider or strategy implementation
  • ✅ It can be swapped for an alternative
  • ✅ Multiple implementations can coexist
  • ✅ It’s optional - platform works without it (with alternatives)
  • ✅ It follows a plugin interface defined in a package

Examples:

  • auth-github-backend: One of many auth providers
  • auth-ldap-backend: Alternative auth provider
  • queue-bullmq-backend: One queue implementation
  • queue-memory-backend: Alternative queue implementation
  • healthcheck-http-backend: One health check strategy
TypeBackendCommon (Shared)Frontend
Packagecore/{name}-backendcore/{name}-commoncore/{name}-frontend
Pluginplugins/{name}-backendplugins/{name}-commonplugins/{name}-frontend
core/
├── backend/ # Core backend server
├── frontend/ # Core frontend app
├── backend-api/ # Backend plugin API
├── frontend-api/ # Frontend plugin API
├── common/ # Shared types/utilities
├── auth-backend/ # Core auth service
├── auth-common/ # Auth contracts
├── auth-frontend/ # Auth UI
├── catalog-*/ # Entity management
├── notification-*/ # Notifications
├── queue-*/ # Queue abstraction
├── healthcheck-*/ # Health monitoring
├── theme-*/ # UI theming
└── ...
plugins/
├── auth-github-backend/ # GitHub OAuth provider
├── auth-credential-backend/ # Username/password auth
├── auth-ldap-backend/ # LDAP auth provider
├── queue-bullmq-backend/ # BullMQ implementation
├── queue-bullmq-common/
├── queue-memory-backend/ # In-memory implementation
├── queue-memory-common/
└── healthcheck-http-backend/ # HTTP health strategy

Plugins implement interfaces defined in packages:

core/queue-api/src/types.ts
export interface QueuePlugin {
type: "queue";
createQueue(name: string, options: QueueOptions): Queue;
}
// plugins/queue-bullmq-backend/src/index.ts
export default createBackendPlugin({
metadata: pluginMetadata,
register(env) {
env.registerService(queuePluginRef, {
type: "queue",
createQueue: (name, options) => new BullMQQueue(name, options),
});
},
});

When using the CLI to create new code:

Terminal window
# Create a core package
bun run cli create package auth-oauth
# Create a replaceable plugin
bun run cli create plugin auth-okta-backend

The CLI will prompt for confirmation if creating in the “wrong” directory based on naming patterns.