Skip to content

Plugins Overview ​

πŸ”Œ Plugins are modular extensions that add reusable features to your Nevr application.

Why Plugins? ​

The Problem: Features That Every App Needs ​

FeatureWithout PluginsWith Plugins
AuthenticationWrite 500+ lines of auth codeauth({ emailAndPassword: { enabled: true } })
TimestampsAdd createdAt/updatedAt to every entity manuallyOne-line plugin for all entities
Rate limitingBuild custom middlewarerateLimit({ max: 100 })
LoggingImplement hooks everywherePlugin auto-hooks all requests

🟒 Beginner Tip: Think of plugins as "drop-in features". You install them, configure them, and they just workβ€”without writing the underlying code.

What Plugins Can Add ​

CapabilityDescriptionExample
EntitiesNew database tables/modelsUser, Session, Account
EndpointsCustom API operations/auth/sign-in, /auth/sign-out
InterceptorsRequest/response processingAuthentication checks, logging
Entity HooksCRUD lifecycle callbacksbeforeCreate, afterDelete
ServicesInjectable utilitiesEmail service, Payment processor

Using Plugins ​

Add plugins to your defineConfig β€” they're picked up automatically by nevr():

typescript
// src/nevr.config.ts
import { defineConfig } from "nevr"
import { auth } from "nevr/plugins/auth"
import { timestamps } from "nevr/plugins/timestamps"
import { user } from "./entities/user.js"
import { post } from "./entities/post.js"

export const config = defineConfig({
  database: "sqlite",
  entities: [user, post],
  plugins: [
    // Official plugin with options
    auth({
      emailAndPassword: { enabled: true },
      socialProviders: {
        google: { clientId: "...", clientSecret: "..." },
        github: { clientId: "...", clientSecret: "..." },
      },
    }),

    // Official simple plugin
    timestamps(),

    // Your custom plugin
    myCustomPlugin({ apiKey: "..." }),
  ],
})

export default config
typescript
// src/server.ts β€” plugins loaded automatically from config
import { nevr } from "nevr"
import { prisma } from "nevr/drivers/prisma"
import { PrismaClient } from "@prisma/client"
import { config } from "./nevr.config.js"

const api = nevr({ ...config, driver: prisma(new PrismaClient()) })

🟑 Intermediate Tip: Plugins are applied in order. If plugin B depends on plugin A, make sure A comes first in the array.

Recommended project structure

For projects with custom plugins, keep them in a dedicated plugins/ folder:

Express / Hono:

src/
β”œβ”€β”€ entities/
β”‚   β”œβ”€β”€ user.ts
β”‚   β”œβ”€β”€ post.ts
β”‚   └── index.ts         # re-exports all entities
β”œβ”€β”€ plugins/
β”‚   β”œβ”€β”€ auth.ts          # auth plugin config
β”‚   β”œβ”€β”€ my-plugin.ts     # your custom plugin
β”‚   └── index.ts         # re-exports all plugins
β”œβ”€β”€ nevr.config.ts       # defineConfig β€” entities + plugins
└── server.ts            # nevr({ ...config, driver })

Next.js:

lib/
β”œβ”€β”€ entities/
β”‚   └── index.ts
β”œβ”€β”€ plugins/
β”‚   β”œβ”€β”€ auth.ts
β”‚   └── index.ts
β”œβ”€β”€ nevr.config.ts
└── nevr.ts
app/
└── api/
    └── [...nevr]/
        └── route.ts

This keeps plugin configuration separate and your nevr.config.ts clean:

typescript
import { defineConfig } from "nevr"
import * as entities from "./entities/index.js"
import { authPlugin, myPlugin } from "./plugins/index.js"

export default defineConfig({
  database: "sqlite",
  entities: Object.values(entities).filter(e => e && typeof e === "object"),
  plugins: [authPlugin, myPlugin],
})

Official Plugin Ecosystem ​

PluginPackageDescriptionStatus
Authnevr/plugins/authComplete authentication systemβœ… Ready
Timestampsnevr/plugins/timestampsAuto createdAt/updatedAtβœ… Ready
Paymentsnevr/plugins/paymentsStripe payment integrationβœ… Ready
Storagenevr/plugins/storageFile upload and managementβœ… Ready
AI-Gatewaynevr/plugins/ai-gatewayAI model integrationβœ… Ready
RAGnevr/plugins/ragRetrieval-Augmented Generationβœ… Ready

Creating Your Own Plugins ​

Quick Example 🟒 ​

typescript
import { createPlugin, endpoint } from "nevr"

const helloWorld = createPlugin({
  id: "hello",
  name: "Hello World",
  version: "1.0.0",
  
  lifecycle: {
    onInit: () => console.log("πŸ‘‹ Hello from Plugin!")
  },
  
  endpoints: {
    hello: endpoint("/hello", {
      method: "GET",
      handler: async () => ({ message: "Hello World!" }),
    }),
  },
})

Configurable Plugin 🟑 ​

typescript
interface Options {
  greeting: string
  shout?: boolean
}

const greetPlugin = createPlugin<Options>({
  id: "greet",
  name: "Greeting Plugin",
  version: "1.0.0",
  
  defaults: { shout: false },
  
  factory: (options) => ({
    endpoints: {
      greet: endpoint("/greet", {
        method: "GET",
        handler: async () => {
          const msg = options.greeting
          return { message: options.shout ? msg.toUpperCase() : msg }
        },
      }),
    },
  }),
})

// Usage in nevr.config.ts:
// plugins: [greetPlugin({ greeting: "Welcome!" })]

See Creating Plugins for the full guide.


Plugin API at a Glance ​

FunctionUse CaseLevel
createPlugin()Most plugins🟒 Recommended
createPlugin() with factoryConfigurable plugins

Next Steps ​

Released under the MIT License.