Skip to content

Commit

Permalink
Merge pull request #18 from tylercrosse/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
tylercrosse authored Mar 14, 2017
2 parents bca8590 + b5afe5a commit 6a90057
Show file tree
Hide file tree
Showing 47 changed files with 1,706 additions and 411 deletions.
99 changes: 86 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,89 @@
# gitter-clone
# Gitter-clone
[![Build Status](https://semaphoreci.com/api/v1/tcrosse/gitter-clone/branches/master/badge.svg)](https://semaphoreci.com/tcrosse/gitter-clone)
[![codecov](https://codecov.io/gh/tylercrosse/gitter-clone/branch/master/graph/badge.svg)](https://codecov.io/gh/tylercrosse/gitter-clone)

Portfolio Project clone of gitter.im -- Hire me!

Built with:
- react
- redux
- jest
- webpack
- babel
- express
- mongodb
- semaphore
- digital ocean
<div align="center">
</div>

This is app was built as portfolio piece representing a subset of the features of Troupe Technology's wonderful chat app, [Gitter](https://gitter.im/). I'm currently looking for a new position - Hire me!

---
### Demo

You can test a fully working live demo at http://138.68.24.248:3333/

---
### Major features

- MD / syntax highlighting support for messages
- Messages grouped into bursts
- Create Channels
- Load previous messages in channel
- Send Messages to all subscribed clients on channel

---
### Built with

##### <img height="20" src="https://cdn.rawgit.com/tylercrosse/gitter-clone/assets/src/client/assets/img/react.svg"> [React](https://facebook.github.io/react/)

React makes it really easy to focus on the view in a declarative way. I like that it makes it easy to write composable, testable UI. Routing is handled by [react router](https://reacttraining.com/react-router/).

##### <img height="20" src="https://cdn.rawgit.com/tylercrosse/gitter-clone/assets/src/client/assets/img/redux.svg"> [Redux](http://redux.js.org/)

Redux is where the fun is at. Maintain a flat minimal state, with dictionary of normalized objects. I use [reselect](https://github.com/reactjs/reselect) to compute derived data. [Redux devtools](https://github.com/zalmoxisus/redux-devtools-extension) are also great, I kept it enabled on production for anyone wanting to easily take a look at the app's state.

##### <img height="20" src="https://cdn.rawgit.com/tylercrosse/gitter-clone/assets/src/client/assets/img/webpack.svg"> [Webpack 2](https://webpack.js.org/)

Fantastic code bundler once you get past the learning curve. I use it for a number of things including: transpile ES2015+ javascript to ES5 with [Babel](https://babeljs.io/), compile [Sass](http://sass-lang.com/) into css, optimize assets, hot reload code, build minimized split production code, + more.

##### <img height="20" src="https://cdn.rawgit.com/tylercrosse/gitter-clone/assets/src/client/assets/img/express.svg"> [Express](https://expressjs.com/)

It's nice to have JS everywhere. Express is fast and minimal. The backend is pretty simple with a router, a few controllers, and basic db interactions. Logging handled by [winston](https://github.com/winstonjs/winston).

##### <img height="20" src="https://cdn.rawgit.com/tylercrosse/gitter-clone/assets/src/client/assets/img/mongodb.svg"> [MongoDB](https://www.mongodb.com/)

This project doesn't currently require a ton of data persistence. MongoDB + [Mongoose](http://mongoosejs.com/) make it easy to quickly update the Schema. If the project continues to grow I will probably switch to a relational DB. Also Mongo is still trendy.

##### <img height="20" src="https://cdn.rawgit.com/tylercrosse/gitter-clone/assets/src/client/assets/img/jest.svg"> [Jest](http://facebook.github.io/jest/)

Unit tests run by Jest. If you haven't seen Jest recently, you should take another look. [Enzyme](https://github.com/airbnb/enzyme) is used for React support and [SuperTest](https://github.com/visionmedia/supertest) is used for HTTP assertions. [Enzyme-to-JSON](https://github.com/adriantoine/enzyme-to-json) is also great and worth checking out in conjunction with the other test utilities.

##### <img height="20" src="https://cdn.rawgit.com/tylercrosse/gitter-clone/assets/src/client/assets/img/semaphor.svg"> [SemaphoreCI](https://semaphoreci.com/)

Continuous integration handled by the super fast SemaphoreCI. Passing merges to master are auto deployed with help from [pm2](http://pm2.keymetrics.io/).

##### <img height="20" src="https://cdn.rawgit.com/tylercrosse/gitter-clone/assets/src/client/assets/img/digitalocean.svg"> [Digital Ocean](https://www.digitalocean.com/)

Application hosted on Ubuntu Digital Ocean droplet. SSH is fun!

---
### Setup

If you don't have [yarn](https://yarnpkg.com/en/) commands can be run with `npm`. First, clone and cd into the repo and install the dependencies.

```sh
$ git clone https://github.com/tylercrosse/gitter-clone.git
$ cd gitter-clone
$ yarn install
```

Additional commands:
##### `yarn dev`
- Start development server on `127.0.0.1:3333`

##### `yarn build`
- Build a production version of the app.

##### `yarn start`
- Start production server on `127.0.0.1:3333` to serve built app. Requires the build command to have already been run.

##### `yarn test`
- Run all of the projects tests using jest.

##### `yarn lint`
- Lint all of the projects javascript files using eslint.

---
### Contributing

Thank you for your interest! Unfortunately, I'm not currently taking contributions.
10 changes: 10 additions & 0 deletions config/sw-precache.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module.exports = {
stirpPrefix: '/static/dist/',
// replacePrefix: '/dist/',
staticFileGlobs: [
'static/dist/manifest.json',
'static/dist/**.js',
'static/dist/**.min.css',
],
swFilePath: 'static/dist/serviceWorker.js'
};
41 changes: 41 additions & 0 deletions config/webpack.config.base.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const path = require('path');
const webpack = require('webpack');

module.exports = {
output: {
path: path.resolve(__dirname, '../static/dist'),
filename: '[name].js',
publicPath: '/dist/'
},
resolve: {
extensions: ['.js', '.jsx', '.json', '.scss']
},
plugins: [
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new webpack.optimize.CommonsChunkPlugin({
names: ['vendor', 'manifest'],
minChunks: Infinity
})
],
module: {
loaders: [
// Images
// Inline base64 URLs for <=8k images, direct URLs for the rest
{
test: /\.(png|jpg|jpeg|gif|svg)$/,
loader: 'url-loader',
query: {
limit: 8192,
}
},
// Fonts
{
test: /\.(woff|woff2|ttf|eot)(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url-loader',
query: {
limit: 8192,
}
}
]
}
};
94 changes: 94 additions & 0 deletions config/webpack.config.dev.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
const path = require('path');
const webpack = require('webpack');
const merge = require('webpack-merge');
const config = require('./webpack.config.base');

module.exports = merge(config, {
devtool: 'source-map',
entry: {
application: [
'babel-polyfill',
'webpack-hot-middleware/client',
'./src/client/index.js'
],
vendor: [
'moment',
'normalizr',
'react',
'react-dom',
'react-modal',
'react-router',
'react-scroll',
'react-redux',
'react-router-redux',
'redux',
'redux-thunk',
'redux-api-middleware',
'redux-socket.io',
'reselect',
'socket.io-client',
]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development')
}
})
],
module: {
loaders: [
{
test: /\.(js|jsx)?$/,
loader: 'babel-loader',
query: {
plugins: [
[
'react-transform', {
transforms: [
{
transform: 'react-transform-hmr',
imports: ['react'],
locals: ['module']
}, {
transform: 'react-transform-catch-errors',
imports: ['react', 'redbox-react']
}
]
}
]
]
},
include: [path.resolve(__dirname, '../src')]
}, {
// test: /\.css?$/,
// loaders: ['style-loader', 'raw-loader']
// }, {
test: /\.scss$/,
loaders : [
{
loader: 'style-loader'
}, {
loader: 'css-loader',
}, {
loader: 'postcss-loader',
options: {
plugins() {
return [
require('autoprefixer')
]
}
}
}, {
loader: 'resolve-url-loader'
}, {
loader: 'sass-loader',
options: {sourceMap: true}
}
]
}
]
}
});
102 changes: 102 additions & 0 deletions config/webpack.config.prod.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const path = require('path');
const webpack = require('webpack');
const merge = require('webpack-merge');
const CleanPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const config = require('./webpack.config.base');

module.exports = merge(config, {
devtool: 'cheap-module-source-map',
entry: {
application: ['./src/client/index'],
vendor: [
'moment',
'normalizr',
'react',
'react-dom',
'react-modal',
'react-router',
'react-scroll',
'react-redux',
'react-router-redux',
'redux',
'redux-thunk',
'redux-api-middleware',
'redux-socket.io',
'reselect',
'socket.io-client',
]
},
plugins: [
new CleanPlugin(['../static/dist'], {verbose: true}),
new CopyWebpackPlugin([
{
from: path.join(__dirname, '../src/client/manifest.json'),
to: 'manifest.json'
}
]),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production')
}
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
'screw_ie8': true
},
output: {
comments: false
},
sourceMap: false
}),
new webpack.LoaderOptionsPlugin({
minimize: true,
debug: false
}),
new ExtractTextPlugin({
filename: 'style.min.css',
allChunks: true
}),
// new BundleAnalyzerPlugin()
],
module: {
noParse: /\.min\.js$/,
loaders: [
{
test: /\.(js|jsx)?$/,
use: 'babel-loader',
include: [path.resolve(__dirname, '../src')]
}, {
test: /\.css?$/,
loaders: ['style-loader', 'raw-loader']
}, {
test: /\.scss$/,
loader: ExtractTextPlugin.extract({
fallbackLoader: 'style-loader',
use: [
{
loader: 'css-loader',
}, {
loader: 'postcss-loader',
options: {
plugins() {
return [
require('autoprefixer')
]
}
}
}, {
loader: 'resolve-url-loader'
}, {
loader: 'sass-loader',
options: {sourceMap: true}
}
]
})
}
]
}
});
Loading

0 comments on commit 6a90057

Please sign in to comment.