diff --git a/.codeclimate.yml b/.codeclimate.yml
index 90ec5722..6dc0ff57 100644
--- a/.codeclimate.yml
+++ b/.codeclimate.yml
@@ -22,3 +22,5 @@ ratings:
- "**.jsx"
exclude_paths:
- node_modules/
+- .next/
+- .gitattributes
diff --git a/.yarnclean b/.yarnclean
new file mode 100644
index 00000000..25bdd148
--- /dev/null
+++ b/.yarnclean
@@ -0,0 +1,42 @@
+# test directories
+__tests__
+test
+tests
+powered-test
+
+# asset directories
+docs
+doc
+website
+images
+assets
+
+# examples
+example
+examples
+
+# code coverage directories
+coverage
+.nyc_output
+
+# build scripts
+Makefile
+Gulpfile.js
+Gruntfile.js
+
+# configs
+.tern-project
+.gitattributes
+.editorconfig
+.*ignore
+.eslintrc
+.jshintrc
+.flowconfig
+.documentup.json
+.yarn-metadata.json
+.*.yml
+*.yml
+
+# misc
+*.gz
+*.md
diff --git a/components/AuthFields/index.data.js b/components/AuthFields/index.data.js
new file mode 100644
index 00000000..e34b5b8c
--- /dev/null
+++ b/components/AuthFields/index.data.js
@@ -0,0 +1,53 @@
+import persist from '../../libraries/persist';
+
+// Actions Naming
+export const AUTH_SIGNIN = 'AUTH_SIGNIN';
+export const AUTH_SIGNOUT = 'AUTH_SIGNOUT';
+export const AUTH_SERVERERROR = 'AUTH_SERVERERROR';
+
+// Initial State
+const initialState = {
+ authenticated: false,
+ token: null,
+ error: null
+};
+
+// Reducer
+const reducer = (state = initialState, action) => {
+ switch (action.type) {
+ case AUTH_SIGNIN:
+ return {
+ ...state,
+ authenticated: true,
+ token: action.token,
+ error: null
+ };
+ case AUTH_SIGNOUT:
+ return { ...state, authenticated: false, token: null, error: null };
+ case AUTH_SERVERERROR:
+ return { ...state, authenticated: false, error: action.error };
+ default:
+ return state;
+ }
+};
+
+// Actions
+const actions = {};
+
+actions.signIn = token => ({ type: AUTH_SIGNIN, token });
+actions.signOut = () => ({ type: AUTH_SIGNOUT });
+
+// Discpatchers
+const dispatchers = {};
+
+dispatchers.signIn = token => {
+ persist.willSetAccessToken(token);
+ return actions.signIn(token);
+};
+
+dispatchers.signOut = () => {
+ persist.willRemoveAccessToken();
+ return actions.signOut();
+};
+
+export { actions, reducer, dispatchers };
diff --git a/components/AuthFields/index.gql.js b/components/AuthFields/index.gql.js
new file mode 100644
index 00000000..928d4bf4
--- /dev/null
+++ b/components/AuthFields/index.gql.js
@@ -0,0 +1,31 @@
+import { gql } from 'react-apollo';
+
+export default {};
+
+export const signIn = gql`
+ mutation signinUser($email: String!, $password: String!) {
+ signinUser(email: { email: $email, password: $password }) {
+ token
+ }
+ }
+`;
+
+export const createUser = gql`
+ mutation createUser(
+ $firstName: String!
+ $lastName: String!
+ $email: String!
+ $password: String!
+ ) {
+ createUser(
+ firstName: $firstName
+ lastName: $lastName
+ authProvider: { email: { email: $email, password: $password } }
+ ) {
+ id
+ }
+ signinUser(email: { email: $email, password: $password }) {
+ token
+ }
+ }
+`;
diff --git a/components/AuthFields/index.js b/components/AuthFields/index.js
new file mode 100644
index 00000000..bdfd3ba9
--- /dev/null
+++ b/components/AuthFields/index.js
@@ -0,0 +1,75 @@
+import React from 'react';
+import styled from 'styled-components';
+import PropTypes from 'prop-types';
+
+const AuthFields = props => {
+ const {
+ selectFields,
+ fields,
+ handleTouch,
+ handleChange,
+ handleSubmit,
+ touched,
+ errors
+ } = props;
+ const mapFields = fields.map(field =>
+
+
+ {errors &&
+
+ {errors[field.attr.name]}
+
}
+
+ );
+ const authMethod =
+ (selectFields === 'signinFields' && 'Sign In') || 'Sign Up';
+ return (
+
+
+ {authMethod}
+
+
+
+ );
+};
+
+AuthFields.propTypes = {
+ selectFields: PropTypes.string.isRequired,
+ fields: PropTypes.array.isRequired,
+ handleTouch: PropTypes.func.isRequired,
+ handleChange: PropTypes.func.isRequired,
+ handleSubmit: PropTypes.func.isRequired,
+ touched: PropTypes.bool.isRequired,
+ errors: PropTypes.object.isRequired
+};
+
+export default styled(AuthFields)`
+ border-bottom: 1px solid #ececec;
+ padding-bottom: 20px;
+ margin-bottom: 20px;
+
+ > h1 {
+ font-size: 20px;
+ }
+
+ >input {
+ display: block;
+ margin-bottom: 10px;
+ }
+`;
diff --git a/components/AuthFields/index.validation.js b/components/AuthFields/index.validation.js
new file mode 100644
index 00000000..0ece39cd
--- /dev/null
+++ b/components/AuthFields/index.validation.js
@@ -0,0 +1,28 @@
+import { isStringEmpty, isEmail } from '../../libraries/validations';
+
+export default values => {
+ const errors = {};
+ const touched = true;
+
+ if (isStringEmpty(values.firstName)) {
+ errors.firstName = 'Required';
+ }
+
+ if (isStringEmpty(values.lastName)) {
+ errors.lastName = 'Required';
+ }
+
+ if (isStringEmpty(values.email)) {
+ errors.email = 'Required';
+ } else if (!isEmail(values.email)) {
+ errors.email = 'Invalid email address';
+ }
+
+ if (isStringEmpty(values.password)) {
+ errors.password = 'Required';
+ } else if (values.password.length <= 3) {
+ errors.password = 'Must be at least 4 characters';
+ }
+
+ return { errors, touched };
+};
diff --git a/components/Header.js b/components/Header.js
deleted file mode 100644
index 44ce447b..00000000
--- a/components/Header.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import PropTypes from 'prop-types';
-import styled from 'styled-components';
-import LinkList from './LinkList';
-
-const Header = ({ className, pathname }) =>
- ;
-
-Header.propTypes = {
- pathname: PropTypes.string.isRequired,
- className: PropTypes.string.isRequired
-};
-
-export default styled(Header)`
- margin-bottom: 25px;
-`;
diff --git a/components/Header/index.data.js b/components/Header/index.data.js
new file mode 100644
index 00000000..8765d61c
--- /dev/null
+++ b/components/Header/index.data.js
@@ -0,0 +1,14 @@
+import { connect } from 'react-redux';
+import { actions } from '../SignInForm/index.data';
+
+const mapStateToProps = state => ({
+ authenticated: state.auth.authenticated
+});
+
+const mapDispatchToProps = dispatch => ({
+ logout() {
+ dispatch(actions.signout());
+ }
+});
+
+export default comp => connect(mapStateToProps, mapDispatchToProps)(comp);
diff --git a/components/Header/index.js b/components/Header/index.js
new file mode 100644
index 00000000..c6092f67
--- /dev/null
+++ b/components/Header/index.js
@@ -0,0 +1,28 @@
+import PropTypes from 'prop-types';
+import styled from 'styled-components';
+import LinkList from '../LinkList';
+import connect from './index.data';
+
+const Header = ({ className, pathname, authenticated, logout }) =>
+ ;
+
+Header.defaultProps = {
+ authenticated: false
+};
+
+Header.propTypes = {
+ pathname: PropTypes.string.isRequired,
+ className: PropTypes.string.isRequired,
+ authenticated: PropTypes.bool.isRequired,
+ logout: PropTypes.func.isRequired
+};
+
+export default connect(styled(Header)`
+ margin-bottom: 25px;
+`);
diff --git a/components/LinkList.js b/components/LinkList.js
index 1081fb1b..b0aed5ac 100644
--- a/components/LinkList.js
+++ b/components/LinkList.js
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import styled from 'styled-components';
import { Router } from '../routes';
-const LinkList = ({ className, pathname }) =>
+const LinkList = ({ className, pathname, authenticated, logout }) =>