├── .editorconfig ├── .env.development ├── .env.production ├── .eslintrc.json ├── .gitattributes ├── .github └── workflows │ └── dev.yml ├── .gitignore ├── .lintstagedrc.js ├── .mailmap ├── .nvmrc ├── .prettierignore ├── .prettierrc.json ├── .vscode └── launch.json ├── .yarnrc ├── ci └── commit-msg.mjs ├── docs ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── architecture-decisions.md ├── commit-convention.md └── review-criteria.md ├── etl ├── .gitignore ├── address-main.jq ├── api-main.mjs ├── fridge-cfm.jq ├── fridge-nyc.jq ├── geoapify-location-invalid.pat ├── geoapify.jq ├── input │ ├── cfm.kml │ └── nyc.json ├── main-api.jq ├── output │ └── api.json ├── process.md ├── table │ └── main.json └── tagsFrom-cfm.jq ├── jest.config.js ├── jsconfig.json ├── mock ├── fake-data.json ├── img │ ├── food.webp │ └── fridge.webp ├── server-routes.json └── src │ └── create-reports.mjs ├── next.config.js ├── package.json ├── public ├── brand │ ├── favicon │ │ └── favicon-32x32.png │ └── logo.webp ├── card │ ├── paragraph │ │ ├── apple.svg │ │ ├── jumpingBlueberries.svg │ │ ├── pearTomatoAndFridge.svg │ │ └── plumAndFridge.svg │ └── title │ │ ├── becomeDriver.svg │ │ ├── donate.svg │ │ ├── joinCommunity.svg │ │ ├── serviceFridge.svg │ │ ├── sourceFood.svg │ │ └── startFridge.svg ├── favicon.ico ├── feedback │ ├── emailError.svg │ ├── emailSuccess.svg │ └── happyFridge.svg ├── hero │ ├── about.webp │ ├── become_a_driver.webp │ ├── best_practices.webp │ ├── donate_to_a_fridge.webp │ ├── get-involved.webp │ ├── index.webp │ ├── join_a_community_group.webp │ ├── service_fridges.webp │ ├── source_food.webp │ └── start_a_fridge.webp └── paragraph │ └── pamphlet │ └── about │ ├── collective_focus.webp │ ├── independence_for_each_fridge.webp │ ├── public_art_installation_on_our_sidewalks.webp │ └── technology_empowers_us.webp ├── src ├── components │ ├── atoms │ │ ├── ButtonLink │ │ │ ├── ButtonLink.jsx │ │ │ └── index.js │ │ ├── FeedbackCard │ │ │ ├── FeedbackCard.jsx │ │ │ └── index.js │ │ ├── MapToggle │ │ │ ├── MapToggle.jsx │ │ │ └── index.js │ │ ├── NextLink │ │ │ ├── NextLink.jsx │ │ │ └── index.js │ │ ├── PageFooter │ │ │ ├── PageFooter.jsx │ │ │ └── index.js │ │ ├── PageHero │ │ │ ├── PageHero.jsx │ │ │ └── index.js │ │ ├── PamphletParagraph │ │ │ ├── PamphletParagraph.jsx │ │ │ └── index.js │ │ ├── ParagraphCard │ │ │ ├── ParagraphCard.jsx │ │ │ └── index.js │ │ ├── TitleCard │ │ │ ├── TitleCard.jsx │ │ │ └── index.js │ │ └── index.js │ ├── molecules │ │ ├── AppBar │ │ │ ├── AppBar.jsx │ │ │ └── index.js │ │ ├── Backtrack │ │ │ ├── Backtrack.jsx │ │ │ └── index.js │ │ ├── FridgeInformation │ │ │ ├── FridgeInformation.jsx │ │ │ └── index.js │ │ └── index.js │ └── organisms │ │ ├── browse │ │ ├── List.jsx │ │ ├── Map.jsx │ │ ├── components │ │ │ ├── LegendDrawer.jsx │ │ │ ├── MapMarkerList.jsx │ │ │ └── SearchMap.jsx │ │ └── model │ │ │ └── markersFrom.js │ │ ├── dialog │ │ └── components │ │ │ ├── PanelConfirm.jsx │ │ │ ├── PanelFridge.jsx │ │ │ ├── PanelMaintainer.jsx │ │ │ ├── PanelNotes.jsx │ │ │ └── PanelReport.jsx │ │ └── index.js ├── lib │ ├── analytics.js │ ├── browser.js │ ├── createEmotionCache.js │ ├── data.js │ ├── format.js │ ├── format.test.js │ ├── geo.mjs │ └── search.mjs ├── model │ ├── data │ │ └── fridge │ │ │ ├── REST.yaml │ │ │ ├── prop-types.js │ │ │ └── yup.mjs │ └── view │ │ ├── component │ │ └── prop-types.js │ │ ├── dialog │ │ └── yup.js │ │ ├── index.js │ │ └── prop-types.js ├── pages │ ├── _app.js │ ├── _document.js │ ├── browse.jsx │ ├── demo │ │ └── styles.jsx │ ├── fridge │ │ └── [id].jsx │ ├── index.jsx │ ├── pamphlet │ │ ├── about.jsx │ │ ├── best-practices.jsx │ │ ├── get-involved.jsx │ │ └── get-involved │ │ │ ├── become-a-driver.jsx │ │ │ ├── donate-to-a-fridge.jsx │ │ │ ├── join-a-community-group.jsx │ │ │ ├── service-fridges.jsx │ │ │ ├── source-food.jsx │ │ │ └── start-a-fridge.jsx │ └── user │ │ ├── contact.jsx │ │ └── fridge │ │ ├── add.jsx │ │ └── report.jsx └── theme │ ├── icons.js │ ├── index.js │ ├── palette.js │ └── typography.js ├── svgo.config.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | NEXT_PUBLIC_FF_API_URL=http://127.0.0.1:3050 2 | NEXT_PUBLIC_FLAG_useLocalDatabase=1 3 | NEXT_PUBLIC_ANALYTICS_ID=G-4H99PPWYCC 4 | -------------------------------------------------------------------------------- /.env.production: -------------------------------------------------------------------------------- 1 | NEXT_PUBLIC_FF_API_URL=https://api-prod.communityfridgefinder.com 2 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "node": true 6 | }, 7 | "extends": ["next/core-web-vitals", "prettier"], // prettier has to be last 8 | "rules": { 9 | "no-restricted-imports": [ 10 | "error", 11 | { 12 | "paths": [ 13 | { 14 | "name": "@emotion/styled", 15 | "message": "Please use MUI/System instead." 16 | }, 17 | { 18 | "name": "@mui/material/styles", 19 | "importNames": ["styled"], 20 | "message": "Please use MUI/System instead." 21 | } 22 | ], 23 | "patterns": ["@mui/*/*/*", "!@mui/material/test-utils/*"] 24 | } 25 | ], 26 | "react/prop-types": "warn" 27 | }, 28 | "settings": { 29 | "react": { 30 | "version": "detect" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf -------------------------------------------------------------------------------- /.github/workflows/dev.yml: -------------------------------------------------------------------------------- 1 | name: Continuous Integration 2 | 3 | on: 4 | push: 5 | branches: 6 | - dev 7 | pull_request: 8 | branches: [dev] 9 | 10 | jobs: 11 | Install_Dependencies: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v3 15 | - uses: actions/setup-node@v3 16 | with: 17 | node-version: "19" 18 | cache: "yarn" 19 | 20 | - name: Get yarn cache directory path 21 | id: yarn-cache-dir-path 22 | run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT 23 | 24 | - name: Cache Yarn dependencies 25 | uses: actions/cache@v3 26 | id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) 27 | with: 28 | path: node_modules 29 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 30 | 31 | - name: Install dependencies 32 | if: steps.yarn-cache.outputs.cache-hit != 'true' 33 | run: yarn install 34 | continue-on-error: false 35 | 36 | Run_Build: 37 | needs: 38 | - Install_Dependencies 39 | runs-on: ubuntu-latest 40 | steps: 41 | - uses: actions/checkout@v3 42 | - uses: actions/setup-node@v3 43 | with: 44 | node-version-file: ".nvmrc" 45 | cache: "yarn" 46 | 47 | - name: Cache Yarn Dependencies 48 | uses: actions/cache@v3 49 | with: 50 | path: node_modules 51 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 52 | 53 | - name: Run Build 54 | run: | 55 | yarn build 56 | 57 | Run_Test: 58 | needs: 59 | - Install_Dependencies 60 | runs-on: ubuntu-latest 61 | steps: 62 | - uses: actions/checkout@v3 63 | - uses: actions/setup-node@v3 64 | with: 65 | node-version-file: ".nvmrc" 66 | cache: "yarn" 67 | 68 | - name: Cache Yarn Dependencies 69 | uses: actions/cache@v3 70 | with: 71 | path: node_modules 72 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 73 | 74 | - name: Run Tests 75 | run: | 76 | yarn test 77 | 78 | Run_Lint: 79 | needs: 80 | - Install_Dependencies 81 | runs-on: ubuntu-latest 82 | steps: 83 | - uses: actions/checkout@v3 84 | - uses: actions/setup-node@v3 85 | with: 86 | node-version-file: ".nvmrc" 87 | cache: "yarn" 88 | 89 | - name: Cache Yarn Dependencies 90 | uses: actions/cache@v3 91 | with: 92 | path: node_modules 93 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 94 | 95 | - name: Run Lint 96 | run: | 97 | yarn lint 98 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # mac os 2 | .DS_Store 3 | 4 | # dependencies 5 | /node_modules 6 | 7 | # testing 8 | /coverage 9 | 10 | # next.js 11 | /.next/ 12 | /out/ 13 | 14 | # production 15 | /build 16 | 17 | # debug 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | .pnpm-debug.log* 22 | 23 | # local env files 24 | .env*.local 25 | 26 | # git backups 27 | *.orig 28 | 29 | # mock server 30 | /mock/fake-data.json 31 | 32 | # editor 33 | /.vscode/ 34 | !/.vscode/launch.json 35 | -------------------------------------------------------------------------------- /.lintstagedrc.js: -------------------------------------------------------------------------------- 1 | console.log('Running "yarn style" on commit files. Please wait...'); 2 | 3 | module.exports = { 4 | '*': ['prettier --write --ignore-unknown'], 5 | '*.svg': ['svgo --quiet'], 6 | }; 7 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Ioana Tiplea 2 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v19.8.1 -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # next.js 2 | /.next/ 3 | /out/ 4 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "printWidth": 80, 4 | "semi": true, 5 | "singleQuote": true, 6 | "trailingComma": "es5", 7 | "overrides": [ 8 | { 9 | "files": ["*.yml"], 10 | "options": { 11 | "singleQuote": false 12 | } 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "CFM: API+Next+Browser", 6 | "type": "node-terminal", 7 | "request": "launch", 8 | "command": "yarn dev", 9 | "serverReadyAction": { 10 | "pattern": "started server on .+, url: http://localhost:([0-9]+)", 11 | "uriFormat": "http://localhost:%s", 12 | "action": "debugWithChrome" 13 | } 14 | }, 15 | { 16 | "name": "CFM: Browser", 17 | "type": "pwa-chrome", 18 | "request": "launch", 19 | "url": "http://localhost:4000" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /.yarnrc: -------------------------------------------------------------------------------- 1 | network-timeout 500000 -------------------------------------------------------------------------------- /ci/commit-msg.mjs: -------------------------------------------------------------------------------- 1 | // Invoked on the commit-msg git hook by simple-git-hooks. 2 | 3 | import { readFileSync } from 'fs'; 4 | import colors from 'picocolors'; 5 | 6 | // get $1 from commit-msg script 7 | const msgFilePath = process.argv[2]; 8 | const msgFileContents = readFileSync(msgFilePath, 'utf-8'); 9 | const commitTitle = msgFileContents.split(/\r?\n/)[0]; 10 | 11 | const commitRE = 12 | /^(revert: )?(feat|fix|refactor|test|perf|style|asset|doc|ci|chore|wip)(\(.+\))?: [A-Z].{1,68}[^.]$/; 13 | 14 | if (!commitRE.test(commitTitle)) { 15 | console.log(); 16 | console.error( 17 | ` ${colors.bgRed(colors.white(' ERROR '))} ${colors.white( 18 | `Invalid commit title format or length.` 19 | )}\n\n` + 20 | colors.white( 21 | ` Commit messages must under 70 characters and have the following format:\n\n` 22 | ) + 23 | ` ${colors.green(`feat: Add 'comments' option`)}\n` + 24 | ` ${colors.green(`fix: Handle events on blur (close #28)`)}\n\n` + 25 | colors.white(` See ./docs/commit-convention.md for more details.\n`) 26 | ); 27 | process.exit(1); 28 | } 29 | -------------------------------------------------------------------------------- /docs/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct: Fridge Finder 2 | 3 | Like the technical community as a whole, the Fridge Map team is made up of a mixture of professionals and volunteers from all over the world, working on every aspect of the mission - including mentorship, teaching, and connecting people. Diversity is one of our huge strengths, but it can also lead to communication issues and unhappiness. To that end, we have a few ground rules that we ask people to adhere to. This code applies equally to founders, mentors and those seeking help and guidance. 4 | 5 | This isn't an exhaustive list of things that you can't do. Rather, take it in the spirit in which it's intended - a guide to make it easier to enrich all of us and the technical communities in which we participate. This code of conduct applies to all spaces managed by the Fridge Map project. This includes the Discord Server, the Trello Board, and any other forums created by the project team which the community uses for communication. In addition, violations of this code outside these spaces may affect a person's ability to participate within them. 6 | 7 | If you believe someone is violating the code of conduct, we ask that you report it by emailing . 8 | 9 | - **Be friendly and patient.** 10 | 11 | - **Be welcoming.** We strive to be a community that welcomes and supports people of all backgrounds and identities. This includes, but is not limited to members of any race, ethnicity, culture, national origin, color, immigration status, social and economic class, educational level, sex, sexual orientation, gender identity and expression, age, size, family status, political belief, religion, and mental and physical ability. 12 | 13 | - **Be considerate.** Your work will be used by other people, and you in turn will depend on the work of others. Any decision you take will affect users and colleagues, and you should take those consequences into account when making decisions. Remember that we're a world-wide community, so you might not be communicating in someone else's primary language. 14 | 15 | - **Be respectful.** Not all of us will agree all the time, but disagreement is no excuse for poor behavior and poor manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn into a personal attack. It's important to remember that a community where people feel uncomfortable or threatened is not a productive one. Members of the Fridge Map community should be respectful when dealing with other members as well as with people outside the Fridge Map community. 16 | 17 | - **Be careful in the words that you choose.** We are a community of professionals, and we conduct ourselves professionally. Be kind to others. Do 18 | not insult or put down other participants. Harassment and other exclusionary behavior aren't acceptable. This includes, but is not limited to: 19 | 20 | - Violent threats or language directed against another person. 21 | - Discriminatory jokes and language. 22 | - Posting sexually explicit or violent material. 23 | - Posting (or threatening to post) other people's personally identifying information ("doxing"). 24 | - Personal insults, especially those using racist or sexist terms. 25 | - Unwelcome sexual attention. 26 | - Advocating for, or encouraging, any of the above behavior. 27 | - Repeated harassment of others. In general, if someone asks you to stop, then stop. 28 | 29 | - **When we disagree, try to understand why.** Disagreements, both social and technical, happen all the time and Fridge Map is no exception. It is important that we resolve disagreements and differing views constructively. Remember that we're different. The strength of Fridge Map comes from its varied community, people from a wide range of backgrounds. Different people have different perspectives on issues. Being unable to understand why someone holds a viewpoint doesn't mean that they're wrong. Don't forget that it is human to err and blaming each other doesn't get us anywhere. Instead, focus on helping to resolve issues and learning from mistakes. 30 | 31 | Original text courtesy of the [Django Project](https://www.djangoproject.com/conduct/) 32 | -------------------------------------------------------------------------------- /docs/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Collective Focus 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 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

Fridge Finder

6 |

7 | 8 |

9 | 10 | 11 | 12 | 13 | 14 | 15 | GitHub contributors 16 | Build Status 17 | 18 | 19 | 20 |

21 | 22 | A community fridge is a decentralized resource where businesses and individuals can [donate perishable food](https://www.thrillist.com/lifestyle/new-york/nyc-community-fridges-how-to-support). There are dozens of fridges hosted by volunteers across the country. The Fridge Finder website is available at [fridgefinder.app](https://fridgefinder.app/) 23 | 24 | Fridge Finder is a project sponsored by [Collective Focus](https://collectivefocus.site/), a community organization in Brooklyn, New York. Our goal is to make it easy for people to find fridge locations and get involved with food donation programs in their community. We are building a responsive, mobile first, multi-lingual web application with administrative controls for fridge maintainers. To join the project read our [contributing guidelines](./CONTRIBUTING.md) and [code of conduct](./CODE_OF_CONDUCT.md). 25 | 26 |

Made possible by contributions from these lovely people …

27 |

28 | 29 | 30 | 31 |

32 |

❤ Thank you for all your hard work

33 | 34 | ## System Requirements 35 | 36 | 1. [Node](https://nodejs.org/en/) 37 | 38 | ## System Setup 39 | 40 | 1. Verify your system meets the requirements 41 | 42 | ```bash 43 | node --version # must be greater than 14.6.0 44 | ``` 45 | 46 | 1. Install global dependencies 47 | 48 | ```bash 49 | npm install --global yarn prettier svgo lint-staged concurrently json-server 50 | corepack enable # for yarn 51 | ``` 52 | 53 | 1. Setup the frontend environment 54 | 55 | ```bash 56 | git clone https://github.com/FridgeFinder/CFM_Frontend frontend 57 | cd frontend 58 | git checkout dev 59 | yarn install 60 | ``` 61 | 62 | 1. Run the unit tests 63 | 64 | ```bash 65 | yarn test 66 | ``` 67 | 68 | 1. Run the application locally 69 | 70 | ```bash 71 | # to run both development database and Next.js web server 72 | yarn dev 73 | 74 | # to run only the web server 75 | yarn web 76 | 77 | # to run only the development database 78 | yarn data 79 | ``` 80 | 81 | in a different terminal window 82 | 83 | ```bash 84 | start "Google Chrome" http://localhost:3000/ # Windows 85 | open -a "Google Chrome" http://localhost:3000/ # MacOS 86 | ``` 87 | -------------------------------------------------------------------------------- /docs/architecture-decisions.md: -------------------------------------------------------------------------------- 1 | # Architecture Decisions 2 | 3 | ## 2022-05-26 -- CSS Engine 4 | 5 | [MUI recommends the use of emotion for CSS styling](https://mui.com/material-ui/guides/styled-engine/). 6 | 7 | > Warning: Using styled-components as an engine at this moment is not working when used in a SSR projects. The reason is that the babel-plugin-styled-components is not picking up correctly the usages of the styled() utility inside the @mui packages. For more details, take a look at this issue. We strongly recommend using emotion for SSR projects. 8 | 9 | ## 2022-07-17 -- Deprecate the use of styled() 10 | 11 | The following functions have been deprecated because they are slow to render, cause issues with css caching, and cannot be rendered server side. Use the MUI/System `sx` prop instead. 12 | 13 | ```js 14 | import { styled } from '@mui/material/styles'; 15 | import { styled } from '@emotion'; 16 | ``` 17 | 18 | ## 2022-07-17 -- API field sizes 19 | 20 | Tag : 140 characters. The size of a twitter hash tag. 21 | 22 | Location.street : 55 characters. The longest street name in the U.S. is 38 characters long: "Jean Baptiste Point du Sable Lake Shore Drive" located in Chicago, Illinois. eg: 1001 Jean Baptiste Point du Sable Lake Shore Drive #33 23 | 24 | Location.city : 35 characters. The longest city name in the U.S. is "Village of Grosse Pointe Shores" in Michigan. 25 | 26 | Maintainer.name : 70 characters. https://stackoverflow.com/questions/30485/what-is-a-reasonable-length-limit-on-person-name-fields 27 | 28 | ## 2022-07-23 -- Standardize to bash shell 29 | 30 | Standardizing all script commands for bash has proven more complicated than it is worth. The node runtime and `yarn dev` execute commands via the system shell. Overriding this to use bash has proven difficult because the configuration steps differ between the various node versions and yarn versions. In addition the bash directory path is not POSIX compliant in Windows and MacOS. `/usr/bin/bash` wont work in either. 31 | -------------------------------------------------------------------------------- /docs/commit-convention.md: -------------------------------------------------------------------------------- 1 | # Git Commit Message Convention 2 | 3 | This convention is adapted from: 4 | 5 | - [How to Write a Git Commit Message](https://cbea.ms/git-commit/) by Chris Beams 6 | - [Semantic Commit Messages](https://gist.github.com/joshbuchea/6f47e86d2510bce28f8e7f42ae84c716) by Josh Buchea 7 | 8 | ## synopsis 9 | 10 | - commit message header format: `(): ` 11 | - `subject` must start with a capital letter 12 | - `subject` must not end with a period 13 | - `subject` must not exceed 70 characters 14 | 15 | commit header examples: 16 | 17 | - `feat: Add hat wobble` 18 | - `wip: Moved commit-convention to docs` 19 | 20 | ## commit message 21 | 22 | A commit message consists of a `header`, `body` and `footer`. The header has a `type`, `scope` and `subject`: 23 | 24 | ``` 25 | (): 26 | 27 | 28 | 29 |