{"id":15551321,"url":"https://github.com/jameslnewell/rechannel","last_synced_at":"2026-02-13T03:01:56.202Z","repository":{"id":57349170,"uuid":"53831304","full_name":"jameslnewell/rechannel","owner":"jameslnewell","description":"Opinionated glue for creating web apps with `react` and `redux`.","archived":false,"fork":false,"pushed_at":"2017-03-16T20:11:32.000Z","size":37,"stargazers_count":0,"open_issues_count":6,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-08-09T14:53:09.461Z","etag":null,"topics":["boilerplate","react","react-router","redux","server-side-rendering","ssr"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jameslnewell.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-03-14T06:09:51.000Z","updated_at":"2017-02-14T01:49:46.000Z","dependencies_parsed_at":"2022-08-29T18:40:40.888Z","dependency_job_id":null,"html_url":"https://github.com/jameslnewell/rechannel","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jameslnewell/rechannel","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jameslnewell%2Frechannel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jameslnewell%2Frechannel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jameslnewell%2Frechannel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jameslnewell%2Frechannel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jameslnewell","download_url":"https://codeload.github.com/jameslnewell/rechannel/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jameslnewell%2Frechannel/sbom","scorecard":{"id":503968,"data":{"date":"2025-08-11","repo":{"name":"github.com/jameslnewell/rechannel","commit":"0b0e99d02872b5e49d405d515d5cfbcd940dc941"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.6,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Code-Review","score":0,"reason":"Found 1/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 1 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-19T22:49:07.880Z","repository_id":57349170,"created_at":"2025-08-19T22:49:07.880Z","updated_at":"2025-08-19T22:49:07.880Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274207174,"owners_count":25241370,"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","status":"online","status_checked_at":"2025-09-08T02:00:09.813Z","response_time":121,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["boilerplate","react","react-router","redux","server-side-rendering","ssr"],"created_at":"2024-10-02T14:04:12.254Z","updated_at":"2026-02-13T03:01:51.163Z","avatar_url":"https://github.com/jameslnewell.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rechannel\n\nOpinionated glue for building web apps with React and Redux.\n\nGlues together `react`, `redux`, `react-router`, `react-router-redux`, `redial` and `redux-devtools-extension`.\nUseful for both client side _and_ UniversalJS apps.\n\n\u003e This package is experimental and the API may receive breaking changes before v1.0.0.\n\n## Installation\n\n    npm install --save rechannel react react-dom react-redux \\\n      react-router react-router-redux redial redux\n\n## Usage\n\n### Client\n\n```javascript\nimport rechannel from 'rechannel';\nimport routes from './routes';\nimport reducer from './reducer';\n\n//creates a store, sets up the router, pre-fetches the necessary data\n// and renders the page\nrechannel({\n  routes,\n  reducer\n});\n\n```\n\n\u003e Note: If you're not using a server you'll have to create your own HTML file.\n\nTry the [example](https://github.com/jameslnewell/rechannel/tree/master/example/client.js).\n\n### Server\n\n```javascript\n\nimport express from 'express';\nimport rechannel from 'rechannel';\nimport routes from './routes';\nimport reducer from './reducer';\n\nconst app = express();\n\napp.use('/', express.static(`./public`));\n\n//returns a middleware function that creates a store, sets up the router, pre-fetches necessary data\n// and renders the page\napp.use(rechannel({\n  routes,\n  reducer\n}));\n\nconst server = app.listen(8000, () =\u003e {\n  const host = server.address().address;\n  const port = server.address().port;\n  console.log('App running at http://%s:%s', host, port);\n});\n\n```\n\nTry the [example](https://github.com/jameslnewell/rechannel/tree/master/example/server.js).\n\n## API\n\n```js\nrechannel(options : object)\n```\n\nCreate a store, set up the router, pre-fetch necessary data\nand render the page.\n\n**Options:**\n\nCommon options:\n\n- `routes : Element|function` _Required_. A `\u003cRoute/\u003e` element or a function creating a `\u003cRoute/\u003e` element. Function are passed the `getState()` and `dispatch()` methods from the redux store (useful for restricting access in a `onEnter` hook). Learn more about configuring routes in the [React Router docs](https://github.com/reactjs/react-router/blob/master/docs/guides/RouteConfiguration.md).\n- `reducer : object` _Required_. A keyed object of reducer functions that may be passed to `combineReducers()`. Learn more about reducer functions in the [Redux docs](http://redux.js.org/docs/Glossary.html#reducer).\n- `middleware : array\u003cfunction\u003e` Optional. An array of middleware functions. Learn more about middleware functions in the [Redux docs](http://redux.js.org/docs/Glossary.html#middleware).\n- `enhancer : array\u003cfunction\u003e` Optional. An array of enhancer functions. Learn more about enhancer functions in the [Redux docs](http://redux.js.org/docs/Glossary.html#store-enhancer).\n- `history : History` Optional. A [history](https://www.npmjs.com/package/history) instance. Default's to `react-router`'s `browserHistory` on the client and the result of `react-router`'s `createMemoryHistory` on the server. Learn more about history objects in the `react-router` [Histories docs](https://github.com/reactjs/react-router/blob/master/docs/guides/Histories.md).\n\nHooks:\n\n- `$init : function`  Optional. Called after the redux store is initialised. May return a promise.\n- `$load : function`  Optional. Called after any data is (pre-)loaded. May return a promise.\n\nClient specific options:\n\n- `element : HTMLElement` Optional. The `HTMLElement` which React will render into. Defaults to `document.querySelector('#app')`.\n\nServer specific options:\n\n- `html : Component` Optional. A component that renders the root HTML. Passed the Redux `state` and the React Router component(s) as `children` via `props`. Defaults to [this component](https://github.com/jameslnewell/rechannel/tree/master/lib/createHtml.js).\n- `send : function(res, html)` Optional. A function that allows customisation of the response sent by the server. Passed the response object and a HTML string.\n\n**Returns:**\n\nReturns nothing on the client. Returns an `express` middleware function on the server.\n\n**Note:** On the client, routes aren't re-created for each time you navigate to a new page, if you're using a factory function to create the routes and utilising the `cookies` or `query` parameters,\nthe routes won't be re-created with the new query or cookie values. The route factory function will only be re-evaluated when you re-load the page.\n\n```js\ncreateHtml(options : object)\n```\n\nCreate a React component for rendering `\u003chtml\u003e` on the server.\n\n**Options:**\n\n- `title : string|function`\n- `script : string|Array\u003cstring\u003e`\n- `style : string|Array\u003cstring\u003e`\n\n**Returns:**\n\nReturns a React component for rendering `\u003chtml\u003e` on the server.\n\n## Change log\n\n### 0.10.0\n\n- add: support server rendered async routes as per https://github.com/ReactTraining/react-router/blob/master/docs/guides/ServerRendering.md#async-routes\n\n### 0.9.0\n\n- add: added `headers` as a parameter for all hooks\n- add: now passing `query`, `cookies` and `headers` to your `Html` component\n\n### 0.8.0\n\n- add: added the ability to provide a custom `history` object\n- add: added `redux-immutable-state-invariant` to non-production builds which trigger an error when the redux state has been mutated\n- add: added validation around some of the `options` to assist developers in finding problems earlier\n\n### 0.7.0\n\n- add: added a `query` parameter to the `$init`, `$load` and `fetch` hooks\n\n### 0.6.2-3\n\n- fix: fixed a bug where routes weren't being re-created per request so conditional routing resulted in outcomes\n\n### 0.6.0\n\n- add: added `$init()` and `$load()` hooks\n\n### 0.5.0\n\n- add: allow routes to be a function\n\n### 0.4.2\n\n- fix: add keyword metadata\n\n### 0.4.1\n\n- fix: `createHtml()` parameters `script` and `style` need to be cast to arrays\n\n### 0.4.0\n\n- add: `createHtml()` parameters `script` and `style` now accept an array of script and style files\n\n### 0.3.0\n\n- break: turned the `Html` component into a factory function to allow customisation of the `\u003chtml\u003e` title, script and style names\n\n## To do\n\n- write tests\n- rename `fetch` trigger to `load`\n- allow the `reducer` to be a single reducer function\n- allow the `middleware` and `enhancer` parameters to be a function call that receives the `req` in order to be configured e.g. `redux-effects-cookie`\n- clean-up `locals` passed to `redial` - allow them to be user configurable\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjameslnewell%2Frechannel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjameslnewell%2Frechannel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjameslnewell%2Frechannel/lists"}