{"id":15434285,"url":"https://github.com/rayandrew/skuy","last_synced_at":"2026-01-24T13:25:17.634Z","repository":{"id":57362521,"uuid":"141685548","full_name":"rayandrew/skuy","owner":"rayandrew","description":"Skuy is Powerpack for React Server Side Rendering","archived":false,"fork":false,"pushed_at":"2018-07-20T10:06:45.000Z","size":1186,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-08-20T03:29:25.271Z","etag":null,"topics":["after","code-splitting","next","react","react-dom","rogue","skuy","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":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rayandrew.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-07-20T08:29:13.000Z","updated_at":"2025-07-27T02:00:50.000Z","dependencies_parsed_at":"2022-09-13T21:10:52.202Z","dependency_job_id":null,"html_url":"https://github.com/rayandrew/skuy","commit_stats":null,"previous_names":["rayandrews/skuy"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/rayandrew/skuy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rayandrew%2Fskuy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rayandrew%2Fskuy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rayandrew%2Fskuy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rayandrew%2Fskuy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rayandrew","download_url":"https://codeload.github.com/rayandrew/skuy/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rayandrew%2Fskuy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28728591,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-24T10:24:43.181Z","status":"ssl_error","status_checked_at":"2026-01-24T10:24:36.112Z","response_time":89,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["after","code-splitting","next","react","react-dom","rogue","skuy","ssr"],"created_at":"2024-10-01T18:38:39.222Z","updated_at":"2026-01-24T13:25:17.599Z","avatar_url":"https://github.com/rayandrew.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  Skuy\n  \u003cbr /\u003e\n  \u003cbr /\u003e\n  \u003ca align=\"center\" href=\"https://nodei.co/npm/skuy/\"\u003e\u003cimg align=\"center\" src=\"https://nodei.co/npm/skuy.png?downloads=true\u0026downloadRank=true\u0026stars=true\" /\u003e\u003c/a\u003e\n\u003c/h1\u003e\n\n\u003ch2 align=\"center\"\u003e\n  \u003cbr\u003e\n    If \u003ca href=\"https://github.com/jaredpalmer/after.js\"\u003eAfterJS\u003c/a\u003e and \u003ca href=\"https://github.com/alidcastano/rogue.js\"\u003eRogueJS\u003c/a\u003e had a baby...\n  \u003cbr /\u003e\n  \u003cbr /\u003e\n  \u003cimg alt=\"Crossover Meme\" src=\"https://github.com/rayandrews/skuy/blob/master/assets/crossover.gif\"\u003e\n  \u003cbr /\u003e\n  \u003cbr /\u003e\n  \u003ca href=\"https://github.com/zeit/next.js\"\u003eNextJS\u003c/a\u003e beloved grandchild..\n  \u003cbr /\u003e\n  \u003cbr /\u003e\n\u003c/h2\u003e\n\n## Getting started with Skuy\n\n__Skuy__ has same API as After.js.\n\nIf you have familiarize yourself with After, then you are not finding it difficult to migrate to __Skuy__.\n\n__Also :__ You can build it on your SSR boilerplate (either it webpack, parcel, etc).\n\n__Skuy__ is just another component wrapper to ease React SSR.\n\n### Quickstart with Razzle\n\n```bash\ncurl https://codeload.github.com/rayandrews/skuy/tar.gz/master | tar -xz --strip=2 skuy-master/examples/basic\ncd basic\n```\n\n---\n\n## Background\n\n[After](https://github.com/jaredpalmer/after.js) is awesome library but it has some drawbacks that I found it difficult to modify it in my other projects such as,\n\n* Not able to modify routes tree\n* Not able to modify static method for get initial props (getInitialProps is good, but you should be able to modify the name based on your content)\n* Not able to add loading or error component while transitioning and getting initial props for other route\n* Code splitting and load inital props based on routes config\n\n---\n\nHow about [Rogue](https://github.com/alidcastano/rogue.js)?\n\n\u003e Brilliant Idea to walk into react tree component recursively like Apollo did in their library\n\nBut.. something is bothering me..\n\n* Document feature in Next and After is __REALLY__ syntactic sugar\n* GetInitialProps method only called on top highest level component (for performance, I know)\n* And of course, not be able to modify static method too\n\n\u003ch3 align=\"center\"\u003e\n  \u003cbr /\u003e\n    tl;dr\n  \u003cbr /\u003e\n    I found them not too suitable for my works\n  \u003cbr /\u003e\n\u003c/h3\u003e\n\n---\n\n**Table of Contents**\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n\n- [How Skuy Works](#how-skuy-works)\n- [Data Fetching](#data-fetching)\n  - [`getInitialProps | { name } : (ctx) =\u003e object`](#getinitialprops---name---ctx--object)\n  - [Injected Context Data](#injected-context-data)\n- [Routing](#routing)\n- [Custom Options](#custom-options)\n- [Code Splitting](#code-splitting)\n- [Custom Document](#custom-document)\n- [Custom/Async Rendering](#customasync-rendering)\n- [Custom/Async Rendering](#customasync-rendering)\n- [Authors](#authors)\n- [Special Thanks](#special-thanks)\n- [Inspirations](#inspirations)\n- [License](#license)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n---\n\n## How Skuy Works\n\n__Skuy__ will walk through your React Tree to find static method that you've already specified.\n\nIf __Skuy__ not found any static method, __Skuy__ will gracefully return your rendered component.\n\n## Data Fetching\n\nFor now, in all components that you want to fetch, you can add a `static async getInitialProps` or `another function's name that exactly does the same`.\nThis will be called on both initial server render, and then client mounts.\n\n\u003ch4\u003e\n  Results are made available on the CONTEXT NOT ON PROPS\n  \u003cbr /\u003e\n  \u003cbr /\u003e\n  If you want to get data in the props, you must include the skuyHoc to easily passing data from context to props.\n  \u003cbr /\u003e\n\u003c/h4\u003e\n\n\u003ch5 align=\"center\"\u003e\n  \u003cbr /\u003e\n  OR\n  \u003cbr /\u003e\n\u003c/h5\u003e\n\n\u003ch4\u003e\n  \u003cbr /\u003e\n  Use SkuyConsumer (React ^16) to consume the data.\n  \u003cbr /\u003e\n  \u003cbr /\u003e\n\u003c/h4\u003e\n\n```js\n// Home.js\nimport React from 'react';\nimport { NavLink } from 'react-router-dom';\n\nclass Home extends React.Component {\n  static async getInitialProps({ req, res, match }) {\n    const stuff = await CallMyApi();\n    return { stuff }; // returned value from static method not passed on props by default\n  }\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003cNavLink to=\"/about\"\u003eAbout\u003c/NavLink\u003e\n        \u003ch1\u003eHome\u003c/h1\u003e\n      \u003c/div\u003e\n    );\n  }\n}\n\nexport default Home;\n```\n\n### `getInitialProps | { name } : (ctx) =\u003e object`\n\nWithin `getInitialProps` or `another function name`, you will get access to all you need to fetch data on both\nthe client and the server (same like After)\n\n* `req?: Request`: (server-only) A Express.js request object\n* `res?: Request`: (server-only) An Express.js response object\n* `match`: React Router 4's `match` object.\n* `history`: React Router 4's `history` object.\n* `location`: (client-only) React Router 4's `location` object.\n* `isServer`: Check whether code is running on server or client\n\n__You can also add another variable to be passed into static method like Redux Store, etc.__\n\n\u003e If you are using some server only modules inside `getInitialProps` or `anoher function name`, make sure to [import them properly](https://arunoda.me/blog/ssr-and-server-only-modules).\n\u003e Otherwise, it'll slow down your app.\n\n_Taken from [Next](https://github.com/zeit/next.js)_\n\n### Injected Context Data\n\n* `data: any` - Whatever you have returned in `getInitialProps` or `another function name`\n* `loading: boolean` - Loading state while fetching data in client\n* `error: boolean` - Error state (but not throwing error) while fetching data in client\n* `prefetch: (pathname: string) =\u003e void` - Imperatively prefetch _and cache_ data for a path.\n\n```js\n// Home.js\nimport React from 'react';\nimport { NavLink } from 'react-router-dom';\nimport { SkuyConsumer } from 'skuy/core';\n\nclass Home extends React.Component {\n  static async getInitialProps({ req, res, match }) {\n    const stuff = await CallMyApi();\n    return { stuff };\n  }\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003cNavLink to=\"/about\"\u003eAbout\u003c/NavLink\u003e\n        \u003ch1\u003eHome\u003c/h1\u003e\n        \u003cSkuyConsumer\u003e\n          {({ data, loading }) =\u003e (\n            if(loading) return \u003cdiv\u003e'Loading...'\u003c/div\u003e;\n\n            return data.stuff;\n          )}\n        \u003c/SkuyConsumer\u003e\n      \u003c/div\u003e\n    );\n  }\n}\n\nexport default Home;\n```\n\n\u003ch5 align=\"center\"\u003e\n  \u003cbr /\u003e\n  OR\n  \u003cbr /\u003e\n  \u003cbr /\u003e\n\u003c/h5\u003e\n\nUsing `skuyHoc` to wrap your context into props, just like Redux `connect`.\n\nYou can also pass options like `LoadingComponent` and `ErrorComponent` to reduce boilerplate in your render function.\n\n```\nskuyHoc : ({ LoadingComponent?: null, ErrorComponent?: null }) =\u003e (Component) =\u003e WrappedComponent\n```\n\n__TL;DR All static methods will be hoisted__\n\n```js\n// Home.js\nimport React from 'react';\nimport { NavLink } from 'react-router-dom';\nimport { skuyHoc } from 'skuy/core';\n\nclass Home extends React.Component {\n  static async getInitialProps({ req, res, match }) {\n    const stuff = await CallMyApi();\n    return { stuff };\n  }\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003cNavLink to=\"/about\"\u003eAbout\u003c/NavLink\u003e\n        \u003ch1\u003eHome\u003c/h1\u003e\n        \u003cdiv\u003e{this.props.data.stuff}\u003c/div\u003e\n      \u003c/div\u003e\n    );\n  }\n}\n\nexport default skuyHoc({\n  LoadingComponent: () =\u003e \u003cdiv\u003eLoading...\u003c/div\u003e,\n  ErrorComponent: () =\u003e \u003cdiv\u003eError!\u003c/div\u003e\n})(Home);\n```\n\n## Routing\n\nReact Router 4 is used in all over __Skuy__ API.\n\n## Custom Options\n\n\u003cp\u003e\n  \u003cdetails\u003e\n    \u003csummary\u003e\n      \u003cb\u003eExamples\u003c/b\u003e\n    \u003c/summary\u003e\n    \u003cul\u003e\n      \u003cli\u003e\u003ca href=\"./examples/basic-rnw\"\u003eBasic with React Native Web\u003c/a\u003e\u003c/li\u003e\n    \u003c/ul\u003e\n  \u003c/details\u003e\n\u003c/p\u003e\n\n__Skuy__ does not need any router config, so just passing React component with React Router 4 in it, and you're done!\n\n__Skuy__ has default options as follows\n\n```js\n{\n  document = DefaultSkuyDocument,\n  staticMethod = 'getInitialProps',\n  rootId = 'root',\n  dataId = 'server-app-state',\n}\n```\n\n\u003ch3\u003eIf you want to change static method, rootId, and dataId, you must pass it both in client and server\u003c/h3\u003e\n\nExample\n\n`Skuy : ({ component, data, options }) =\u003e RenderedComponent`\n\n```js\n// client.js\n\nimport React from 'react';\nimport { hydrate } from 'react-dom';\nimport { BrowserRouter } from 'react-router-dom';\nimport './client.css';\n\nimport { Skuy } from 'skuy/core';\nimport { getSsrData } from 'skuy/client';\nimport App from './App';\n\nconst data = getSsrData();\nconst options = {\n  staticMethod: 'fetchData', // * change the method to make client can preload data\n\n  // Anything else you add here will be made available\n  // within static method in client\n  // e.g a redux store, etc.\n}\n\nhydrate(\n  \u003cBrowserRouter\u003e\n    \u003cSkuy component={App} data={data} options={options} /\u003e\n  \u003c/BrowserRouter\u003e,\n  document.getElementById('root')\n);\n\nif (module.hot) {\n  module.hot.accept();\n}\n```\n\n`render : (component = App, routerContext, options) =\u003e html : string`\n\n```js\n// server.js\n\nimport express from 'express';\nimport { render } from 'skuy/server';\n\nimport App from './App';\n\nconst assets = require(process.env.RAZZLE_ASSETS_MANIFEST);\n\nconst server = express();\nserver\n  .disable('x-powered-by')\n  .use(express.static(process.env.RAZZLE_PUBLIC_DIR))\n  .get('/*', async (req, res) =\u003e {\n    const routerContext = {};\n\n    if (req.url.match(/.map$/)) return;\n\n    try {\n      const html = await render(App, routerContext, {\n        req,\n        res,\n        assets,\n        staticMethod: 'fetchData',\n        customThing: 'thing',\n\n        // Anything else you add here will be made available\n        // within static method in server\n        // e.g a redux store, etc.\n      });\n      res.send(html);\n    } catch (error) {\n      res.json(error);\n    }\n  });\n\nexport default server;\n```\n\n## Code Splitting\n\n\u003cp\u003e\n  \u003cdetails\u003e\n    \u003csummary\u003e\n      \u003cb\u003eExamples\u003c/b\u003e\n    \u003c/summary\u003e\n    \u003cul\u003e\n      \u003cli\u003e\u003ca href=\"./examples/redux-rnw-loadable-components\"\u003eLoadable Components with React Native Web and Redux\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"./examples/redux-rnw-react-loadable\"\u003eReact Loadable with React Native Web and Redux\u003c/a\u003e\u003c/li\u003e\n    \u003c/ul\u003e\n  \u003c/details\u003e\n\u003c/p\u003e\n\n__Skuy__ does not defining any code splitting method like After, Next, or Rogue (with loadable-components) did.\n\n\u003e But __Skuy__ does enforce you to implement code splitting with other libraries\n\nWith the right custom render function, you can implement it with another React code splitting library out there such as\n* [React Loadable](https://github.com/jamiebuilds/react-loadable)\n* [Loadable Components](https://github.com/smooth-code/loadable-components)\n\n## Custom Document\n\n\u003cp\u003e\n  \u003cdetails\u003e\n    \u003csummary\u003e\n      \u003cb\u003eExamples\u003c/b\u003e\n    \u003c/summary\u003e\n    \u003cul\u003e\n      \u003cli\u003e\u003ca href=\"./examples/basic-rnw\"\u003eBasic with React Native Web\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"./examples/redux-rnw-loadable-components\"\u003eLoadable Components with React Native Web and Redux\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"./examples/redux-rnw-react-loadable\"\u003eReact Loadable with React Native Web and Redux\u003c/a\u003e\u003c/li\u003e\n    \u003c/ul\u003e\n  \u003c/details\u003e\n\u003c/p\u003e\n\nSkuy works like After and Next, you can override any html structure that suitable for your needs.\n\n**_Why we need it?_**\n\nIt really helps if you want to add CSS or other component with side-effects (React Helmet, etc) that needs custom document structure.\n\nExample with React Native Web\n\n```js\nimport React, { Component } from 'react';\nimport { AppRegistry } from 'react-native';\nimport { renderToStaticMarkup } from 'react-dom/server';\n\nimport { SkuyRoot, SkuyData } from 'skuy/document';\n\n/* eslint-disable */\n\nexport default class CustomDocument extends Component {\n  static async getInitialProps({ assets, data, renderPage }) {\n    const page = await renderPage();\n\n    AppRegistry.registerComponent('SkuyRoot', () =\u003e SkuyRoot);\n    const { getStyleElement } = AppRegistry.getApplication('SkuyRoot', {});\n\n    const rnwCss = renderToStaticMarkup(getStyleElement());\n\n    return { assets, data, rnwCss, ...page };\n  }\n\n  render() {\n    const {\n      rootId,\n      dataId,\n      helmet,\n      assets,\n      data,\n      rnwCss,\n    } = this.props;\n\n    const htmlAttrs = helmet.htmlAttributes.toComponent();\n    const bodyAttrs = helmet.bodyAttributes.toComponent();\n\n    return (\n      \u003chtml lang=\"en\" {...htmlAttrs}\u003e\n        \u003chead\u003e\n          \u003cmeta httpEquiv=\"X-UA-Compatible\" content=\"IE=edge\" /\u003e\n          \u003cmeta charSet=\"utf-8\" /\u003e\n          \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1\" /\u003e\n          {helmet.title.toComponent()}\n          {helmet.meta.toComponent()}\n          {helmet.link.toComponent()}\n          {assets.client.css \u0026\u0026 (\n            \u003clink rel=\"stylesheet\" href={assets.client.css} /\u003e\n          )}\n          \u003cstyle\n            id=\"react-native-stylesheet\"\n            dangerouslySetInnerHTML={{\n              __html: rnwCss\n                .replace(/\u003c\\/style\u003e/g, '')\n                .replace(/\u003cstyle id=\"react-native-stylesheet\"\u003e/g, ''),\n            }}\n          /\u003e\n        \u003c/head\u003e\n        \u003cbody {...bodyAttrs}\u003e\n          \u003cSkuyRoot id={rootId} /\u003e\n          \u003cSkuyData id={dataId} data={data} /\u003e\n          \u003cscript\n            type=\"text/javascript\"\n            src={assets.client.js}\n            crossOrigin=\"anonymous\"\n          /\u003e\n        \u003c/body\u003e\n      \u003c/html\u003e\n    );\n  }\n}\n```\n\nIf you were using something like `styled-components`, and you need to wrap you entire app with some sort of additional provider or function, you can do this with `renderPage()`.\n\n_Taken from [After](https://github.com/jaredpalmer/after.js)_\n\n```js\n// Document.js\nimport React, { Component } from 'react';\nimport { ServerStyleSheet } from 'styled-components'\nimport { renderToStaticMarkup } from 'react-dom/server';\n\nimport { SkuyRoot, SkuyData } from 'skuy/document';\n\nexport default class CustomDocument extends Component {\n  static async getInitialProps({ assets, data, renderPage }) {\n    const sheet = new ServerStyleSheet();\n    const page = await renderPage(App =\u003e props =\u003e sheet.collectStyles(\u003cApp {...props} /\u003e));\n    const styleTags = sheet.getStyleElement();\n    return { assets, data, ...page, styleTags };\n  }\n\n  render() {\n    const {\n      rootId,\n      dataId,\n      helmet,\n      assets,\n      data,\n      styleTags,\n    } = this.props;\n    const htmlAttrs = helmet.htmlAttributes.toComponent();\n    const bodyAttrs = helmet.bodyAttributes.toComponent();\n\n    return (\n      \u003chtml lang=\"en\" {...htmlAttrs}\u003e\n        \u003chead\u003e\n          \u003cmeta httpEquiv=\"X-UA-Compatible\" content=\"IE=edge\" /\u003e\n          \u003cmeta charSet=\"utf-8\" /\u003e\n          \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1\" /\u003e\n          {helmet.title.toComponent()}\n          {helmet.meta.toComponent()}\n          {helmet.link.toComponent()}\n          {styleTags}\n        \u003c/head\u003e\n        \u003cbody {...bodyAttrs}\u003e\n          \u003cSkuyRoot id={rootId} /\u003e\n          \u003cSkuyData id={dataId} data={data} /\u003e\n          \u003cscript\n            type=\"text/javascript\"\n            src={assets.client.js}\n            defer\n            crossOrigin=\"anonymous\"\n          /\u003e\n        \u003c/body\u003e\n      \u003c/html\u003e\n    );\n  }\n```\n\nTo use custom document, you need to pass it on server file\n\n```js\n// server.js\n\nimport express from 'express';\nimport { render } from 'skuy/server';\n\nimport App from './App';\nimport Doc from './Document';\n\nconst assets = require(process.env.RAZZLE_ASSETS_MANIFEST);\n\nconst server = express();\nserver\n  .disable('x-powered-by')\n  .use(express.static(process.env.RAZZLE_PUBLIC_DIR))\n  .get('/*', async (req, res) =\u003e {\n    const routerContext = {};\n\n    if (req.url.match(/.map$/)) return;\n\n    try {\n      const html = await render(App, routerContext, {\n        req,\n        res,\n        assets,\n        staticMethod: 'fetchData',\n        customThing: 'thing',\n        document: Doc,\n        // Anything else you add here will be made available\n        // within static method in server\n        // e.g a redux store, etc.\n      });\n      res.send(html);\n    } catch (error) {\n      res.json(error);\n    }\n  });\n\nexport default server;\n```\n\n## Custom/Async Rendering\n\n\u003cp\u003e\n  \u003cdetails\u003e\n    \u003csummary\u003e\n      \u003cb\u003eExamples\u003c/b\u003e\n    \u003c/summary\u003e\n    \u003cul\u003e\n      \u003cli\u003e\u003ca href=\"./examples/redux-rnw-loadable-components\"\u003eLoadable Components with React Native Web and Redux\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"./examples/redux-rnw-react-loadable\"\u003eReact Loadable with React Native Web and Redux\u003c/a\u003e\u003c/li\u003e\n    \u003c/ul\u003e\n  \u003c/details\u003e\n\u003c/p\u003e\n\nYou can provide a custom (potentially async) rendering function as an option to Skuy `render` function, just like After.js.\n\nIf it presents, it will be used instead of the default ReactDOMServer renderToString function.\n\nIt has to return an object of shape `{ html : string!, ...otherProps }`, in which `html` will be used as the rendered string.\n\n`otherProps` will be passed as props to the rendered Document.\n\n```js\ndefaultRenderer = (node) =\u003e ({ html: ReactDOMServer.renderToString(node) })\n```\n\nExample\n\n```js\n\n// server.js\n\nimport express from 'express';\nimport { render } from 'skuy/server';\n\nimport { Capture } from 'react-loadable';\nimport { getBundles } from 'react-loadable/webpack';\n\nimport stats from 'build/react-loadable.json';\n\nimport configureStore from 'store/configureStore';\n\nimport App from './App';\nimport Doc from './Document';\n\nconst assets = require(process.env.RAZZLE_ASSETS_MANIFEST);\n\nconst server = express();\nserver\n  .disable('x-powered-by')\n  .use(express.static(process.env.RAZZLE_PUBLIC_DIR))\n  .get('/*', async (req, res) =\u003e {\n    const routerContext = {};\n\n    if (req.url.match(/.map$/)) return;\n\n    try {\n      const preloadedState = {};\n      const store = configureStore(preloadedState);\n      const modules = [];\n\n      const customRenderer = (node) =\u003e {\n        const CustomApp = (\n          \u003cCapture report={(moduleName) =\u003e modules.push(moduleName)}\u003e\n            \u003cProvider store={store}\u003e{node}\u003c/Provider\u003e\n          \u003c/Capture\u003e\n        );\n\n        const bundles = getBundles(stats, modules);\n        const chunks = bundles.filter((bundle) =\u003e bundle.file.endsWith('.js'));\n\n        return {\n          chunks,\n          store, // notice that this will passed into document\n          html: renderToString(CustomApp),\n        };\n      };\n\n      const html = await render(App, routerContext, {\n        req,\n        res,\n        assets,\n        staticMethod: 'fetchData',\n        customThing: 'thing',\n        document: Doc,\n        store, // this will be passed in static method in server\n\n        // Anything else you add here will be made available\n        // within static method in server\n        // e.g a redux store, etc.\n      });\n      res.send(html);\n    } catch (error) {\n      res.json(error);\n    }\n  });\n\nexport default server;\n```\n\n---\n\n## Authors\n\n* Ray Andrew [@rayandrews](https://github.com/rayandrews)\n* Natan Elia [@natanelia](https://github.com/natanelia)\n\n---\n\n## Special Thanks\n\n* Ivana Irene [@ivanaairenee](https://github.com/ivanaairenee)\n* Reinaldo Ignatius [@nimitz21](https://github.com/nimitz21)\n\n---\n\n## Inspirations\n\n* [Next.js](https://github.com/zeit/next.js)\n* [After.js](https://github.com/jaredpalmer/after.js)\n* [Rogue.js](https://github.com/alidcastano/rogue.js)\n* [Razzle](https://github.com/jaredpalmer/razzle)\n\n---\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frayandrew%2Fskuy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frayandrew%2Fskuy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frayandrew%2Fskuy/lists"}