{"id":15521549,"url":"https://github.com/sjc5/remix-easy-mode","last_synced_at":"2025-03-16T21:30:39.396Z","repository":{"id":151420278,"uuid":"623565288","full_name":"sjc5/remix-easy-mode","owner":"sjc5","description":"Simple, typesafe toolkit for developing highly interactive Remix apps. Inspired by TRPC.","archived":false,"fork":false,"pushed_at":"2023-11-01T22:36:22.000Z","size":716,"stargazers_count":77,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-04-26T14:06:02.670Z","etag":null,"topics":["actions","bouncer","forms","middleware","react","react-query","remix","trpc","typesafe","typescript","validations","zod"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/remix-easy-mode","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sjc5.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-04T16:14:53.000Z","updated_at":"2024-04-25T18:50:35.000Z","dependencies_parsed_at":"2023-04-09T20:51:51.414Z","dependency_job_id":"a256ba06-d0d0-47e6-98cb-51bdd35caada","html_url":"https://github.com/sjc5/remix-easy-mode","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sjc5%2Fremix-easy-mode","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sjc5%2Fremix-easy-mode/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sjc5%2Fremix-easy-mode/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sjc5%2Fremix-easy-mode/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sjc5","download_url":"https://codeload.github.com/sjc5/remix-easy-mode/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243830915,"owners_count":20354850,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["actions","bouncer","forms","middleware","react","react-query","remix","trpc","typesafe","typescript","validations","zod"],"created_at":"2024-10-02T10:35:24.986Z","updated_at":"2025-03-16T21:30:39.083Z","avatar_url":"https://github.com/sjc5.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Remix Easy Mode\n\nSimple, typesafe toolkit for developing highly interactive Remix apps\n\n## Features\n\n- 100% typesafe\n- Built on zod\n- Inspired by TRPC\n- Designed for building highly interactive apps\n- Bone-simple client form validations\n- Server-side input validations _a la_ TRPC\n- Session middleware via \"bouncer\" pattern\n- `onSuccess`, `onError`, and `onSettled` mutation callbacks _a la_ react-query\n- Input helpers are unstyled (and polymorphic, if you want to supply your own input components)\n- Optional custom serializers (_e.g._, `superjson`)\n- MIT licensed\n\n## Installation\n\n```bash\nnpm i remix-easy-mode zod\n```\n\n## Usage\n\n### Resource Route\n\n```tsx\nimport type { DataFunctionArgs } from \"@remix-run/server-runtime\"\nimport { dataFunctionHelper, useAction } from \"remix-easy-mode\"\nimport { z } from \"zod\"\n\nconst schema = z.object({\n  someUserInput: z.string(),\n})\n\n// this is like a TRPC procedure\nexport const action = (ctx: DataFunctionArgs) =\u003e {\n  return dataFunctionHelper({\n    ctx,\n    schema,\n    bouncer: async ({ ctx, csrfToken }) =\u003e {\n      // (1) throw error or (2) return user session\n    },\n    fn: async ({ input, session }) =\u003e console.log({ input, session }), // typesafe!,\n  })\n}\n\n// return hook from your resource route to use on client\nexport function useExample() {\n  return useAction\u003ctypeof action, typeof schema\u003e({\n    path: \"/resource-route\",\n    schema,\n    onSuccess: (res) =\u003e console.log(res), // typesafe!,\n  })\n}\n```\n\n### Client-side Form\n\n```tsx\nimport { InputHelper } from \"remix-easy-mode\"\nimport { useExample } from \"./resource-route\"\nimport { StyledInput } from \"./your-custom-input-component\"\n\nexport default function Index() {\n  const { Form, fields } = useExample()\n\n  return (\n    \u003cdiv\u003e\n      \u003cForm\n        csrfToken=\"whatever\" // optional\n        onSuccess={(res) =\u003e console.log(res)} // typesafe!\n      \u003e\n        \u003cInputHelper {...fields.someUserInput.props} component={StyledInput} /\u003e\n\n        \u003cbutton\u003eSubmit\u003c/button\u003e\n      \u003c/Form\u003e\n    \u003c/div\u003e\n  )\n}\n```\n\n## Example App\n\nTo run the example app:\n\n```bash\npnpm install\ncd packages/example\npnpm run dev\n```\n\nThen visit `localhost:3000`.\n\n## Peer Dependencies\n\n`react`, `@remix-run/react`, `@remix-run/server-runtime`, `zod`\n\n## Disclaimer\n\nThis is a work in progress. It's not yet battle-tested, and the pre-1.0.0 API will change without notice. If you want to use this in production, be careful, and set your dependency to a specific version.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsjc5%2Fremix-easy-mode","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsjc5%2Fremix-easy-mode","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsjc5%2Fremix-easy-mode/lists"}