{"id":15207175,"url":"https://github.com/jonathannen/cater","last_synced_at":"2025-10-02T23:35:51.032Z","repository":{"id":57194997,"uuid":"114091343","full_name":"jonathannen/cater","owner":"jonathannen","description":"A modular convention-driven framework for React and Friends","archived":true,"fork":false,"pushed_at":"2019-02-13T05:44:59.000Z","size":1168,"stargazers_count":1,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-05-05T05:21:53.278Z","etag":null,"topics":["babel","jest","react","webpack"],"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/jonathannen.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-12-13T07:57:38.000Z","updated_at":"2023-01-28T18:13:53.000Z","dependencies_parsed_at":"2022-09-16T05:14:32.623Z","dependency_job_id":null,"html_url":"https://github.com/jonathannen/cater","commit_stats":null,"previous_names":["clashbit/cater"],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathannen%2Fcater","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathannen%2Fcater/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathannen%2Fcater/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathannen%2Fcater/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jonathannen","download_url":"https://codeload.github.com/jonathannen/cater/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219876112,"owners_count":16554735,"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":["babel","jest","react","webpack"],"created_at":"2024-09-28T06:23:31.461Z","updated_at":"2025-10-02T23:35:50.446Z","avatar_url":"https://github.com/jonathannen.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🍽 Cater \u0026middot; [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://github.com/facebook/react/blob/master/LICENSE) [![Build Status](https://travis-ci.org/clashbit/cater.svg?branch=master)](https://travis-ci.org/clashbit/cater)\n\nHello.\n\nCater is a convention-driven framework for building Universal applications, using React and Friends.\n\nThe primary goal of Cater is to **eliminate as much boilerplate as possible**. If you're writing code for your users rather than your tools, Cater is doing its job.\n\nCater will configure the following components out-of-the-box\n\n* Babel 6\n* Jest 22\n* React 16\n* Webpack 4\n\nAs core components, Cater tends to have a strong opinion on how they're set up. The configuration is augmented and extended by Plugins.\n\nFeel free to have a poke around. For a quick look, take a look at the [hello-world application](https://github.com/clashbit/cater/tree/master/examples/hello-world) and its peers under [examples](https://github.com/clashbit/cater/tree/master/examples).\n\nGood luck. To get in touch, drop me a line at the author details listed in package.json 🙇‍♂️\n\n\u003chr/\u003e\n\n## Table of Contents\n\n* [Motivation](#motivation)\n* [Getting Started](#getting-started)\n* [Core Concepts](#core-concepts)\n  * [Modes](#modes)\n  * [Sides](#sides)\n  * [Universal Imports](#universal-imports)\n  * [Universal Wrappering](#universal-wrappering)\n* [Plugins](#plugins)\n* [Examples](#examples)\n* [Alternatives](#alternatives)\n* [Contributing](#contributing)\n\n\u003chr/\u003e\n\n## Motivation\n\nThere are three main motivations behind cater:\n\n* **Micro-Services having First-Class \"Micro-Applications\"**\u003cbr/\u003eHaving experience with several Ruby on Rails monoliths, we now want to write platforms as a series focused, contained applications.\n* **No Boilerplate**\u003cbr/\u003eLots of focused applications sounds tidy, but also means lots of boilerplate. Lots of repeated code. Cater's mantra is \"no boilerplate\". We want focussed, contained _straightforward_ applications.\n* **Fully Universal Applications**\u003cbr/\u003eBoilerplate is one complicating issue. Overlap, repetition, and competition between the client and server code is another. Cater aims to be a simple way of building and maintaining Universal applications.\n\n\u003ca id=\"getting-started\"\u003e\u003c/a\u003e\n\n## Getting Started (aka \"Hello Cater\")\n\nThe simplest example is hello-world. Note that most of the Cater examples assume the use of the [yarn package manager](https://yarnpkg.com/en/).\n\nIn the spirit of no boilerplate, let's get started. First of all, let's create your project directory and add in cater.\n\n    mkdir hello-cater\n    cd hello-cater\n    yarn add cater\n    yarn add --dev cater-build\n\nNote that we have two cater modules. One covers the core and runtime portions. The second is for build-time compilation. That's covered later in this README.\n\nNow let's say hello:\n\n    mkdir app\n    touch app/app.js\n\nIn that app/app.js file, use your favorite editor to add in the following:\n\n    import React from 'react';\n    import Title from 'app/cater/title';\n    export default () =\u003e (\n      \u003cdiv\u003e\n        \u003cTitle\u003eHello Down There!\u003c/Title\u003e\n        \u003ch1\u003eHello World! (from Cater)\u003c/h1\u003e\n      \u003c/div\u003e\n    );\n\nWe're ready to roll. Run:\n\n    yarn run cater dev\n\nThen visit http://localhost:3000/\n\nThat's it. You've got a Cater application up and running. For extra credit, quit with CTRL-C and then run:\n\n    yarn run cater build\n    NODE_ENV=production yarn run cater start\n\nThe first command will build your code into the build directory. The second starts a production-configured server against that build code. Browse to the same location as before. You might not notice, but it's quite a bit snappier than before.\n\nThat's the very simple intro. Most of the time you'll want to add the cater commands to the package.json scripts, add tests and the like. You'll find more detailed code in the [examples directory](https://github.com/clashbit/cater/tree/master/examples). This includes a very slightly upgraded version of [this Hello World Example](https://github.com/clashbit/cater/tree/master/examples/hello-world).\n\n\u003ca id='core-concepts'\u003e\u003c/a\u003e\n\n## Core Concepts\n\n\u003ca id=\"modes\"\u003e\u003c/a\u003e\n\n### Modes (aka \"Times\")\n\nCater is designed to be a build-centric framework. You develop against a development version of the framework, and then build this to static code for release. We call this different stages \"modes\". Cater has three primary modes:\n\n* **Dev**: is for development. This is a hot-reloading local version that a developer will typically work against.\n* **Build**: signifies the code is being built for production. Many of the dev-time tools are used, such as Webpack. However, they are configured for production-time execution. For example, built turns on JavaScript minification.\n* **Runtime**: is for running the code in a production or production-like environment.\n\nThese are referred to as dev-time, build-time and runtime.\n\nThese will be related to the NODE_ENV values you may be familar with, but with some differences. For example, the build spans both development and production configurations. In build you're still running in the development (cater-build) environment, but you are generating production (runtime) code. In Cater idiom, dev-time also resembles what would often be an integration test.\n\nThese modes also have very different performance profiles. The Hello-World example above takes (on typical hardware) 2ms to render in dev and the JavaScript bundle is almost 2MB. In production the code those figures are 0.5ms and 32KB (of gzipped, minified JavaScript).\n\nDev and Build modes are enabled by the cater-build package. That's why we recommend you install cater-build as a development dependency (devDependency). Runtime is enabled by the cater package, which imports cater-runtime.\n\n    yarn add cater\n    yarn add --dev cater-build\n\nIn this way, you can test and build your application in a full \"cater-build\" environment and then only deploy the production packages absolutely necessary for runtime.\n\n\u003ca id=\"sides\"\u003e\u003c/a\u003e\n\n### Sides\n\nCater is designed to make your applications as Universal as possible. Whilst some code will be shared, there are always differences between running code on the server-side and client-side. When Cater starts up, it creates configurations for different \"sides\", representing the server and client sides. These configurations are largely shared, but varying where necessary for that particular side.\n\nAlong with the client and server sides, the \"Universal Side\" is code that is shared by the client and server. In the Getting Started example, the `app/app.js` component was under the Universal \"app\" directory.\n\nIt's possible that we will add sides down the line - for example for React Native or Electron.\n\nTo facilitate code differences between the sides, Cater has Universal Imports, Universal Wrappering (See Below).\n\n### Universal Imports\n\nThe core Cater piece plugs into the Babel and Webpack framework to produce differentiated builds for the client and server sides. What does this mean? If you had a directory structure like:\n\n    + app\n      - app.js\n      - main.js\n    + client\n      - sidebar.js\n    + server\n      - sidebar.js\n    - package.json\n\nIn this trivial example, the App React Component lays out both the Main and Sidebar components. It does this by importing `app/main` and `app/sidebar`.\n\nOne the client-side, this brings in `app/app.js`, which then imports `app/main.js` and `client/sidebar.js`. On the server it brings in the same, except the Sidebar resolves to `server/sidebar.js`. In this way you can create differentiate components depending on the \"side\" they are on.\n\nFor many components, this isn't necessary. You just import from app. Or, you can still import `./your/regular/file/like/normal`.\n\nHowever, there are plenty of components where it is necessary. If you take a look at the cater-redux package you'll see Provider Components. On the server side it determines the initial state. On the client side it rehydrates the Redux state.\n\nYou can also specify imports like `server/name` or `client/name` where you want a specific side to apply.\n\n### Universal Wrappering\n\nAnother key feature is wrappering. For any import of `app/my-component` a tree of paths will be searched. This will be a series of paths, which are then searched with the directory \"app\" and then either the directory \"client\" or \"server\", depending on the side. The tree will look something like:\n\n    + \u003cyour-current-application\u003e\n      - app\n      - \u003cclient|server\u003e\n    + cater-assets\n      - app\n      - \u003cclient|server\u003e\n    + cater-build\n      - app\n      - \u003cclient|server\u003e\n\nIn the above example, cater-assets is a \"plugin\", which are described below. Plugins bring in specific features, such as asset compilation, Redux, or CSS-in-JS. The cater-assets plugin happens to be one that is always included by default.\n\nLet's assume the code is running server-side and you wanted to import the Title component from app/title. The code (at build time) would check:\n\n    your-current-application/app/title\n    your-current-application/server/title\n    cater-assets/app/title\n    cater-assets/server/title\n    ... and so on.\n\nSo it's possible to _override_ the Title component at `cater-build/server/title.js` by putting one at either `your-current-application/app/title.js` or `your-current-application/server/title.js`. Whichever is appropriate.\n\nHowever, sometimes you want to inherit. In this case you want to replace the component, but also get a reference to the origial. For this, you use the caret `^` import. Imports like `app/^` will return the next component in the search path.\n\nWhat does that mean? Taking the example of `your-current-application/server/title.js` an import of `app/^` would return the component _up the path list_, being the Title component in `cater-build/server/title.js`. In your own Title component you can then extent or wrapper that original component as you see fit. Like so:\n\n    import ParentTitle from 'app/^'; // ...the mysterious caret import...\n    import React from 'react';\n\n    class MyTitle extends React.Component {\n\n        render() {\n          return \u003cParentTitle\u003eI've changed the title!\u003c/ParentTitle\u003e\n        }\n    }\n\n    export default MyTitle;\n\nThe Title component is a contrived example, but there are a number of real applications. The simplest of which is wrappering providers. Each plugin can add a provider that then wrappers the following one. An example of this is the [cater-redux/server/provider.js](https://github.com/clashbit/cater/blob/master/packages/cater-redux/server/provider.js).\n\nThis code adds in the Redux Provider and then wrappers it in the parent provider. In this way you can stack providers and other components between your application, plugins and the core Cater code.\n\n## Plugins\n\nSo we have Universal Imports and Universal Wrappering. Why? The main reason is to facilitate plugins.\n\nPlugins add in features and libraries like Asset Compilation, Redux, CSS-in-JS, or React Router. Ideally with zero configuration.\n\nUniversal Imports allow plugins to provide Universal components. Taking the simple Title component in Hello-Cater above, this component is different for the server and client sides. On the server it sets the `\u003chead\u003e\u003ctitle\u003e` element. On the client it uses JavaScript to change `document.title`. Killer.\n\nUniveral Wrapping allows plugins to cascade behavior. The most common case is adding in providers. A CSS-in-JS Theme Provider can wrapper a Redux or React Router Provider without being aware of the specifics of the other plugins.\n\nLet's pick up from the Hello-Cater example at the top of the document. In the same project, run:\n\n     yarn add --dev cater-react-router\n\nThen change the app/app.js file to the following:\n\n    import React from \"react\";\n    import { Link, Route, Switch } from \"react-router-dom\";\n\n    export default () =\u003e (\n      \u003cdiv\u003e\n        \u003cp\u003e\n          \u003cLink to=\"/hello\"\u003eSay Hello\u003c/Link\u003e or{\" \"}\n          \u003cLink to=\"/goodbye\"\u003esay Goodbye\u003c/Link\u003e.\n        \u003c/p\u003e\n        \u003cSwitch\u003e\n          \u003cRoute exact path=\"/hello\"\u003e\u003ch1\u003eHello!\u003c/h1\u003e\u003c/Route\u003e\n          \u003cRoute exact path=\"/goodbye\"\u003e\u003ch1\u003eGoodbye!\u003c/h1\u003e\u003c/Route\u003e\n        \u003c/Switch\u003e\n      \u003c/div\u003e\n    );\n\nThen run as before:\n\n    yarn run cater dev\n\nHead back to http://localhost:3000 and you'll be able to use the links to click between the Hello and Goodbye routes. Note that the code routes client-side using the `BrowserRouter` react-router component.\n\nThat's it. This example is simplified, but can easily be extended to a full application.\n\n## Examples\n\nThere are a number of projects under the example directory. To highlight some:\n\n**/examples/hello-world**\u003cbr/\u003e\nThe eponymous introduction application. Hello World is a single App Component that gives the world a friendly \"Hello\".\n\n**/examples/custom-layout**\u003cbr/\u003e\nA Cater application with it's own customized Layout.\n\n**/examples/express**\u003cbr/\u003e\nBy default, Cater in development will launch it's own http.Server. However, you use your own. In this example, we plug Cater into the Express web framework. Express handles the incoming requests, delegating to the Cater handler.\n\n**/examples/redux-counter-split**\u003cbr/\u003e\nCater with the Redux framework enabled.\n\n**/examples/show-emotion**\u003cbr/\u003e\nShows Cater being used with the [emotion](https://github.com/emotion-js/emotion) CSS-in-JS framework.\n\n## Alternatives\n\nCater is very new and still working towards version 1.0. However, there are plenty of great React frameworks out there. To mention a couple:\n\nThe first alternative to mention is [Create React App](https://github.com/facebookincubator/create-react-app). It's the best way to get started on a React application.\n\nThis library was somewhat inspired from using the [Next.js](https://github.com/zeit/next.js/) Framework. This is an attempt to learn from the ground up, plus take a modular and convention-driven approach.\n\n## Contributing\n\nIf you feel like working on this project, reach out. Contact details are in the top-level `package.json`.\n\nNavigating the code:\n\n* `contrib`\n  * Plugins that are versioned independently of the core cater packages.\n* `examples`\n  * Examples illustrating the use of Cater. Many of these also function as integration tests for specific plugins and features.\n  * An ideal example has no boilerplate and can be replicated easily by someone new to Cater.\n* `packages`\n  * The core Cater packages. This includes:\n  * `cater` contains the CLI code and `cater-runtime` as a dependency. It'll also work with `cater-build`, but only if it's explictly installed.\n  * `cater-build` has the components to run Cater at dev and build-time. As a result the code is aimed to be more verbose and defensive.\n  * `cater-runtime` has the code for running a cater application in production. For this it's leaner and focussed on performance and robustness.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonathannen%2Fcater","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjonathannen%2Fcater","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonathannen%2Fcater/lists"}