Github search, modern web app
This small application allows searches using the Github v4 API (GraphQL), displays the user information and his repositories.
Stack: Typescript, React, GraphQL with Apollo Client and Redux, and Jest for tests.
✅ Live version: github-search-react.netlify.com
Roadmap:
- Display search UI and results page with data fetched from Github API
- Dynamic Themes (changes CSS theme on demand through UI option) using native CSS variables
- Multilingual support (EN | BR | ES)
- Fully responsive, without frameworks (using native flexbox CSS)
- Progresive web app
- Add CI service to run tests (Travis CI)
- Use guides for accessibility (WAI-ARIA standard)
- Use animations, page transitions, and elements
- Store user settings on localStorage (to keep the settings even if the page refreshes)
Main future improvements
- Add a significant amount of tests and improve the quality of existing tests (for now, only tests components mount with react-dom, react-router, and Jest)
- Move all user settings to Redux store (lang, themes)
- Use styled-components themes instead of native CSS variables
- Write a Docker file to deploy in own servers (no netlify-like integrations)
Good practices
- Use Eslint (code linter with support for Typescript)
- Prettier (code formatting) with a Pre-Commit hook (git)
- Semantic Commit Messages
Installation
Create .env
file with your Github Token, this token is required by Github GraphQL API. (more information about token here)
REACT_APP_GITUHB_API_TOKEN=___YOUR_TOKEN_HERE___
After that, in the project directory, run:
npm install
this command will install all needed project dependencies
Available commands (after installation)
In the project directory, you can run:
npm start
Runs the app in the development mode.
Open http://localhost:3000 to view it in the browser.
The page will reload if you make edits.
You will also see any lint errors in the console.
npm test
Launches the test runner in the interactive watch mode.
See the section about running tests for more information.
npm run build
Builds the app for production to the build
folder.
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.
Your app is ready to be deployed!
Project structure
This project was bootstrapped with Create React App, and the main structure is proposed by this boilerplate, also, as a component strategy use "atomic design pattern" where the main goal is divide into differents component as is possible, finding a balance between coupling and cohesion.
├── App.tsx
├── assets
├── common
│ ├── Logo
│ │ └── index.tsx
│ ├── Search
│ │ ├── Button.tsx
│ │ ├── Input.tsx
│ └── index.tsx
├── config.tsx
├── index.tsx
├── pages
│ ├── home
│ └── results
│ ├── components
│ │ ├── Avatar.tsx
│ │ ├── Info.tsx
│ │ ├── Result.tsx
│ │ ├── Sidebar.tsx
│ │ └── index.tsx
│ └── index.tsx
├── react-app-env.d.ts
├── serviceWorker.ts
└── styles
└── index.scss
Each component folder contains a directory called __tests__
where test files are located with .test.tsx suffix.
Main directories are: common
with shared components around de app. pages
that contain two main pages components (home and results), each directory has a components folder with local comps. The main internal configuration is located on src/config.tsx
where you can see some constants and static configuration. About the styles, the local CSS live in each component, but in the file styles/index.scss
you can found global CSS variables and html/fonts/global layout styles.
GraphQL approach
One of the main advantages of using GraphQL is the declarative way in how we write the queries to the server, for this example application, the query groups the user information and its repositories using the username, type and order parameters as variables (example: direction DESC on stars) (located on: src/pages/results/github-user.graphql
)
query SearchReposByUser($login: String!, $queryString: String!, $pageSize: Int!) {
search(query: $queryString, type: REPOSITORY, first: $pageSize) {
edges {
node {
... on Repository {
name
description
url
stargazers(orderBy: { field: STARRED_AT, direction: DESC }) {
totalCount
}
}
}
}
}
user(login: $login) {
name
login
organization(login: $login) {
name
}
avatarUrl
location
starredRepositories {
totalCount
}
repositories {
totalCount
}
followers {
totalCount
}
}
}
Architecture
Because the control of the local state in apollo client is still incipient, and when projects grow too much it becomes complex to manage the state of the application, this proposal includes the use of a redux store for internal state management, using all the advantages that this implies.
On the other hand using the advantages of GraphQL and the cache of apollo client in each query.
This configuration allows passing values from the Apollo store to redux, using a serializing layer that will keep the container component (data handler) agnostic of data fetching by means of a stateless component.
In the future, the challenge will be to keep the Apollo cache updated with the Redux store automatically.
+---------------------+
| Apollo Client |
| +-----------------+ |
| | | |
| | Redux | |
| | | |
| +-----------------+ |
| |
+---------------------+
With this approach, you can use redux devs tools to interact with the application state, in this example, we see the user info and results as a graph.
Conventions
- Semantic Commit Messages
- Semantic versioning
- Gitflow, as a git strategy
- Changelog [Standard Version]
Changelog
All notable changes to this project will be documented in this file. See standard-version for commit guidelines.
1.3.0 (2019-11-18)
Features
- update manifiest.json (0bb0995)
Bug Fixes
- update translation ES
1.2.0 (2019-11-17)
Features
- add :hover style over button (8b5623c)
- add 'connected-react-router' to manage routes as value on redux store (d253fcf)
- add basic redux implementation (d5c3d2b)
- add graphql.macro to load .graphql files. This change adds best readability (76e7f5f)
- add mapStateToProps to results page component (72475f3)
- add UserInfo reducer and store data from fetch GraphQL Hook (3d0c300)
- display data from redux store, remove values directly from graphql query component (0576679)
- improve components file structure (a1cab67)
- improve Redux implementation. Add data from GraphQL fetch Hook (bd752c7)
Bug Fixes
- set right current lang value (65e9f34)