diff --git a/.babelrc b/.babelrc new file mode 100644 index 00000000..c14b2828 --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["react-app"] +} diff --git a/.circleci/config.yml b/.circleci/config.yml index 372d6f85..5934a6f9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -6,19 +6,25 @@ version: 2 jobs: build: docker: - - image: kriasoft/node-ci:8.2.1-alpine - working_directory: ~/repo + - image: circleci/node:8.9.3 steps: - checkout - - setup_remote_docker - # Download and cache dependencies - restore_cache: - key: yarn-cache-{{ checksum "yarn.lock" }} - - run: yarn install --no-progress + key: yarn-v1-{{ checksum "yarn.lock" }} + key: yarn-v1- + - run: + name: Install NPM modules + command: yarn - save_cache: - key: yarn-cache-{{ checksum "yarn.lock" }} + key: yarn-v1-{{ checksum "yarn.lock" }} paths: - - node_modules - # Run unit tests - - run: yarn lint - - run: yarn test + - ~/.cache/yarn/v1 + - run: + name: Test + command: | + yarn lint + yarn test --forceExit + - run: + name: Build + command: yarn build + diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 00000000..5ef965d4 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,17 @@ +{ + "extends": ["eslint-config-react-app", "prettier"], + "plugins": ["flowtype", "prettier"], + "rules": { + "prettier/prettier": [ + "error", + { + "printWidth": 80, + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": true, + "trailingComma": "all" + } + ] + } +} diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 98f3eb91..00000000 --- a/.eslintrc.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * React Static Boilerplate - * Copyright (c) 2015-present Kriasoft. All rights reserved. - */ - -/* @flow */ - -module.exports = { - extends: ['eslint-config-react-app', 'prettier'], - plugins: ['flowtype', 'prettier'], - rules: { - 'prettier/prettier': [ - 'error', - { - singleQuote: true, - trailingComma: 'all', - }, - ], - }, -}; diff --git a/.firebaserc b/.firebaserc new file mode 100644 index 00000000..c55a7598 --- /dev/null +++ b/.firebaserc @@ -0,0 +1,5 @@ +{ + "projects": { + "default": "react-firebase-graphql" + } +} diff --git a/.flowconfig b/.flowconfig index f111649a..8d5a6541 100644 --- a/.flowconfig +++ b/.flowconfig @@ -1,11 +1,14 @@ [ignore] -.*/build -.*/docs -.*/node_modules -.*/public +.*/build/.* +.*/public/.* +.*/setup.js [include] +[libs] + +[lints] + [options] -module.system.node.resolve_dirname=node_modules -module.system.node.resolve_dirname=src + +[strict] diff --git a/.gitignore b/.gitignore index 79db8e76..36366ffc 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ # Dependencies /node_modules +/functions/node_modules # Testing /coverage @@ -21,6 +22,8 @@ __generated__ npm-debug.log* yarn-debug.log* yarn-error.log* +firebase-debug.log* +firebase-error.log* # VS Code .vscode/* diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..4cbee9a2 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +node_modules +package.json \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..0b0eae19 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,8 @@ +{ + "printWidth": 80, + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": true, + "trailingComma": "all" +} diff --git a/.stylelintrc.js b/.stylelintrc.js index 60c085d2..78f6076c 100644 --- a/.stylelintrc.js +++ b/.stylelintrc.js @@ -1,6 +1,7 @@ /** - * React Static Boilerplate - * Copyright (c) 2015-present Kriasoft. All rights reserved. + * React Starter Kit for Firebase and GraphQL + * https://github.com/kriasoft/react-firebase-starter + * Copyright (c) 2015-present Kriasoft | MIT License */ const primerConfig = require('stylelint-config-primer'); @@ -28,6 +29,7 @@ module.exports = { 'at-rule-empty-line-before': null, 'block-opening-brace-space-after': null, 'block-closing-brace-space-before': null, + 'declaration-colon-newline-after': null, // https://github.com/hudochenkov/stylelint-order/blob/master/rules/order/README.md 'order/order': [ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a8e43209..c56ba010 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ -# Contributing to React Static Boilerplate +# Contributing to React Starter Kit for Firebase and GraphQL -♥ **React Static Boilerplate** and want to get involved? Thanks! There are plenty of ways you can +♥ **React Firebase Starter** and want to get involved? Thanks! There are plenty of ways you can help! Please take a moment to review this document in order to make the contribution process easy and @@ -10,10 +10,9 @@ Following these guidelines helps to communicate that you respect the time of the and developing this open source project. In return, they should reciprocate that respect in addressing your issue or assessing patches and features. - ## Using the issue tracker -The [issue tracker](https://github.com/kriasoft/react-static-boilerplate/issues) is the preferred +The [issue tracker](https://github.com/kriasoft/react-firebase-starter/issues) is the preferred channel for [bug reports](#bugs), [features requests](#features) and [submitting pull requests](#pull-requests), but please respect the following restrictions: @@ -29,8 +28,8 @@ requests](#pull-requests), but please respect the following restrictions: [`Babel`](https://github.com/babel/babel) or [`Webpack`](https://github.com/webpack/webpack) (open them in their respective repositories). - + ## Bug reports A bug is a _demonstrable problem_ that is caused by the code in the repository. Good bug reports are @@ -68,16 +67,16 @@ Example: > include the lines of code that you have identified as causing the bug, and potential solutions > (and your opinions on their merits). - + ## Feature requests Feature requests are welcome. But take a moment to find out whether your idea fits with the scope -and aims of the project. It's up to *you* to make a strong case to convince the project's developers +and aims of the project. It's up to _you_ to make a strong case to convince the project's developers of the merits of this feature. Please provide as much detail and context as possible. - + ## Pull requests Good pull requests - patches, improvements, new features - are a fantastic help. They should remain @@ -97,11 +96,11 @@ Adhering to the following process is the best way to get your work included in t ```bash # Clone your fork of the repo into the current directory - git clone https://github.com//react-static-boilerplate.git + git clone https://github.com//react-firebase-starter.git # Navigate to the newly cloned directory - cd react-static-boilerplate + cd react-firebase-starter # Assign the original repo to a remote called "upstream" - git remote add upstream https://github.com/kriasoft/react-static-boilerplate.git + git remote add upstream https://github.com/kriasoft/react-firebase-starter.git ``` 2. If you cloned a while ago, get the latest changes from upstream: diff --git a/README.md b/README.md index 1b6d1536..0b535274 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,8 @@ -# React Static Boilerplate   - -[**React Static Boilerplate**](https://github.com/kriasoft/react-static-boilerplate) (RSB) is a -boilerplate and tooling for creating modern stand-alone web applications (aka -[SPA](https://en.wikipedia.org/wiki/Single-page_application)s) for a serverless architecture. RSB -significantly reduces cost by eliminating the need for servers such as EC2 instances because the -entire site can be hosted directly from CDN ([Firebase](https://www.firebase.com/), [GitHub -Pages](https://pages.github.com/), [Amazon S3](http://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteHosting.html), -or other similar cloud storage). Sites built with RSB can be fully functional with REST API or -GraphQL calls to micro-services such as [Amazon Lambda](https://aws.amazon.com/lambda/), -[Azure Functions](https://azure.microsoft.com/services/functions/), or dynamic Docker endpoints -hosted on [DigitalOcean](https://www.digitalocean.com/?refcode=eef302dbae9f&utm_source=github&utm_medium=oss_sponsorships&utm_campaign=opencollective). -RSB demonstrates how to use component-based UI development approach with best of breed -technologies including [React](http://facebook.github.io/react/), [Relay Modern](http://facebook.github.io/relay), -[Babel](http://babeljs.io/), [Webpack](https://webpack.github.io/), -[React Hot Loader](http://gaearon.github.io/react-hot-loader/), and more. - -**View** [online demo](https://rsb.kriasoft.com)  |  **Follow us** on -[Gitter](https://gitter.im/kriasoft/react-static-boilerplate), [Twitter](https://twitter.com/ReactStatic), -or [ProductHunt](https://www.producthunt.com/tech/react-static-boilerplate)  |  -**Learn** [React.js and ES6](#learn-reactjs-and-es6)  |  **Visit our sponsors**: +# React Starter Kit for Firebase and GraphQL   + +[**React Firebase Starter**](https://github.com/kriasoft/react-firebase-starter) (RFS) is a popular project template (aka boilerplate) for creating single-page applications with React, Firebase and GraphQL. + +**View** [online demo](https://rfs.kriasoft.com)  |  **Follow us** on [Twitter](https://twitter.com/ReactStarter)  |  **Get Support** on [Telegram](https://t.me/ReactStarterKit)  |  **Visit our sponsors**:

@@ -31,69 +15,60 @@ or [ProductHunt](https://www.producthunt.com/tech/react-static-boilerplate) &nbs --- -This project was bootstraped with [React Static Boilerplate][rsb] by [Kriasoft][kriasoft] ([support][gitter]). +This project was bootstraped with [React Firebase Starter][rfs] by [Kriasoft][kriasoft] ([get support][support]). ### Tech Stack * [Create React App][cra] for development and test infrastructure (see [user guide][cradocs]) -* [React][react] + [Relay Modern][relay] for UI and declarative data fetching +* [Material UI][mui] to reduce development time by integrating Google's [Material Design][material] * [Styled Components][sc] for component friendly CSS styles ([docs][scdocs]) +* [Firebase][firebase] for serverless architecture, authentication and free CDN hosting * [Universal Router][router] + [history][history] for declarative routing and client-side navigation +Also, you need to be familiar with [HTML][html], [CSS][css], [JavaScript][js] ([ES2015][es2015]) and [React](https://reactjs.org/docs/). ### Directory Layout ```bash ├── node_modules/ # 3rd-party libraries and utilities ├── public/ # Static files such as favicon.ico etc. -│ ├── favicon.ico # Application icon to be displayed in bookmarks -│ ├── index.html # HTML template -│ ├── robots.txt # Instructions for search engine crawlers -│ ├── manifest.json # Application meta data -│ └── ... # etc. ├── src/ # Application source code -│ ├── About/ # About page -│ ├── App/ # Application shell (layout) component -│ ├── Button/ # Button component -│ ├── ErrorPage/ # Error page -│ ├── Home/ # Home page -│ ├── Link/ # Link component to be used instead of +│ ├── components/ # Shared React components +│ ├── routes/ # Components for pages/screens + routing information +│ ├── auth.js # Authentication manager │ ├── history.js # Client-side navigation manager │ ├── index.js # <== Application entry point (main) <=== │ ├── registerServiceWokrer.json # This list of application routes │ ├── relay.js # Relay Modern client -│ ├── router.js # Application routes │ ├── graphql.schema # GraphQL schema obtained from a GraphQL API -│ └── store.js # Application state manager (Redux) -├── test/ # Unit and integration tests +│ └── theme.js # Overrides for Material UI default styles ├── package.json # The list of project dependencies + NPM scripts └── setup.js # Customizations for create-react-app ``` - ### Prerequisites -* [Node.js][nodejs] v8.2.1 or higher + [Yarn][yarn] v0.27.5 or higher   (*HINT: On Mac install - them via [Brew][brew]*) +* [Node.js][nodejs] v8.2.1 or higher + [Yarn][yarn] v0.27.5 or higher   (_HINT: On Mac install + them via [Brew][brew]_) * [Watchman][wm] v4.7.0 or higher, required by the [Relay Compiler][relaycompiler] * [VS Code][vc] editor (preferred) + [Project Snippets][vcsnippets], [EditorConfig][vceditconfig], [ESLint][vceslint], [Flow][vcflow], [Prettier][vcprettier], and [Babel JavaScript][vcjs] plug-ins - ### Getting Started Just clone the repo and start hacking: ```bash -$ git clone https://github.com/kriasoft/react-static-boilerplate.git MyApp +$ git clone https://github.com/kriasoft/react-firebase-starter.git MyApp $ cd MyApp $ yarn install # Install project dependencies listed in package.json $ yarn relay # Pre-compile GraphQL queries with Relay Compiler $ yarn start # Compiles the app and opens it in a browser with "live reload" ``` -The app should become available at [http://localhost:3000/](http://localhost:3000/). +Then open [http://localhost:3000/](http://localhost:3000/) to see your app.
+

npm start

### How to Test @@ -103,7 +78,6 @@ $ yarn fix # Attempt to automatically fix ESLint warning $ yarn test # Run unit tests. Or, `yarn test -- --watch` ``` - ### How to Deploy ```bash @@ -111,35 +85,38 @@ $ yarn build -- --prerender # Build the app for production and pre-render $ npx gh-pages -d ./build # Push the contents of the ./build folder to GitHub Pages ``` - ### How to Update If you keep the original Git history after cloning this repo, you can always fetch and merge the recent updates back into your project by running: ```bash -git remote add react-static-boilerplate https://github.com/kriasoft/react-static-boilerplate.git +git remote add react-firebase-starter https://github.com/kriasoft/react-firebase-starter.git git checkout master -git fetch react-static-boilerplate -git merge react-static-boilerplate/master +git fetch react-firebase-starter +git merge react-firebase-starter/master yarn install yarn relay ``` +<<<<<<< HEAD *NOTE: Try to merge as soon as the new changes land on the master branch in React Static Boilerplate repository, otherwise your project may diverge too much from the base/upstream repo.* +======= +_NOTE: Try to merge as soon as the new changes land on the master branch in React Static Boilerplate +repository, otherwise your project may diverse too much from the base/upstream repo._ +>>>>>>> Refactor to integrate with Firebase ### How to Contribute Anyone and everyone is welcome to [contribute](CONTRIBUTING.md) to this project. The best way to -start is by checking our [open issues](https://github.com/kriasoft/react-static-boilerplate/issues), -[submit a new issues](https://github.com/kriasoft/react-static-boilerplate/issues/new?labels=bug) or -[feature request](https://github.com/kriasoft/react-static-boilerplate/issues/new?labels=enhancement), +start is by checking our [open issues](https://github.com/kriasoft/react-firebase-starter/issues), +[submit a new issues](https://github.com/kriasoft/react-firebase-starter/issues/new?labels=bug) or +[feature request](https://github.com/kriasoft/react-firebase-starter/issues/new?labels=enhancement), participate in discussions, upvote or downvote the issues you like or dislike, send [pull requests](CONTRIBUTING.md#pull-requests). - ### Learn React.js and ES6 :mortar_board:   [React for Beginners](https://reactforbeginners.com/friend/konstantin) and [ES6 Training Course](https://es6.io/friend/konstantin) by Wes Bos
@@ -147,7 +124,6 @@ requests](CONTRIBUTING.md#pull-requests). :green_book:   [Getting Started with React](http://amzn.to/2bmwP5V) by Doel Sengupta and Manu Singhal (Apr, 2016)
:green_book:   [You Don't Know JS: ES6 & Beyond](http://amzn.to/2bBfVnp) by Kyle Simpson (Dec, 2015)
- ### Related Projects * [React Starter Kit](https://github.com/kriasoft/react-starter-kit) — Boilerplate and tooling for @@ -155,23 +131,30 @@ requests](CONTRIBUTING.md#pull-requests). * [Node.js API Starter Kit](https://github.com/kriasoft/nodejs-api-starter) — Boilerplate and tooling for building data APIs with Docker, Node.js and GraphQL - ### License Copyright © 2015-present Kriasoft. This source code is licensed under the MIT license found in -the [LICENSE.txt](https://github.com/kriasoft/react-static-boilerplate/blob/master/LICENSE.txt) file. +the [LICENSE.txt](https://github.com/kriasoft/react-firebase-starter/blob/master/LICENSE.txt) file. --- + Made with ♥ by Konstantin Tarkus ([@koistya](https://twitter.com/koistya), [blog](https://medium.com/@tarkus)) -and [contributors](https://github.com/kriasoft/react-static-boilerplate/graphs/contributors) +and [contributors](https://github.com/kriasoft/react-firebase-starter/graphs/contributors) -[rsb]: https://github.com/kriasoft/react-static-boilerplate +[rfs]: https://github.com/kriasoft/react-firebase-starter [kriasoft]: https://www.kriasoft.com/ -[gitter]: https://gitter.im/kriasoft/react-static-boilerplate +[support]: https://t.me/ReactStarterKit [cra]: https://github.com/facebookincubator/create-react-app +[mui]: https://material-ui-next.com/ +[material]: https://material.io/ [cradocs]: https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md +[html]: https://developer.mozilla.org/en-US/docs/Web/HTML +[css]: https://developer.mozilla.org/en-US/docs/Web/CSS +[js]: https://developer.mozilla.org/en-US/docs/Web/JavaScript +[es2015]: http://babeljs.io/learn-es2015/ [react]: https://facebook.github.io/react/ [relay]: https://facebook.github.io/relay/ +[firebase]: https://firebase.google.com/ [router]: https://github.com/kriasoft/universal-router [history]: https://github.com/ReactTraining/history [sc]: https://www.styled-components.com/ diff --git a/firebase.json b/firebase.json new file mode 100644 index 00000000..ab738e6a --- /dev/null +++ b/firebase.json @@ -0,0 +1,30 @@ +{ + "firestore": { + "rules": "firestore.rules", + "indexes": "firestore.indexes.json" + }, + "hosting": { + "public": "build", + "ignore": ["firebase.json", "**/.*", "**/node_modules/**"], + "rewrites": [ + { + "source": "**", + "destination": "/index.html" + } + ], + "headers": [ + { + "source": "service-worker.js", + "headers": [ + { + "key": "Cache-Control", + "value": "no-cache, no-store, must-revalidate" + } + ] + } + ] + }, + "storage": { + "rules": "storage.rules" + } +} diff --git a/firestore.indexes.json b/firestore.indexes.json new file mode 100644 index 00000000..04c1b158 --- /dev/null +++ b/firestore.indexes.json @@ -0,0 +1,14 @@ +{ + // Example: + // + // "indexes": [ + // { + // "collectionId": "widgets", + // "fields": [ + // { "fieldPath": "foo", "mode": "ASCENDING" }, + // { "fieldPath": "bar", "mode": "DESCENDING" } + // ] + // } + // ] + "indexes": [] +} diff --git a/firestore.rules b/firestore.rules new file mode 100644 index 00000000..31eda174 --- /dev/null +++ b/firestore.rules @@ -0,0 +1,7 @@ +service cloud.firestore { + match /databases/{database}/documents { + match /{document=**} { + allow read, write; + } + } +} diff --git a/functions/index.js b/functions/index.js new file mode 100644 index 00000000..cee42bd6 --- /dev/null +++ b/functions/index.js @@ -0,0 +1,7 @@ +const functions = require('firebase-functions'); + +// Create and Deploy Your First Cloud Functions +// https://firebase.google.com/docs/functions/write-firebase-functions +exports.helloWorld = functions.https.onRequest((req, res) => { + res.send('Hello from Firebase!'); +}); diff --git a/functions/package.json b/functions/package.json new file mode 100644 index 00000000..14588ed9 --- /dev/null +++ b/functions/package.json @@ -0,0 +1,16 @@ +{ + "name": "functions", + "description": "Cloud Functions for Firebase", + "scripts": { + "serve": "firebase serve --only functions", + "shell": "firebase experimental:functions:shell", + "start": "npm run shell", + "deploy": "firebase deploy --only functions", + "logs": "firebase functions:log" + }, + "dependencies": { + "firebase-admin": "~5.4.2", + "firebase-functions": "^0.7.1" + }, + "private": true +} diff --git a/package.json b/package.json index 1d2db1f8..9aef62a4 100644 --- a/package.json +++ b/package.json @@ -3,17 +3,21 @@ "version": "0.0.0", "private": true, "dependencies": { + "@firebase/app": "^0.1.4", + "@firebase/auth": "^0.3.0", + "@firebase/firestore": "^0.2.1", "classnames": "^2.2.5", "history": "^4.7.2", "lodash": "^4.17.4", + "material-ui": "1.0.0-beta.23", "prop-types": "^15.5.10", "query-string": "^5.0.0", - "react": "^15.6.1", - "react-dom": "^15.6.1", + "react": "^16.2.0", + "react-dom": "^16.2.0", "react-relay": "^1.3.0", "relay-runtime": "^1.3.0", "styled-components": "^2.1.2", - "universal-router": "^3.2.0" + "universal-router": "^5.0.0" }, "devDependencies": { "babel-plugin-relay": "^1.3.0", @@ -23,33 +27,38 @@ "eslint-config-prettier": "^2.3.0", "eslint-plugin-flowtype": "^2.35.0", "eslint-plugin-prettier": "^2.2.0", - "flow-bin": "^0.53.1", + "flow-bin": "^0.61.0", "gh-pages": "^1.0.0", - "husky": "^0.14.3", - "lint-staged": "^4.0.4", + "husky": "^0.15.0-beta.16", + "lint-staged": "^6.0.0", "pre-render": "^0.1.0-preview.2", "prettier": "^1.6.1", - "react-scripts": "1.0.12", + "react-scripts": "1.0.17", "relay-compiler": "^1.3.0", "stylelint": "^8.0.0", "stylelint-config-primer": "^2.0.1", - "stylelint-config-standard": "^17.0.0", + "stylelint-config-standard": "^18.0.0", "stylelint-config-styled-components-processor": "^0.1.1", - "stylelint-order": "^0.6.0", - "stylelint-processor-styled-components": "^0.4.0" + "stylelint-order": "^0.8.0", + "stylelint-processor-styled-components": "^1.2.1" }, "lint-staged": { - "*.js": ["eslint --no-ignore --fix", "git add"], - "*.json": ["prettier --write", "git add"] + "*.js": [ + "eslint --no-ignore --fix", + "git add" + ], + "*.json": [ + "prettier --write", + "git add" + ] }, "scripts": { + "postinstall": "(cd ./functions && yarn install --no-lockfile)", "precommit": "lint-staged", - "lint": - "eslint --ignore-path .gitignore --ignore-pattern \"!**/.*\" . && stylelint \"./src/**/*.js\"", - "fix": - "eslint --ignore-path .gitignore --ignore-pattern \"!**/.*\" --fix .", - "relay": - "node ./setup --download-schema && relay-compiler --src ./src --schema ./src/schema.graphql", + "flow": "flow", + "lint": "eslint --ignore-path .gitignore --ignore-pattern \"!**/.*\" . && stylelint \"src/**/*.js\"", + "fix": "eslint --ignore-path .gitignore --ignore-pattern \"!**/.*\" --fix .", + "relay": "node ./setup --download-schema && relay-compiler --src ./src --schema ./src/schema.graphql", "build": "node ./setup && react-scripts build && node ./render", "test": "node ./setup && react-scripts test --env=jsdom", "deploy": "node ./setup && react-scripts build && gh-pages -d build", diff --git a/public/index.html b/public/index.html index e2d43bcc..26aa8256 100644 --- a/public/index.html +++ b/public/index.html @@ -1,13 +1,25 @@ - + + - React Static Boilerplate + + React App