├── .circleci └── config.yml ├── .github └── ISSUE_TEMPLATE │ └── feature_request.md ├── .gitignore ├── .vscode ├── launch.json └── settings.json ├── LICENSE ├── PULL_REQUEST_TEMPLATE.md ├── README.md ├── _server ├── __tests__ │ ├── hello-world.test.ts │ └── server.test.ts ├── api │ └── hello-world.ts ├── index.ts └── server.ts ├── client ├── __tests__ │ ├── __snapshots__ │ │ └── subapp.spec.tsx.snap │ └── subapp.spec.tsx ├── app │ ├── app.tsx │ ├── components │ │ ├── TestComponent.tsx │ │ ├── about.tsx │ │ ├── error-page.tsx │ │ ├── header.tsx │ │ ├── home.tsx │ │ ├── index.ts │ │ └── subapp.tsx │ ├── index.tsx │ └── router.tsx ├── public │ ├── img │ │ ├── icon-128.png │ │ ├── icon-256.png │ │ ├── icon-48.png │ │ ├── icon-512.png │ │ ├── icon-72.png │ │ └── icon-96.png │ ├── index.html │ └── manifest.json ├── setupTests.ts ├── tsconfig.json └── webpack.config.js ├── docs ├── how-to-add-routes.md ├── index_README.md └── pwa │ └── resources.md ├── jest.config.js ├── package-lock.json ├── package.json ├── server └── index.js ├── tsconfig.json └── yarn.lock /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: circleci/node:7.10 6 | 7 | working_directory: ~/repo 8 | 9 | steps: 10 | - checkout 11 | 12 | - restore_cache: 13 | keys: 14 | - v1-dependencies-{{ checksum "package.json" }} 15 | - v1-dependencies- 16 | 17 | - run: yarn install 18 | 19 | - save_cache: 20 | paths: 21 | - node_modules 22 | key: v1-dependencies-{{ checksum "package.json" }} 23 | 24 | - run: yarn test 25 | 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea/enhancement for this project 4 | 5 | --- 6 | 7 | **Requirement** 8 | Clear and concise description of what the requirement is. What problem it is going to solve. 9 | 10 | **Tasks** 11 | Breakdown of feature in small chunks of work. Chunks which could be taken as one or separate PRs. 12 | 13 | **Additional context** 14 | Add any other context or screenshots about the feature request here. 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .DS_Store 3 | yarn-error.log 4 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Run Unit Tests In Current File", 11 | "program": "${workspaceFolder}/node_modules/jest/bin/jest.js", 12 | "cwd": "${workspaceFolder}", 13 | "args": [ 14 | "--config", 15 | "jest.config.js", 16 | "${relativeFile}" 17 | ], 18 | "outFiles": ["${workspaceFolder}/**/*.js", "!**/node_modules/**"] 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "git.ignoreLimitWarning": true 3 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Tanay Pratap 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Please provide enough information so that others can review your pull request: 2 | 3 | ## Motivation 4 | 5 | Explain the **motivation** for making this change. What existing problem does the pull request solve? Mention issue number if any. 6 | 7 | ## Test plan 8 | 9 | Demonstrate the code is solid. Example: the exact commands you ran and their output, screenshots / videos if the pull request changes UI. 10 | 11 | Make sure you test on Chrome and Firefox if your change affects UI. 12 | 13 | The code must pass tests. Also, add tests for your code. 14 | 15 | ## Code formatting 16 | 17 | Look around. Match the style of the rest of the codebase. Run `yarn format` before committing. 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Polaris 2018 2 | ============= 3 | Creating a scaffolding for full stack React with TypeScript (striving to put everything in TS), Apollo, GraphQL, Jest, Express, React Router and make them all work cohesively 4 | 5 | ### Vision 6 | This is a work in progress. Idea is to treat this as scaffolding for future projects. 7 | It will also be a learning of all these technologies in React Ecosystem. 8 | 9 | ### Technologies to be incorporated 10 | * [React 16.3](https://reactjs.org/) 11 | * [TypeScript (Both on client and server side)](https://www.typescriptlang.org/) 12 | * [React Router 4](https://reacttraining.com/react-router/) 13 | * [PostCSS for CSS](https://postcss.org/) 14 | * [Webpack 4](https://webpack.js.org/) 15 | * [Jest (React Testing)](https://jestjs.io/en/) 16 | * [Apollo](https://www.apollographql.com/) 17 | * [GraphQL](https://graphql.org/) 18 | * [Express](https://expressjs.com/) 19 | * [MongoDB](https://www.mongodb.com/) 20 | 21 | 22 | ### Running the client and server 23 | Currently client and server are two disjointed pieces. However, soon server will be serving the client in dev as well as in prod mode. 24 | For now, if you want to run server (which has no useful code), use `npm run start:server` at project root. 25 | The client is setup only for development currently, if you want to run it to see the output use `npm run start` at project root. 26 | 27 | ### Testing setup for Polaris 28 | 29 | Polaris uses Jest for server side testing and Jest & Enzyme to test the React components. To enable Jest with typescript, a jest config file is included in the root directory, where various options are set to suit the needs of the project. Besides, Enzyme is being used as it is an exclusive testing utility for React which makes it easier to assert and manipulate component's output, thereby making testing client side code less cumbersome. 30 | 31 | ### How to run tests 32 | 33 | `npm run test` - To run all the unit tests in client & server both. 34 | `npm run test:server` - To run only server unit tests 35 | `npm run test:client` - To run only client unit tests 36 | `npm run test:watch` - To run jest in watch mode 37 | 38 | To debug the individual tests, run the vscode debugger with `Run Unit Tests In Current File` configuration. 39 | 40 | ### How to add tests 41 | 42 | Add your test file in the following format [filename].spec.ts/tsx or [filename].test.ts/tsx in the __tests__ folder in **./client** for client side & in **./_server** for server side tests. A sample test file has been written in the corresponding folders. 43 | 44 | ### Documentation 45 | Separate folder is created for docs and all documentation related to a functionality/library/tech should go into proper folder. 46 | A link should be added here, for example: 47 | #### PWA 48 | 49 | * [Resources for making a React App PWA](./docs/pwa/resources.md) -------------------------------------------------------------------------------- /_server/__tests__/hello-world.test.ts: -------------------------------------------------------------------------------- 1 | import hello from "../api/hello-world"; 2 | 3 | const send = jest.fn(); 4 | const res = { 5 | send, 6 | }; 7 | 8 | test('Should call res.send() with Hello World!', () => { 9 | hello({} as any, res as any); 10 | expect(send.mock.calls).toHaveLength(1); 11 | expect(send.mock.calls[0][0]).toBe('Hello World!'); 12 | }); -------------------------------------------------------------------------------- /_server/__tests__/server.test.ts: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import { bootstrap } from "../server"; 3 | 4 | jest.mock("express", () => { 5 | return jest.fn().mockImplementation(() => { 6 | return { 7 | set: jest.fn(), 8 | get: jest.fn(), 9 | listen: jest.fn((_options, callback) => callback()) 10 | }; 11 | }); 12 | }); 13 | 14 | describe("Bootstraping server", () => { 15 | beforeEach(() => { 16 | (express as any).mockClear(); 17 | }) 18 | test("bootstrap through express", () => { 19 | bootstrap(); 20 | expect(express).toHaveBeenCalledTimes(1); 21 | }) 22 | }) -------------------------------------------------------------------------------- /_server/api/hello-world.ts: -------------------------------------------------------------------------------- 1 | import { Response, Request } from "express" 2 | 3 | export default (req: Request, res: Response) => res.send('Hello World!'); -------------------------------------------------------------------------------- /_server/index.ts: -------------------------------------------------------------------------------- 1 | import { bootstrap } from "./server"; 2 | 3 | bootstrap(); -------------------------------------------------------------------------------- /_server/server.ts: -------------------------------------------------------------------------------- 1 | import express from "express" 2 | import hello from "./api/hello-world"; 3 | 4 | export async function bootstrap () { 5 | const server = express() 6 | 7 | server.set('port', 6789) 8 | 9 | server.get('/hello', hello); 10 | 11 | server.listen(server.get('port'), () => { 12 | console.log(`Server is running at http://localhost:${server.get('port')} in ${server.get('env')} mode`) 13 | }) 14 | } -------------------------------------------------------------------------------- /client/__tests__/__snapshots__/subapp.spec.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`matches snapshot test with no props supplied 1`] = ` 4 |

5 | Hello 6 |

7 | `; 8 | -------------------------------------------------------------------------------- /client/__tests__/subapp.spec.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { SubApp } from "../app/components/subapp"; 3 | import { shallow } from "enzyme"; 4 | 5 | test("renders the heading with props supplied", () => { 6 | const result = shallow().contains( 7 |

Hello Polaris

8 | ); 9 | expect(result).toBeTruthy(); 10 | }); 11 | 12 | test("matches snapshot test with no props supplied", () => { 13 | const snap = shallow(); 14 | // Snapshot demo 15 | expect(snap).toMatchSnapshot(); 16 | }); 17 | -------------------------------------------------------------------------------- /client/app/app.tsx: -------------------------------------------------------------------------------- 1 | import React, { SFC } from "react"; 2 | import { Header } from "./components"; 3 | 4 | interface AppProps { 5 | className?: string; 6 | children: JSX.Element[]; 7 | } 8 | 9 | const appStyling = { 10 | paddingTop: "66px", 11 | fontSize: "1em", 12 | lineHeight: "1.4" 13 | }; 14 | 15 | export const App: SFC = (props: AppProps) => ( 16 |
17 |
18 |
{props.children}
19 |
20 | ); 21 | -------------------------------------------------------------------------------- /client/app/components/TestComponent.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | export const TestComponent = () => ( 4 |
This is just a TestComponent
5 | ) -------------------------------------------------------------------------------- /client/app/components/about.tsx: -------------------------------------------------------------------------------- 1 | import React, { SFC } from "react"; 2 | interface AboutProps { 3 | content?: string; 4 | } 5 | 6 | const pStyle = { 7 | fontSize: "20px", 8 | lineHeight: "1.4em" 9 | }; 10 | 11 | const divStyle = { 12 | padding: "1% 3%" 13 | }; 14 | 15 | export const About: SFC = (props: AboutProps) => ( 16 |
17 |

About

18 |

{props.content}

19 |
20 | ); 21 | 22 | About.defaultProps = { 23 | content: `About content here` 24 | }; 25 | -------------------------------------------------------------------------------- /client/app/components/error-page.tsx: -------------------------------------------------------------------------------- 1 | import React, { SFC } from "react"; 2 | interface ErrorPageProps { 3 | code: Number; 4 | message: string; 5 | } 6 | 7 | const flexDivStyle = { 8 | height: "calc(100% - 66px)", 9 | display: "flex", 10 | alignItems: "center", 11 | justifyContent: "center", 12 | margin: 0, 13 | padding: 0 14 | }; 15 | 16 | export const ErrorPage: SFC = (props: ErrorPageProps) => ( 17 |
18 |

19 | {props.code}: {props.message} 20 |

21 |
22 | ); 23 | 24 | ErrorPage.defaultProps = { 25 | code: 404, 26 | message: "This is not the page you are looking for" 27 | }; 28 | -------------------------------------------------------------------------------- /client/app/components/header.tsx: -------------------------------------------------------------------------------- 1 | import React, { SFC } from "react"; 2 | import { Link } from "react-router-dom"; 3 | 4 | const MENU_LINKS: Array = [ 5 | { link: "/", label: "Home" }, 6 | { link: "/about", label: "About" } 7 | ]; 8 | 9 | interface MenuItem { 10 | link: string; 11 | label: string; 12 | } 13 | 14 | interface NavbarProps { 15 | menu: Array; 16 | className?: string; 17 | } 18 | interface HeaderProps { 19 | className?: string; 20 | } 21 | 22 | const navbarStyle = { 23 | marginLeft: "50px" 24 | }; 25 | 26 | const navbarAStyle = { 27 | textDecoration: "none", 28 | color: "inherit", 29 | padding: "0 10px" 30 | }; 31 | 32 | const headerStyle = { 33 | left: 0, 34 | right: 0, 35 | height: "66px", 36 | lineHeight: "66px", 37 | color: "#ffffff", 38 | backgroundColor: "#24292e" 39 | }; 40 | 41 | // Basic components 42 | const Navbar: SFC = (props: NavbarProps) => ( 43 | 50 | ); 51 | 52 | export const Header: SFC = (props: HeaderProps) => ( 53 |
54 | 55 |
56 | ); 57 | -------------------------------------------------------------------------------- /client/app/components/home.tsx: -------------------------------------------------------------------------------- 1 | import React, { SFC } from "react"; 2 | interface HomeProps { 3 | projectName: string; 4 | } 5 | 6 | const flexDivStyle = { 7 | height: "calc(100% - 66px)", 8 | display: "flex", 9 | alignItems: "center", 10 | justifyContent: "center", 11 | margin: 0, 12 | padding: 0 13 | }; 14 | 15 | export const Home: SFC = props => ( 16 |
17 |

Hi ! Welcome onboard with project {props.projectName}!

18 |
19 | ); 20 | 21 | Home.defaultProps = { 22 | projectName: "Polaris" 23 | }; 24 | -------------------------------------------------------------------------------- /client/app/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./home"; 2 | export * from "./about"; 3 | export * from "./header"; 4 | export * from "./error-page"; 5 | -------------------------------------------------------------------------------- /client/app/components/subapp.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | interface SubAppProps { 4 | message: string 5 | } 6 | 7 | export class SubApp extends React.Component{ 8 | render(){ 9 | return( 10 |

Hello {this.props.message}

11 | ) 12 | } 13 | } -------------------------------------------------------------------------------- /client/app/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as ReactDOM from "react-dom"; 3 | import { AppRouter } from "./router"; 4 | 5 | ReactDOM.render(, document.getElementById("root")); 6 | -------------------------------------------------------------------------------- /client/app/router.tsx: -------------------------------------------------------------------------------- 1 | import React, { SFC } from "react"; 2 | import { Switch, BrowserRouter as Router, Route } from "react-router-dom"; 3 | import { Home, About, ErrorPage } from "./components"; 4 | import { App } from "./app"; 5 | 6 | export const AppRouter: SFC<{}> = () => ( 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 | ); 18 | -------------------------------------------------------------------------------- /client/public/img/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanaypratap/polaris/a5ebbdcf1a328cf25357141b672a701d95d3b045/client/public/img/icon-128.png -------------------------------------------------------------------------------- /client/public/img/icon-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanaypratap/polaris/a5ebbdcf1a328cf25357141b672a701d95d3b045/client/public/img/icon-256.png -------------------------------------------------------------------------------- /client/public/img/icon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanaypratap/polaris/a5ebbdcf1a328cf25357141b672a701d95d3b045/client/public/img/icon-48.png -------------------------------------------------------------------------------- /client/public/img/icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanaypratap/polaris/a5ebbdcf1a328cf25357141b672a701d95d3b045/client/public/img/icon-512.png -------------------------------------------------------------------------------- /client/public/img/icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanaypratap/polaris/a5ebbdcf1a328cf25357141b672a701d95d3b045/client/public/img/icon-72.png -------------------------------------------------------------------------------- /client/public/img/icon-96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanaypratap/polaris/a5ebbdcf1a328cf25357141b672a701d95d3b045/client/public/img/icon-96.png -------------------------------------------------------------------------------- /client/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 12 | Scaffolding for full stack React - Polaris 2018 | Opensource 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /client/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Polaris", 3 | "name": "Polaris 2018", 4 | "icons": [ 5 | { 6 | "src": "img/icon-48.png", 7 | "type": "image/png", 8 | "sizes": "48x48" 9 | }, 10 | { 11 | "src": "img/icon-72.png", 12 | "type": "image/png", 13 | "sizes": "72x72" 14 | }, 15 | { 16 | "src": "img/icon-96.png", 17 | "type": "image/png", 18 | "sizes": "96x96" 19 | }, 20 | { 21 | "src": "img/icon-128.png", 22 | "type": "image/png", 23 | "sizes": "128x128" 24 | }, 25 | { 26 | "src": "img/icon-256.png", 27 | "type": "image/png", 28 | "sizes": "256x256" 29 | }, 30 | { 31 | "src": "img/icon-512.png", 32 | "type": "image/png", 33 | "sizes": "512x512" 34 | } 35 | ], 36 | "start_url": "index.html", 37 | "background_color": "#E9B800", 38 | "display": "standalone", 39 | "scope": "/", 40 | "theme_color": "#00397F" 41 | } -------------------------------------------------------------------------------- /client/setupTests.ts: -------------------------------------------------------------------------------- 1 | import Enzyme from 'enzyme' 2 | import Adapter from 'enzyme-adapter-react-16' 3 | 4 | Enzyme.configure({ 5 | adapter: new Adapter(), 6 | }) -------------------------------------------------------------------------------- /client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ 5 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 6 | "lib": [ 7 | "dom", 8 | "es6" 9 | ], /* Specify library files to be included in the compilation. */ 10 | // "allowJs": true, /* Allow javascript files to be compiled. */ 11 | // "checkJs": true, /* Report errors in .js files. */ 12 | "jsx": "react", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 13 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 14 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 15 | "sourceMap": true, /* Generates corresponding '.map' file. */ 16 | // "outFile": "./", /* Concatenate and emit output to single file. */ 17 | // "outDir": "/", /* Redirect output structure to the directory. */ 18 | // "rootDir": "/", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 19 | // "composite": true, /* Enable project compilation */ 20 | // "removeComments": true, /* Do not emit comments to output. */ 21 | // "noEmit": true, /* Do not emit outputs. */ 22 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 23 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 24 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 25 | /* Strict Type-Checking Options */ 26 | "strict": true, /* Enable all strict type-checking options. */ 27 | "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 28 | "strictNullChecks": true, /* Enable strict null checks. */ 29 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 30 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 31 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 32 | "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 33 | /* Additional Checks */ 34 | "noUnusedLocals": true, /* Report errors on unused locals. */ 35 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 36 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 37 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 38 | /* Module Resolution Options */ 39 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 40 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 41 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 42 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 43 | // "typeRoots": [], /* List of folders to include type definitions from. */ 44 | // "types": [], /* Type declaration files to be included in compilation. */ 45 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 46 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 47 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 48 | /* Source Map Options */ 49 | // "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 50 | // "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */ 51 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 52 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 53 | /* Experimental Options */ 54 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 55 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 56 | }, 57 | "include": [ 58 | "app" 59 | ], 60 | "compileOnSave": false 61 | } -------------------------------------------------------------------------------- /client/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const createStyledComponentsTransformer = require("typescript-plugin-styled-components") 3 | .default; 4 | const styledComponentsTransformer = createStyledComponentsTransformer(); 5 | 6 | module.exports = { 7 | context: path.resolve(__dirname), 8 | entry: "./app/index.tsx", 9 | output: { 10 | path: __dirname + "/public", 11 | filename: "build/app.js", 12 | publicPath: "/" 13 | }, 14 | resolve: { 15 | extensions: [".ts", ".tsx", ".js"] 16 | }, 17 | devServer: { 18 | historyApiFallback: true 19 | }, 20 | module: { 21 | rules: [ 22 | { 23 | test: /\.tsx?$/, 24 | loader: "ts-loader", 25 | options: { 26 | getCustomTransformers: () => ({ 27 | before: [styledComponentsTransformer] 28 | }) 29 | } 30 | } 31 | ] 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /docs/how-to-add-routes.md: -------------------------------------------------------------------------------- 1 | # How to add routes 2 | 3 | To add Routes, you need to create a new component in _/app/components_ 4 | 5 | example: 6 | 7 | ``` 8 | // app/components/new-component.tsx 9 | import React, {SFC} from 'react'; 10 | interface NewComponentProps { 11 | name: string 12 | } 13 | export const NewComponent: SFC = (props: NewComponentProps) =>
Hello {props.name} !
14 | ``` 15 | 16 | ``` 17 | // app/components/index.ts 18 | ... 19 | export * from './new-component.tsx' 20 | ``` 21 | 22 | You then need to import it in the router component, and create a new route: 23 | 24 | ``` 25 | // app/router.tsx 26 | ... 27 | import { NewComponent } from './components'; 28 | ... 29 | 30 | export const AppRouter: SFC<{}> = () => ( 31 | 32 |
33 | 34 | 35 | // Other routes here 36 | 37 | 38 |
39 |
40 | ); 41 | ``` 42 | 43 | And you're done for the routing part ! If you want to add your route to the navbar, just add it to header.tsx and make sure the link you pass is the same as defined in the router component 44 | 45 | ``` 46 | // app/components/header.tsx 47 | 48 | const MENU_LINKS = [ 49 | // Other links here 50 | {link: "/new-route", label: "New Route"} 51 | ] 52 | 53 | ... 54 | ``` 55 | -------------------------------------------------------------------------------- /docs/index_README.md: -------------------------------------------------------------------------------- 1 | Polaris 2018 - index.html 2 | ========================= 3 | 4 | [meta name="viewport"](https://developer.mozilla.org/en-US/docs/Mozilla/Mobile/Viewport_meta_tag) 5 | Using the viewport meta tag to control layout on mobile browsers. 6 | 7 | [meta name = "description"](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta) 8 | A meta description (sometimes called a meta description attribute or tag) is an HTML element that describes and summarizes the contents of your page for the benefit of users and search engines. 9 | 10 | 11 | [The Open Graph Markup](http://ogp.me/) 12 | Most content is shared online as a URL, so it's important that you mark up your website with Open Graph tags to take control over how your content appears on shared sites. Supported social media includes Facebook, Google, twitter and many more 13 | 14 | * Mandatory Fields 15 | - [og:title](http://ogp.me/) 16 | The title of your article without any branding such as your site name. 17 | 18 | - [og:description](http://ogp.me/) 19 | A brief description of the content, usually between 2 and 4 sentences. This will displayed below the title of the post. 20 | 21 | - [og:image](http://ogp.me/) 22 | The URL of the image that appears when someone shares the content. 23 | 24 | - [og:url](http://ogp.me/) 25 | 26 | - [twitter:card](https://developer.twitter.com/en/docs/tweets/optimize-with-cards/guides/getting-started.html) 27 | The card type, which will be one of “summary”, “summary_large_image”, “app”, or “player”. 28 | 29 | * Recommended 30 | - [og:site_name](http://ogp.me/) 31 | If the shared page is part of a larger web site, the name which should be displayed for the overall site. 32 | 33 | - [twitter:image:alt](https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/summary.html) 34 | A text description of the image conveying the essential nature of an image to users who are visually impaired. Maximum 420 characters. 35 | 36 | * Required for facebook Analytics 37 | - [fb:app_id](https://developers.facebook.com/docs/sharing/opengraph/object-properties) 38 | In order to use Facebook Insights you must add the app ID to your page. Insights lets you view analytics for traffic to your site from Facebook. 39 | -------------------------------------------------------------------------------- /docs/pwa/resources.md: -------------------------------------------------------------------------------- 1 | Resources for making a React App PWA 2 | ==================================== 3 | 4 | [Push Notifications codelab](https://github.com/GoogleChromeLabs/web-push-codelab) 5 | Code lab from Google for Sending Push Notifications. 6 | 7 | [Service Workers: an Introduction](https://developers.google.com/web/fundamentals/primers/service-workers/) 8 | Only about service workers from Google 9 | 10 | [Progressive Web Apps Training](https://developers.google.com/web/ilt/pwa) 11 | There's an entire 20+ videos tutorial from Google on how to create and serve PWA. This must be the most exhaustive material there is on PWA. This even has analytics. 12 | 13 | [Using Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers) 14 | Mozilla's take on Using Service Wokers. Starts by explaining the basic concepts and then delve into making an image caching library using service workers. This will download images in advance. 15 | 16 | 17 | [Service Worker Cookbook](https://serviceworke.rs/) Need to explore this 18 | The Service Worker Cookbook is a collection of working, practical examples of using service workers in modern web sites. 19 | 20 | [Public URLs for exposing your local web server.](https://ngrok.com/) 21 | Testing your service worker in dev over HTTPS. Incredibly useful for other purposes as well. 22 | 23 | [Lighthouse](https://developers.google.com/web/tools/lighthouse/) 24 | Most important tool to audit and see if you're ready to release. Best thing is it has direct links to docs shown where there's an audit failure. 25 | Starts from here [Address Bar Theme Color](https://developers.google.com/web/tools/lighthouse/audits/address-bar) and then covers every subsequent audit point. 26 | 27 | [How Push Works](https://developers.google.com/web/fundamentals/push-notifications/) 28 | Everything you need to know about push notifications in web. This covers both web and PWA related push as both works using Service Worker only. 29 | 30 | [Service Workers an Introduction](https://developers.google.com/web/fundamentals/primers/service-workers/) 31 | Lifecycle and High Performance Loading of Service workers from Google. 32 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "roots": [ 3 | "/client", 4 | "/_server" 5 | ], 6 | "transform": { 7 | "^.+\\.tsx?$": "ts-jest" 8 | }, 9 | "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$", 10 | "moduleFileExtensions": [ 11 | "ts", 12 | "tsx", 13 | "js", 14 | "jsx", 15 | "json", 16 | "node" 17 | ], 18 | "setupTestFrameworkScriptFile": "/client/setupTests.ts", 19 | "snapshotSerializers": [ 20 | "enzyme-to-json/serializer" 21 | ], 22 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "polaris", 3 | "version": "1.0.0", 4 | "description": "The best in the react ecosystem", 5 | "main": "./lib/server.js", 6 | "repository": "https://github.com/tanaypratap/polaris-2018.git", 7 | "author": "Tanay Pratap", 8 | "license": "MIT", 9 | "private": true, 10 | "scripts": { 11 | "start": "webpack-dev-server -d --content-base ./client/public --config ./client/webpack.config.js", 12 | "start:server": "npm run build:watch", 13 | "build:server": "tsc", 14 | "build:watch": "nodemon --exec ./node_modules/.bin/ts-node -- ./_server/index.ts", 15 | "test": "jest", 16 | "test:server": "jest --roots=_server", 17 | "test:client": "jest --roots=client", 18 | "test:watch": "jest --watch" 19 | }, 20 | "dependencies": { 21 | "express": "^4.16.3", 22 | "react": "^16.4.1", 23 | "react-dom": "^16.4.1", 24 | "react-router-dom": "^4.3.1", 25 | "webpack": "^4.15.1", 26 | "webpack-cli": "^3.0.8", 27 | "webpack-dev-server": "^3.1.4" 28 | }, 29 | "devDependencies": { 30 | "@types/enzyme": "^3.1.14", 31 | "@types/enzyme-adapter-react-16": "^1.0.3", 32 | "@types/express": "^4.16.0", 33 | "@types/jest": "^23.3.3", 34 | "@types/node": "^10.5.2", 35 | "@types/react": "^16.4.6", 36 | "@types/react-dom": "^16.0.6", 37 | "@types/react-router-dom": "^4.3.1", 38 | "enzyme": "^3.7.0", 39 | "enzyme-adapter-react-16": "^1.6.0", 40 | "enzyme-to-json": "^3.3.4", 41 | "jest": "^23.6.0", 42 | "nodemon": "^1.17.5", 43 | "ts-jest": "^23.10.3", 44 | "ts-loader": "^4.4.2", 45 | "ts-node": "^7.0.0", 46 | "typescript": "^2.9.2", 47 | "typescript-plugin-styled-components": "^1.0.0" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /server/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const express_1 = __importDefault(require("express")); 7 | const server = express_1.default(); 8 | server.set('port', 6789); 9 | server.get('/', (req, res) => { 10 | res.send('Test Page Online'); 11 | }); 12 | server.listen(server.get('port'), () => { 13 | console.log(`Server is running at http://localhost:${server.get('port')} in ${server.get('env')} mode`); 14 | }); 15 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ 5 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 6 | // "allowJs": true, /* Allow javascript files to be compiled. */ 7 | "jsx": "react", 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 10 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 11 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 12 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 13 | // "outFile": "./", /* Concatenate and emit output to single file. */ 14 | "outDir": "server", /* Redirect output structure to the directory. */ 15 | "rootDir": "_server", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 16 | // "composite": true, /* Enable project compilation */ 17 | // "removeComments": true, /* Do not emit comments to output. */ 18 | // "noEmit": true, /* Do not emit outputs. */ 19 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 20 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 21 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 22 | 23 | /* Strict Type-Checking Options */ 24 | "strict": true, /* Enable all strict type-checking options. */ 25 | "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 26 | "strictNullChecks": true, /* Enable strict null checks. */ 27 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 28 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 29 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 30 | "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 31 | 32 | /* Additional Checks */ 33 | "noUnusedLocals": true, /* Report errors on unused locals. */ 34 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 35 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 36 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 37 | 38 | /* Module Resolution Options */ 39 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 40 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 41 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 42 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 43 | // "typeRoots": [], /* List of folders to include type definitions from. */ 44 | // "types": [], /* Type declaration files to be included in compilation. */ 45 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 46 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 47 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 48 | 49 | /* Source Map Options */ 50 | // "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 51 | // "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */ 52 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 53 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 54 | 55 | /* Experimental Options */ 56 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 57 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 58 | }, 59 | "include": [ 60 | "_server" 61 | ] 62 | } --------------------------------------------------------------------------------