Apollo 2 Universal Starter Kit — GraphQL React JavaScript app boilerplate for Mobile, Server and Web where code for all platforms built with Webpack to enable max code reuse, stack: Apollo, GraphQL, React 16, React Native, Expo, Express, Knex, SQLite, Twitter Bootstrap, Babel, Webpack
JavaScript TypeScript Other
Clone or download
Permalink
Failed to load latest commit information.
.github Added .github/ISSUE_TEMPLATE.md (optional) Nov 7, 2017
config Convert server Upload module into TypeScript (#805) Aug 13, 2018
docs add helpers and some docs Jan 6, 2018
packages Delete chai-subset lib and move test helpers for the Users module (#811) Aug 13, 2018
tools Fix CLI add/delete module (#794) Aug 3, 2018
typings Convert counter module into TypeScript (#781) Jul 22, 2018
.babelrc User module UI components for mobile (#688) May 9, 2018
.babelrc.native Add temp workaround for latest babel-minify Jul 13, 2018
.dockerignore Add Docker support (#394) Sep 28, 2017
.env Add .env with APP_DIR to the root for Docker (#675) Mar 12, 2018
.eslintignore Drop flow types from master May 4, 2018
.eslintrc Merge branch 'master' into workspaces-lerna Jan 24, 2018
.eslintrc.base.json Fix interoperability issues between tslint and eslint Jul 19, 2018
.gitignore Implement authentication across all platforms (#644) Mar 28, 2018
.travis.yml Add language picker for all UI toolkits (#708) Apr 25, 2018
CONTRIBUTING.md Added CONTRIBUTING.md (optional) Nov 7, 2017
Dockerfile Fix couldn't find git Docker error Dec 6, 2017
LICENSE Add 2018 to the copyright Jan 14, 2018
Procfile Utilize "npm start" both for dev and prod Sep 14, 2016
README.md GraphiQL -> GPlayground renaming Aug 3, 2018
app.png Update project icons Jul 12, 2017
docker-compose.prod.yml Switch from LAN IP to localhost everywhere where possible Oct 4, 2017
docker-compose.yml Switch from LAN IP to localhost everywhere where possible Oct 4, 2017
lerna.json Init Lerna Dec 13, 2017
logo.svg Update project icons Jul 12, 2017
package.json Convert counter module into TypeScript (#781) Jul 22, 2018
settings.js Move dotenv loading into server entry May 4, 2018
tsconfig.json Add support for both ES6 and TypeScript code Feb 19, 2018
tslint.json Convert counter module into TypeScript (#781) Jul 22, 2018
yarn.lock Delete chai-subset lib and move test helpers for the Users module (#811) Aug 13, 2018

README.md

Apollo v2 GraphQL app Starter Kit for Mobile, Web and Server with Webpack used everywhere

Use our chat, please, to get help really quick or to discuss general topic

Backers on Open Collective Sponsors on Open Collective Join the chat at https://gitter.im/sysgears/apollo-fullstack-starter-kit Build Status code style: prettier Twitter Follow

Apollo Universal Starter Kit is a SEO friendly boilerplate for Universal Mobile and Web app development built on top of Apollo, GraphQL, React 16, React Native, Expo, Redux, Express with SQL storage support, for styling Twitter Bootstrap, NativeBase and Ant Design integration. Hot Code Reload of back end & front end using Webpack and Hot Module Replacement to reflect your changes instantly and help you stay productive.

Hot Code Reload demo

screencast

Mobile app demo

Checkout our Mobile App Demo

Available Branches

Branch Description
stable The latest stable version of the kit
single Single-package Apollo v2 version of the kit
apollo1 Apollo v1 version of the kit
cli-crud generate CRUD implementations from the command line

Getting Started

  1. Clone the latest stable starter kit locally.
git clone -b stable https://github.com/sysgears/apollo-universal-starter-kit.git
cd apollo-universal-starter-kit
  1. Install dependencies (make sure you have yarn >= 1.0.0).
yarn
  1. Seed sample database data.
yarn seed
  1. Run starter kit in development mode. For running Android or iOS you need to set in packages/mobile/.spinrc.js config.builders.ios.enabled and/or config.builders.android.enabled field true. See Getting Started with React Native section.
yarn watch
  1. You browser will open the web application automatically with web app in a new tab.
  2. Change any app code and see the changes applied immediately!
  3. Open app in multiple tabs, try to increase counter or add a new post/comment in one tab and then switch to another tab. You will see that counter value and post/comment are updated there as well, because the application is live updated via subscriptions.

Getting Started with React Native

This starter kit adds full React Native integration, with Webpack as a packager and Expo. No native code compilation tools are needed in order to develop native mobile applications with this kit. You are able to run both web and mobile versions of your app at the same time connected to the same backend.

For running Android or iOS you need to set in packages/mobile/.spinrc.js config.builders.ios.enabled and/or config.builders.android.enabled field true.

Configuring IDE/Editor

Make sure to enable eslint and tslint integration in your Editor or IDE this will save you from many little and big traps when working with the code.

Running on a device

You need to install Expo app on your Android or iOS device and then you can scan the QR shown in the terminal, to start the app on your device.

Running in a simulator

Android

Download and install Android Studio and configure virtual phone via Tools -> Android -> AVD Manager. Choose Lollipop x86_64 API for your Phone, it is the lowest x86_64 API (because it is x86_64 emulator will work really fast). Make sure that you add ~/Android/Sdk/platform-tools folder that has adb added into PATH environment variable, so that Expo inside this kit used adb instance from Android SDK.

Then launch your virtual phone and launch starter kit after that via yarn watch. After starting, Expo app should start on it's own.

You can also use Genymotion. After downloading and installing you might need to install VirtualBox unless you already have it. Create a new emulator and start it. After starting the server Expo app should start on it's own. To bring up the developer menu press ⌘+M.

iOS

You need to install Xcode. Then install Command Line Tools by running xcode-select --install. Next, open up Xcode, go to preferences and click the Components tab, install a simulator from the list. After the installation if you run the server, simulator should start on it's own and open the app in Expo. To bring up the developer menu press ⌘+D.

Note: If iOS simulator fail to start expo client or the app: Try to reset the simulator in Hardware -> Erase all content and settings and restart the application.

Support

Community support

  • Gitter channel - questions, answers, general discussions
  • GitHub issues - submit issues, send feature requests
  • Wiki - community driven effort to document all the usage scenarios of the starter kit, editable by anyone
  • FAQ - frequently asked questions wiki page

Commercial support

SysGears team provides advanced support for commercial partners. A commercial partner will have a premium access to our team whether this is to help you with your code based on this starter kit or related technologies used in the kit. Contact us using Skype or via email: info@sysgears.com

Writing the code

This starter kit is designed so you can use it for just web, mobile or projects using both together. In case you do not want to use mobile, just set both builders.ios.enabled or builders.android.enabled settings in .spinrc.js to false.

To cover differences between platforms you can use platform-specific files.

MyComponent.web.jsx
MyComponent.android.jsx
MyComponent.ios.jsx

In case you only want to use it for web and do not intend to later add mobile version, you can omit .web.jsx extension and just use MyComponent.jsx. Same applies if you just wish to use it for mobile.

Currently counter example is implemented to support web and mobile version. If you want to try running CounterView.jsx as universal component, just delete or rename CounterView.web.jsx and you can see how the same component can be used for both web and mobile.

Writing modules in TypeScript

The starter kit supports both modules written in ES6 JavaScript and TypeScript. You can have a mix - some modules or even parts of modules written in ES6 and some in TypeScript.

When writting TypeScript modules you can face some pitfalls. The general discussion about TypeScript pitfalls will be handled here. The recipes from discussion will be mirrored into this section of documentation.

Known pitfalls:

  • TypeScript has limited support for the code using custom extensions. All the code targeted for web platform should have extension somefile.ts, because of that, not somefile.web.ts, so that the TS compiler can find it. And if the same file has different implementation for mobile platforms, it should have extension somefile.native.ts. In JavaScript code when you import somefile you never include per-platform extension, i.e. you never import somefile.native, because extension is determined at compile time automatically for you. With TypeScript the situation is different, somefile and somefile.naitve.ts might export different interfaces and in this case you will have to import somefile.native.
  • locales/index.js must be kept in JavaScript for now, if you rename it to have .ts extension you will run into incompatibilities between @alienfast/i18next-loader and TypeScript compiler. This can be fixed by making changes to @alienfast/i18next-loader.
  • When using stateless JSX component written in JavaScript from within TypeScript code you can get error TS2322 - missing key, despite the fact that key in question is declared optional. The known workaround for now is to convert this component to stateful JSX component.
  • tslint complains that the module is missing, though it is present in peerDependencies. tslint checks dependencies and either peerDependencies or devDependencies, not both, hence we face this problem. We have configured tslint to look into dependencies, devDependencies and optionalDependencies, this is the best that can be reached at the moment. Hence you can work around this issue by switching from using peerDependencies in package.json to optionalDependencies, this way both eslint and tslint find all needed modules.

Known issues

Currently we do not yet support persisted queries. This can be used in this starter kit currently only for web, but it is planed in the future.

Using with Docker

Get latest Docker and Docker Compose: https://www.docker.com/ https://docs.docker.com/compose/

Starting Docker container for Development

To run starter kit in development mode with hot code reload execute:

docker-compose up

, then open URL http://localhost:3000 in web browser or open URL exp://localhost:19001 in Expo Client Explore section (tap magnifier, enter URL, then tap it below). In case if you want to open the app on the phone use LAN IP of your development machine instead of localhost in Expo Client (QR code scanning will not work, because QR code will have address of Docker container).

Starting Docker container for Production

To run starter kit in production mode execute:

docker-compose -f docker-compose.prod.yml up

, then open URL http://localhost:3000 in web browser.

Configuring starter kit

This starter kit supplies boilerplate code for multiple platforms:

  • Node.js backend
  • Web frontend
  • Android frontend
  • iOS frontend

If you don't need some of these platforms you can turn off building their code in .spinrc.js as well as edit other build properties described below:

Option Description
buildDir output directory for build files
dllBuildDir output directory for Webpack DLL files used to speed up incremental builds
webpackDevPort the local port used for Webpack Dev Server process to host web frontend files
__API_URL__ URL to GraphQL backend endpoint
__WEBSITE_URL__ URL to website
ssr Use server side rendering in backend
webpackDll Utilize Webpack DLLs to speed up incremental builds
frontendRefreshOnBackendChange Trigger web frontend refresh when backend code changes
reactHotLoader Utilize React Hot Loader v3
persistGraphQL Generate and use persistent GraphQL queries

There are also application config options available in config/app.js to aid with debugging GraphQL and SQL:

Option Description
debugSQL Print executed by backend SQL commands
apolloLogging Log all Apollo GraphQL operations

Feature Modules Scaffolding with CLI

This starter kit encourages modular design of application features. Each feature should be designed as a decoupled module, deleting feature should ideally not break the remaining application. Basic feature module scaffolding is provided with the following command:

yarn cli addmodule <moduleName>

This will create all the necessary files to start developing on a new feature module. It creates client and server module. If you would like to only add one or the other, add a second parameter like:

yarn cli addmodule <moduleName> [client|server]

If you wish to remove an existing module, do so with:

yarn cli deletemodule <moduleName>

Again you can specify client or server as a second parameter, if you only wish to delete one or the other.

This way you can easily delete existing examples, like counter, post or user. Do keep in mind that you need at least one module linked on the server side. So deleting both, before creating any new ones first, will result in TypeError: Cannot read property 'schema' of undefined on the server side.

Run the following command to see the CLI help:

yarn cli

Features and examples included

  • Full LOGIN funcionality in user example with JWT tokens stored in localStorage and cookies

  • Stripe Payment Processor integration as a starting point for apps that use user subscriptions. Check subscription module documentation for details.

  • GraphQL API

    GraphQL is used as very flexible and much faster API in terms of bandwidth and round-trips, compared to REST. GraphQL requests are batched together automatically by Apollo

  • GraphQL subscriptions example

    Full CRUD functionality with Counter updating and Subscriptions in Posts and Comments example, with ReduxForm

  • GraphQL Cursor Pagination Example of Relay-style cursor pagination

  • Dataloader for loading comments in post example

  • Declarative/dynamic head section, using React Helmet

  • Google Analytics integration using React GA

  • Webpack for back end

    This starter kit is different from most of the starter kits out there, because it uses Webpack not only for front end, but for back-end code as well. This enables powerful Webpack features for back-end code, such as conditional compilation, embedding non-js files and CSS stylesheets into the code, hot code reload, etc.

  • Webpack and Expo for mobile front-end

    For the best code sharing support between back-end, web front-end and mobile front-end the Webpack is used to build React Native JavaScript bundles with the help of using Haul project parts. Resulting React Native JavaScript bundles use Expo, so no native code compilation tools are needed in order to develop native mobile applications with this kit.

  • Hot Code Reload for back end and front end

    Hot Code Reload for back end is done using Webpack. When Webpack prepares hot patches on the filesystem, SIGUSR2 signal is sent to Node.js app and embedded Webpack Hot Module Runtime reacts to this signal and applies patches to running modules from filesystem. Hot code reload for front end is using Webpack Dev Server and Hot Module Replacement to apply patches to front-end code. Hot patches for React components are applied on the front end and back end at the same time, so React should not complain about differences in client and server code.

  • Webpack DLL vendor bundle generation and updating out of the box

    For all the non-development dependencies of project package.json the Webpack vendor DLL bundle is generated and updated automatically, so that Webpack didn't process vendor libraries on each change to the project, but only when they are actually changed. This boosts speed of cold project start in development mode and speed of hot code reload even if the number of dependencies is huge.

  • Server Side Rendering with Apollo Redux Store sync

    On the initial web page request back end fully renders UI and hands off Apollo Redux Store state to front end. Frontend then starts off from there and updates itself on user interactions.

    If you don't need Server Side Rendering, set ssr key value to false in packages/client/.spinrc.js and packages/server/.spinrc.js

  • Optimistic UI updates

    This example application uses Apollo optimistic UI updates, that result in immediate UI update on user interaction and then, after data arrives from the server, UI state is finalized.

  • SQL and arbitrary data sources support

    Knex code to access SQLite is included as an example of using arbitrary data source with Apollo and GraphQL. NoSQL storage or any other data source can be used the same way.

    Debug SQL Prints out execuded queries, with respective times in development mode and can be set in config/app.js by debugSQL field true

  • Powerful stylesheets with Hot Reloading

    Twitter Bootstrap in form of SASS stylesheets is used for styling demo application. Application has stylesheet in styles.scss for global styling which is Hot Reloaded on change. React components styling is done by Styled Components.

    If you would like to use a different styling than Twitter Bootstrap, UI components are structured in a way to make it easy to use something else. We already prepared Ant Design integation. To switch the UI all you need to do is rename the import in packages/client/src/modules/common/components/web/index.jsx.

    NativeBase for mobile styling, with an option to use Ant Design Mobile. To switch, just change the export in packages/client/src/modules/common/components/native/index.jsx.

  • Babel for ES2017 transpiling

  • ESLint to enforce proper code style

  • React Hot Loader v3 for the sake of completeness this project also supports React Hot Loader v3, but it is turned off. By default this starter kit uses pure Webpack HMR for all hot reloading purposes and we think it covers all practical needs during development and using React Hot Loader v3 in addition to Webpack HMR makes hot reloading less predictable and buggy. To turn React Hot Loader v3 on: set reactHotLoader field of .spinrc.js to true.

  • PersistGraphQL Webpack Plugin is a tool to gather static GraphQL queries for GraphQL projects and inject them into build. It will make front end and back end aware of static queries used in the project and will only allow these queries for better security and less bandwidth.

  • TypeScript support. This kit supports both ES6 and TypeScript out of the box.

  • Internationalization with i18next

Project Structure

The project structure presented in this boilerplate is fractal, where functionality is grouped primarily by feature rather than file type. This structure is only meant to serve as a guide, it is by no means prescriptive. That said, it aims to represent generally accepted guidelines and patterns for building scalable applications.

.
├── packages                   # Yarn packages with application source code
│   ├── client                 # Front-end Yarn package
│   |   └── src
│   │       ├── app            # Common front-end application code
│   │       ├── modules        # Front-end feature-modules, each module has:
│   │       │                  # (components, containers, GraphQL queries, redux reducers)
│   │       ├── styles         # Application-wide styles
│   │       ├── testHelpers    # Test helper for front-end integration tests
│   │       └── index.tsx      # Entry point to web front-end with hot code reload
│   ├── common                 # Yarn package with Common code, redux store and logging
│   ├── mobile                 # Mobile front-end Yarn package
│   |   └── src
│   │       └── index.ts       # Entry point to mobile front-end with live code reload
│   └── server                 # Back-end Yarn package
│   |   └── src
│   │       ├── api            # GraphQL API implementation
│   │       ├── database       # Database migrations and seeds
│   │       │   └── migrations # Database migration scripts using Knex
│   │       │   └── seeds      # Database seed scripts using Knex
│   │       ├── middleware     # GraphQL Playground, GraphQL express and SSR rendering
│   │       ├── modules        # Back-end server feature-modules, each module has:
│   │       │                  # (schema definition, resolvers, sql queries)
│   │       ├── sql            # Knex connector
│   │       ├── testHelpers    # Test helper for back-end integration tests
│   │       ├── server.js      # GraphQL api server set up
│   │       └── index.ts       # Entry point to back-end with hot code reload
└── tools                      # All build and cli related files

Additional scripts

While developing, you will probably rely mostly on yarn watch; however, there are additional scripts at your disposal:

yarn <script> Description
watch Run your app in development mode and watch your changes. Hot code reload will be enabled in development.
start Run your app in production mode.
build Compiles the application to the build folder.
tests Runs unit tests with Mocha.
tests:watch Runs unit tests with Mocha and watches for changes automatically to re-run tests.
test Runs unit tests with Mocha and check for lint errors
lint Check for lint errors and runs for all .js and .jsx files.
seed Seed sample database using SQLite. Use --prod flag to run in "production" mode.
migrate Migrate the sample database
rollback Rollback the sample database to previous state.
cli CLI tool, currently used for modules scaffolding only.

Deployment to Production

Deploying to Linux running Node.js

  1. Clone the latest stable starter kit locally.
git clone -b stable https://github.com/sysgears/apollo-universal-starter-kit.git
cd apollo-universal-starter-kit
  1. Install dependencies.
yarn
  1. Seed production database data.
NODE_ENV=production yarn seed
  1. Compile project.
yarn build
  1. Run project in production mode.
yarn start

Publishing mobile apps

  1. Compile project for production via yarn build
  2. Run yarn exp publish to publish, the URL like: https://exp.host/@vlasenko/apollo-universal-starter-kit where your users can access mobile app from Expo Client will be printed in terminal.

Building standalone mobile apps for Play Store and App Store

  1. Compile project for production via yarn build
  2. Run yarn exp ba to launch building signed .apk or yarn exp bi for signed .iap.
  3. Run yarn exp bs to get status and links for signed standalone mobile applications when build finishes. For more details refer to Expo Build standalone apps documentation, but use yarn exp .. instead of exp ... command.

Deploying to Heroku

  1. Add your app to Heroku
  2. Allow Heroku to install build time dependencies from the devDependencies in package.json: Settings -> Config Variables -> Add, KEY: YARN_PRODUCTION, VALUE: false.
  3. Add EXP_USERNAME and EXP_PASSWORD config variables there as well. They will be used to publish mobile Expo Client applications
  4. Deploy your app on Heroku

Deploy

Heroku Demo

You can see latest version of this app deployed to Heroku here: https://apollo-universal-starter-kit.herokuapp.com

Contributors

Thanks goes to all the wonderful people who already contributed to Apollo Universal Starter Kit!

Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

License

Copyright © 2016, 2017 SysGears INC. This source code is licensed under the MIT license.