{"id":17920,"library":"remix-middleware","title":"Remix Middleware","description":"remix-middleware provides an Express-like middleware stack for Remix's `loader` and `action` functions, allowing developers to centralize cross-cutting concerns such as authentication, logging, and response manipulation. Currently at version `0.1.1`, this library is still considered experimental, indicating that its API may evolve rapidly. It differentiates itself by deeply integrating with Remix's server-side data functions and offering specialized middleware for common Remix patterns, including streamlined integration with `remix-auth`. While there isn't a fixed release cadence, development appears active, with several minor releases building out core features and addressing early architectural concerns, particularly around preventing server-only code from being bundled for the browser.","status":"active","version":"0.1.1","language":"javascript","source_language":"en","source_url":"https://github.com/neurosnap/remix-middleware","tags":["javascript","typescript"],"install":[{"cmd":"npm install remix-middleware","lang":"bash","label":"npm"},{"cmd":"yarn add remix-middleware","lang":"bash","label":"yarn"},{"cmd":"pnpm add remix-middleware","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Required for using the `isAuthenticated` and `userData` middleware functions, which streamline authentication flows.","package":"remix-auth","optional":true}],"imports":[{"note":"Primarily designed for ESM environments, typical in Remix projects. While CJS might work with transpilation, direct `require` is generally not recommended.","wrong":"const { createMiddleware } = require('remix-middleware');","symbol":"createMiddleware","correct":"import { createMiddleware } from 'remix-middleware';"},{"note":"Used to create authentication middleware, often with `remix-auth`'s `Authenticator` instance. Requires explicit import.","symbol":"isAuthenticated","correct":"import { isAuthenticated } from 'remix-middleware';"},{"note":"This is a TypeScript type for augmenting the middleware context with authentication data. It should be imported as a type, not a value.","wrong":"import { AuthCtx } from 'remix-middleware';","symbol":"AuthCtx","correct":"import type { AuthCtx } from 'remix-middleware';"}],"quickstart":{"code":"import { createMiddleware, isAuthenticated } from 'remix-middleware';\nimport type { ActionFunction, LoaderFunction } from '@remix-run/node'; // Or '@remix-run/react' depending on Remix version\n\n// For remix-auth integration (optional)\n// import { Authenticator } from 'remix-auth';\n// import { sessionStorage } from './session';\n// interface User { id: string; email: string; }\n// export const authenticator = new Authenticator<User>(sessionStorage);\n\n// ./app/middleware.ts\nexport const mdw = createMiddleware();\n\nmdw.use(async (ctx, next) => {\n  console.log('middleware activated for', ctx.request.url);\n  // ctx.request and ctx.response are available here\n  await next();\n  console.log('middleware completed for', ctx.request.url);\n});\n\n// Example using remix-auth middleware (uncomment if using remix-auth)\n// export const authed = createMiddleware<AuthCtx<User>>();\n// authed.use(isAuthenticated(authenticator, { failureRedirect: '/login' }));\n// authed.use(authed.routes());\n\nmdw.use(mdw.routes()); // Important: This must be called at the end of the middleware stack\n\n// ./app/routes/posts/index.tsx\n// Assuming you have a file at `~/middleware.ts`\n// import { mdw } from '~/middleware';\n// import { Form, useLoaderData } from '@remix-run/react';\n\ninterface Post { id: string; title: string; }\n\nexport const loader: LoaderFunction = (props) =>\n  mdw.run(props, (ctx) => {\n    // Simulate fetching data\n    ctx.response = [\n      { id: '1', title: 'My First Post' },\n      { id: '2', title: 'A Mixtape I Made Just For You' }\n    ];\n  });\n\nexport const action: ActionFunction = (props) =>\n  mdw.run(props, async (ctx) => {\n    const body = await ctx.request.formData();\n    const post = { id: '3', title: String(body.get('title')) };\n    ctx.response = post;\n  });\n\n// export default function Posts() {\n//   const posts = useLoaderData<Post[]>();\n//   return (\n//     <div>\n//       <h1>Posts</h1>\n//       <div>{posts.map((post) => (<div key={post.id}>{post.title}</div>))}\n//       </div>\n//       <Form method=\"post\"><p><label>Title: <input name=\"title\" type=\"text\" /></label></p><p><button type=\"submit\">Create</button></p></Form>\n//     </div>\n//   );\n// }","lang":"typescript","description":"This example demonstrates how to set up `remix-middleware` with a global logger and then apply it to a Remix `loader` and `action` to process requests and set responses, including basic form handling. It also outlines the optional setup for `remix-auth` integration."},"warnings":[{"fix":"Review the new API usage documented for `0.1.0` and ensure your middleware setup correctly uses the updated patterns to manage server-only code. Specifically, ensure `mdw.run` is used to wrap your loader/action logic.","message":"Version `0.1.0` introduced a significant change to prevent server-side code from being erroneously included in the browser bundle. This involved a new API, meaning direct upgrades from `0.0.x` might require updating how middleware is defined and executed to avoid bundling issues.","severity":"breaking","affected_versions":">=0.1.0"},{"fix":"Monitor GitHub releases and the project's README for updates. Consider pinning to a specific patch version if stability is critical, and be prepared for potential refactoring when upgrading.","message":"The package is still marked as 'experimental' (first released as `0.0.1` experimental). This implies that the API surface may not be stable and could change in future minor or patch releases, potentially introducing breaking changes without a major version bump.","severity":"gotcha","affected_versions":">=0.0.1"},{"fix":"Ensure that your terminal middleware function (the one passed to `mdw.run`) or one of the preceding middleware in the stack explicitly sets `ctx.response = yourData` or `ctx.response = new Response(...)`.","message":"For middleware to correctly set the response, you must assign the return value to `ctx.response`. If `ctx.response` is not set by any middleware or the final handler, the Remix `loader` or `action` will not return a valid response, leading to errors.","severity":"gotcha","affected_versions":">=0.0.1"},{"fix":"Declare your middleware creator like `export const authed = createMiddleware<AuthCtx<User>>();` where `User` is your authenticated user type.","message":"When integrating with `remix-auth`, ensure you properly type your `createMiddleware` call with `AuthCtx<UserType>` to gain correct TypeScript inference for `ctx.user`. Forgetting this will result in `ctx.user` being typed as `unknown` or `undefined`.","severity":"gotcha","affected_versions":">=0.1.1"}],"env_vars":null,"last_verified":"2026-04-23T00:00:00.000Z","next_check":"2026-07-22T00:00:00.000Z","problems":[{"fix":"Ensure your project, especially test setups or unusual build configurations, is correctly configured for ESM. Check `tsconfig.json` for `module` and `moduleResolution` settings (e.g., `\"module\": \"esnext\", \"moduleResolution\": \"bundler\"` for newer Node/Remix projects) and your `package.json` `type` field (set to `\"module\"`).","cause":"This error typically occurs in environments that struggle with ESM imports, often when a build system or test runner is misconfigured to treat ESM as CommonJS, or vice-versa.","error":"TypeError: (0 , remix_middleware__WEBPACK_IMPORTED_MODULE_X__.createMiddleware) is not a function"},{"fix":"Verify that the final function passed to `mdw.run(props, (ctx) => { /* ... */ })` explicitly assigns `ctx.response = yourData` or `ctx.response = new Response(...)`. The `mdw.response` helper can simplify this for simple JSON data.","cause":"The `mdw.run` function executes your middleware stack, and the final handler in the stack (or a preceding middleware) must set `ctx.response`. If this is missed, Remix receives no return value.","error":"Error: You did not return a value or a Response from your loader/action. This is a common issue when using external tools or incorrectly wrapping the `mdw.run` call."},{"fix":"When creating your middleware instance that uses `isAuthenticated`, explicitly define its context type: `export const authed = createMiddleware<AuthCtx<User>>();` where `User` is your application's user type.","cause":"This TypeScript error occurs when using the `isAuthenticated` middleware for `remix-auth` but the `AuthCtx` type parameter has not been correctly applied to `createMiddleware`.","error":"Property 'user' does not exist on type 'RemixMiddlewareContext<unknown>'"}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}