├── .eslintrc.js ├── .github ├── CODE_OF_CONDUCT.md └── workflows │ ├── build.yml │ └── lint.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SUBMISSION_GUIDELINES.md ├── components ├── MDXComponents.js ├── backbtn.js ├── card.js ├── contributor.js ├── footer.js ├── head.js ├── layout.js ├── nav.js ├── projectdetails.js ├── searchbar.js └── searchcard.js ├── data └── PROJECTS.json ├── lib ├── fetcher.js ├── getGithubData.js └── search.js ├── next-env.d.ts ├── next.config.js ├── package-lock.json ├── package.json ├── pages ├── _app.js ├── _document.js ├── about.mdx ├── api │ └── hello.js ├── contributors.js ├── docs │ └── git.mdx ├── index.js └── search.js ├── postcss.config.js ├── public └── favicon.ico ├── styles └── globals.css ├── tailwind.config.js ├── tsconfig.eslint.json └── tsconfig.json /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ["airbnb-typescript", "plugin:prettier/recommended"], 4 | env: { 5 | browser: true, 6 | node: true, 7 | es2020: true 8 | }, 9 | parserOptions: { 10 | project: "./tsconfig.eslint.json" 11 | }, 12 | rules: { 13 | "react/jsx-filename-extension": [1, { extensions: [".js", ".jsx", ".ts", ".tsx"] }], 14 | "prettier/prettier": ["error", {}, { usePrettierrc: true }], 15 | "react/react-in-jsx-scope": "off", 16 | "no-console": "off", 17 | "react/prop-types": "off", 18 | "simple-import-sort/imports": "error", 19 | "@typescript-eslint/explicit-function-return-type": "off", 20 | "jsx-a11y/anchor-is-valid": [ 21 | "error", 22 | { 23 | components: ["Link"], 24 | specialLink: ["hrefLeft", "hrefRight"], 25 | aspects: ["invalidHref", "preferButton"] 26 | } 27 | ], 28 | "jsx-a11y/alt-text": "warn", 29 | "@typescript-eslint/no-unused-vars": "warn", 30 | "react/no-unescaped-entities": "warn" 31 | }, 32 | plugins: ["simple-import-sort"] 33 | }; 34 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at https://discord.gg/thinkfiveable. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | branches: 8 | - main 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Clone repo 14 | uses: actions/checkout@v2 15 | - name: Set up Node 16 | uses: actions/setup-node@v1 17 | with: 18 | node-version: '14' 19 | - name: Cache node modules 20 | uses: actions/cache@v2 21 | env: 22 | cache-name: cache-node-modules 23 | with: 24 | path: ~/.npm 25 | key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} 26 | restore-keys: | 27 | ${{ runner.os }}-build-${{ env.cache-name }}- 28 | ${{ runner.os }}-build- 29 | ${{ runner.os }}- 30 | - name: Install dependencies 31 | run: npm i 32 | - name: Build 33 | run: npm run build -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint and Format 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | branches: 8 | - main 9 | jobs: 10 | lint: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Clone repo 14 | uses: actions/checkout@v2 15 | - name: Set up Node 16 | uses: actions/setup-node@v1 17 | with: 18 | node-version: '14' 19 | - name: Cache node modules 20 | uses: actions/cache@v2 21 | env: 22 | cache-name: cache-node-modules 23 | with: 24 | path: ~/.npm 25 | key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} 26 | restore-keys: | 27 | ${{ runner.os }}-build-${{ env.cache-name }}- 28 | ${{ runner.os }}-build- 29 | ${{ runner.os }}- 30 | - name: Install dependencies 31 | run: npm i 32 | - name: Run Linter 33 | run: npm run lint -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | 36 | # replit 37 | .replit -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Intro 2 | Welcome to the Fiveable Open Source Initiative repository. We are so happy to have you here and can't wait to see what you will contribute. We're gonna go over some guidelines for what we are expecting all contributions to follow. [**Please ensure all your contributions follow our CODE OF CONDUCT**](https://github.com/ThinkFiveable/open/blob/main/.github/CODE_OF_CONDUCT.md). 3 | 4 | You are expected to fork this repository (unless you are a maintainer and have write access). You are highly recommended to create branches with appropriate naming for whatever your PR is going to be for. The reason we want you to create branches instead of pushing to *your* main branch is in the event that we do not merge your PR and it is rejected, your main branch will be out of sync. 5 | 6 | ## Keeping Sync 7 | Let's propose a scenario, say you and another person make two separate PRs. The other persons PR is merged before yours, you are **required** to "merge the upstream main branch" into your current branch. In order to do this, you would: 8 | 1. Make sure you have our main repo as a remote `git remote add upstream https://github.com/ThinkFiveable/open.git` 9 | 2. Fetch upstream `git fetch upstream` 10 | 3. Checkout the branch you are working on (if you are already on your working branch you can skip this step) `git checkout new-feature-branch-2` 11 | 4. Merge upstream master into your branch `git merge upstream/master` (*There is a chance that you could run into merge conflicts, which are when someone elses PR has edited files and lines that you have also edited in your PR, in which case you need to decide whose change to move forward with. We will cover this more in our git tutorials.*) 12 | 13 | ## Guidelines 14 | - PR and Issues titles should be short and descriptive. 15 | - Commits **must** follow the [Our Commit Convention](#commiting) 16 | - PR bodies must describe what changes were made, and if it was made in response to an issue you must include "closes #issuenumber" at the top of the body. 17 | - Ensure that if you are making a PR to solve an open issue, that no one has already claimed it and been assigned to it. 18 | 19 | ## Commiting 20 | Our commit convention is based directly from the [Angular Commit Convention](https://www.conventionalcommits.org/en/v1.0.0-beta.4/). Some examples of that being: 21 | - `fix: broken button on index.html` 22 | - `fix(index): broken button` 23 | - `chore: add NEWFILE.md` 24 | - `feat: new button!!!` 25 | 26 | We use husky and commitlint to enforce this on the developer side, so please do not try to circumvent it. 27 | If your commit has an unclear message or does not follow our commit convention, you are subject to being asked to edit it using `git rebase`. 28 | 29 | Once you are ready to create a PR, make sure that you have run `npm run lint:fix` in your terminal to lint and format your code changes. If any warnings or errors are shown, make sure to fix them and commit again before creating the PR. 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Fiveable 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Open Source Intiative](https://open.fiveable.me) 2 | We're building a community for discovery and learning. 3 | 4 | ## To get started, follow these steps: 5 | 6 | **Prerequisites**: Node.js ( [Install Here](https://nodejs.org/en/download/) ), Git ( [Install Here](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) ) 7 | 8 | 1. Clone the repository using the following command in your terminal: `git clone https://github.com/ThinkFiveable/open fiveable-open` 9 | 2. Go into that project's directory using `cd fiveable-open` 10 | 3. Do `npm install` to install required dependencies 11 | 4. Then, `npm run dev` which will run the site locally at [http://localhost:3000](http://localhost:3000) 12 | 13 | ## Frameworks/Libraries this project uses 14 | - Tailwind CSS (no more going through the installation guide!) - for styling components easily 15 | - `next-themes` (@pacocoursey) - for going to the dark side 16 | - `swr` (@vercel) - for fetching constantly mutating data 17 | - `fetcher.js` so you don't have to keep writing return functions 18 | - `framer-motion` - for making interactive components and eye-catching animations 19 | - `react-icons` - for including your favorite icon packs without increasing bundle size significantly. Tree shaking included. 20 | 21 | ## How do I contribute? 22 | Great question! You are expected to fork this repository and to create PRs when you want to merge your changes. Your commits are expected to follow our [Commit Convention](https://github.com/ThinkFiveable/open/blob/main/CONTRIBUTING.md#commiting), so some example ones are: 23 | - `fix: broken button on index.html` 24 | - `fix(Index): broken button` 25 | - `chore: add NEWFILE.md` 26 | - `feat: new button!!!` 27 | Before making a PR, make sure to run `npm run lint:fix` and fix any warnings or errors that might be shown in your terminal to ensure consistent code style. 28 | 29 | You can find more information regarding contributing to this project in our [CONTRIBUTING.md](https://github.com/ThinkFiveable/open/blob/main/CONTRIBUTING.md) 30 | 31 | 32 | Licensed under [MIT](LICENSE). 33 | -------------------------------------------------------------------------------- /SUBMISSION_GUIDELINES.md: -------------------------------------------------------------------------------- 1 | # Fiveable Open Source Project Submission Guidelines 2 | 3 | - Projects must be constructive and unique, repos that are intended to serve as a personal website or documentation websites are not allowed. The exception to this are external guides for libraries that don't provide a guide. 4 | - Projects must have a clear CODE_OF_CONDUCT.md that clearly denounces any discriminatory, unwelcoming, or any otherwise harmful behavior that damages/hinders the positive environment we've strived to create. Examples of an acceptable code of conduct can be found at contributor-covenant.org/version/2/0/code_of_conduct. 5 | - Projects must have a clear/organized README with information as to what the projects purpose is. It doesn't have to be a fancy readme, but it does need to cover basic information. 6 | - repo description 7 | - clear instructions as to how to setup a local environment for contributors 8 | - (encouraged) gifs/photos/text demonstrating example usage 9 | - (encouraged) demo 10 | - repo structure explanation (if isn't self-explanatory) 11 | - Projects must be contributable, cannot be archived or privated, and must be licensed under an appropriate license that is Open Source foundation certified. You can find an abiding license at (https://choosealicense.com/). 12 | - Projects must be submitted by either the repo owner or someone with the "maintainer" status on said repo. "contributor" status does not meet this criteria. 13 | - Submitter/maintainers must display behavior that will fit well with our environment. Toxic or unwelcoming behavior is not tolerated at all. 14 | - If the project is a fork, it must be transformative to an extent. This will be decided on a case by case basis. 15 | 16 | If any help is needed with the overall application process or repository setup, you can contact the Open Source Interns at the [Discord server](https://discord.gg/thinkfiveable). 17 | -------------------------------------------------------------------------------- /components/MDXComponents.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable react/destructuring-assignment */ 2 | /* eslint-disable react/jsx-props-no-spreading */ 3 | import Link from "next/link"; 4 | 5 | const CustomLink = (props) => { 6 | const { href } = props; 7 | const isInternalLink = href && (href.startsWith("/") || href.startsWith("#")); 8 | 9 | if (isInternalLink) { 10 | return ( 11 | 12 | 13 | {props.children} 14 | 15 | 16 | ); 17 | } 18 | 19 | return ( 20 | 25 | {props.children} 26 | 27 | ); 28 | }; 29 | 30 | const CustomHeader = (props) => { 31 | return ( 32 |

33 | {props.children} 34 |

35 | ); 36 | }; 37 | 38 | const CustomSubheading = (props) => { 39 | return ( 40 |

41 | {props.children} 42 |

43 | ); 44 | }; 45 | 46 | const UnorderedList = (props) => { 47 | return ( 48 | 51 | ); 52 | }; 53 | 54 | const OrderedList = (props) => { 55 | return ( 56 |
    57 | {props.children} 58 |
59 | ); 60 | }; 61 | 62 | const MDXComponents = { 63 | h1: CustomHeader, 64 | h2: CustomSubheading, 65 | a: CustomLink, 66 | ul: UnorderedList, 67 | ol: OrderedList 68 | }; 69 | 70 | export default MDXComponents; 71 | -------------------------------------------------------------------------------- /components/backbtn.js: -------------------------------------------------------------------------------- 1 | import { useRouter } from "next/router"; 2 | import { BsArrowLeft } from "react-icons/bs"; 3 | 4 | export default function BackButton() { 5 | const router = useRouter(); 6 | return ( 7 | 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /components/card.js: -------------------------------------------------------------------------------- 1 | export default function Card({ owner, title, type, thumbnail, profileIcon, award }) { 2 | return ( 3 |
4 |
8 |
9 |
10 |

{title}

11 |
12 |

13 | {owner} • {type} 14 |

15 |
16 |
17 | 18 | Profile 19 | 20 |
21 |
22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /components/contributor.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | 3 | const bgColors = { 4 | maintainer: { color: "black", status: "Maintainer" }, 5 | gold: { color: "#ffb800", status: "Gold Contributor" }, 6 | silver: { color: "#878787", status: "Silver Contributor" }, 7 | bronze: { color: "#ffb8a1", status: "Bronze Contributor" }, 8 | contributor: { color: "#c9beff", status: "Contributor" } 9 | }; 10 | 11 | class UserStatus { 12 | constructor(contribution) { 13 | this.contribution = contribution; 14 | } 15 | 16 | getLabelBgColor(maintainer) { 17 | if (maintainer) return bgColors.maintainer.color; 18 | if (this.contribution > 10) return bgColors.gold.color; 19 | if (this.contribution > 5) return bgColors.silver.color; 20 | if (this.contribution > 2) return bgColors.bronze.color; 21 | return bgColors.contributor.color; 22 | } 23 | 24 | getLabelText(maintainer) { 25 | if (maintainer) return bgColors.maintainer.status; 26 | if (this.contribution > 10) return bgColors.gold.status; 27 | if (this.contribution > 5) return bgColors.silver.status; 28 | if (this.contribution > 2) return bgColors.bronze.status; 29 | return bgColors.contributor.status; 30 | } 31 | } 32 | 33 | function Contributor({ name, contributions, avatar, url }) { 34 | const [maintainers, setMaintainers] = useState([]); 35 | const user = new UserStatus(contributions); 36 | 37 | useEffect(() => { 38 | fetch("https://api.github.com/orgs/thinkfiveable/public_members") 39 | .then((res) => res.json()) 40 | .then(setMaintainers) 41 | .catch((err) => err); 42 | }, []); 43 | 44 | const maintainersName = maintainers.map(({ login }) => ({ login })); 45 | const checkUserStatus = maintainersName.find(({ login }) => login === name) !== undefined; 46 | 47 | return ( 48 |
49 |
50 | avatar 51 |
52 |
53 | 54 | @{name} 55 | 56 | {maintainersName ? ( 57 |

63 | {user.getLabelText(checkUserStatus)} 64 |

65 | ) : null} 66 |
67 |
68 | ); 69 | } 70 | 71 | export default function Contributors() { 72 | const [usersDetails, setUsersDetails] = useState([]); 73 | 74 | useEffect(() => { 75 | fetch("https://api.github.com/repos/thinkfiveable/open/contributors") 76 | .then((res) => res.json()) 77 | .then(setUsersDetails) 78 | .catch((err) => err); 79 | }, []); 80 | 81 | return ( 82 |
83 | {usersDetails 84 | ? usersDetails.map((user) => ( 85 | 92 | )) 93 | : null} 94 |
95 | ); 96 | } 97 | -------------------------------------------------------------------------------- /components/footer.js: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | 3 | export default function Footer() { 4 | return ( 5 |
6 | 11 | 15 | 16 |
17 |
18 |
19 | © Fiveable 2021 | All Rights Reserved. 20 |
21 |
22 | 57 |
58 |
59 | ); 60 | } 61 | -------------------------------------------------------------------------------- /components/head.js: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | 3 | export default function HeadObject({ children }) { 4 | const title = "Open Source Initiative | Fiveable "; 5 | const description = 6 | "Put your projects on the Fiveable Open Souce Initiative today and release them to the world!"; 7 | const keywords = "Fiveable, Open Source, Fiveable Open Source, projects"; 8 | const author = "Fiveable"; 9 | const twitter = "@thinkfiveable"; 10 | // const image = "/ogimage.png"; // This is your OpenGraph image 11 | return ( 12 | 13 | 14 | 15 | 16 | {title} 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | {/* */} 25 | 26 | 27 | 28 | {children} 29 | 30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /components/layout.js: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | import { BsArrowLeftShort } from "react-icons/bs"; 3 | 4 | import Footer from "./footer"; 5 | import HeadObject from "./head"; 6 | 7 | function Layout({ subtitle, title, authors, publishDate, children }) { 8 | return ( 9 |
10 | 11 |
12 | 13 |
14 | Back 15 |
16 | 17 |
18 |

{title}

19 | {subtitle &&

{subtitle}

} 20 |

{publishDate}

21 |
22 | {authors?.length && ( 23 |
24 | {authors.map((author) => ( 25 |
26 | {author.name} 27 |

{author.name}

28 |
29 | ))} 30 |
31 | )} 32 |
33 | 36 | 37 | 38 |
{children}
39 |
40 |
41 | ); 42 | } 43 | 44 | export default Layout; 45 | -------------------------------------------------------------------------------- /components/nav.js: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | import { useTheme } from "next-themes"; 3 | import { CgDarkMode } from "react-icons/cg"; 4 | import { FiGithub } from "react-icons/fi"; 5 | 6 | import SearchBar from "./searchbar"; 7 | 8 | export default function Nav() { 9 | const { theme, setTheme } = useTheme(); 10 | return ( 11 | 39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /components/projectdetails.js: -------------------------------------------------------------------------------- 1 | import { AnimatePresence, motion } from "framer-motion"; 2 | import { useState } from "react"; 3 | import { FiGithub } from "react-icons/fi"; 4 | 5 | export default function Modal({ 6 | owner, 7 | title, 8 | type, 9 | thumbnail, 10 | profileIcon, 11 | award, 12 | description, 13 | handleKeyDown 14 | }) { 15 | const [showModal, setShowModal] = useState(false); 16 | return ( 17 |
18 |
setShowModal(true)}> 24 |
28 |
29 |
30 |

{title}

31 |
32 |

33 | {owner} • {type} 34 |

35 |
36 |
37 | 38 | Profile 39 | 40 |
41 |
42 | {showModal ? ( 43 | 44 | 51 |
52 |
53 | {/* Modal header */} 54 |
55 |
56 | 62 | 63 | 64 |
65 | 66 |
67 |

68 | {title} 69 |

70 |
71 | 75 | GitHub user profile 80 | 81 |

{owner}

82 |
83 |
84 |
85 | {/* Repo Description */} 86 |
87 |

88 | {description} 89 |

90 |
91 | {/* Modal Footer */} 92 |
93 | 99 |
100 |
101 |
102 |
103 | {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events */} 104 | {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */} 105 |
setShowModal(false)} 109 | /> 110 | 111 | ) : null} 112 |
113 | ); 114 | } 115 | -------------------------------------------------------------------------------- /components/searchbar.js: -------------------------------------------------------------------------------- 1 | import { useRouter } from "next/router"; 2 | import { useState } from "react"; 3 | import { BsSearch } from "react-icons/bs"; 4 | 5 | export default function SearchBar() { 6 | const router = useRouter(); 7 | const [search, update] = useState(""); 8 | const submit = () => { 9 | router.push(`/search?q=${search}`); 10 | }; 11 | return ( 12 |
13 | { 21 | if (evt.key === "Enter") { 22 | submit(); 23 | } 24 | }} 25 | onChange={(evt) => update(evt.target.value)} 26 | /> 27 | 28 | 34 | 40 |
41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /components/searchcard.js: -------------------------------------------------------------------------------- 1 | export default function SearchCard({ repoOwner, title, projectType, thumbnail, award }) { 2 | return ( 3 |
4 |
7 | featured project 12 |
13 |
14 |
15 |

{title}

16 |
17 |

18 | {repoOwner} • {projectType} 19 |

20 |
21 | 22 | Profile 27 | 28 |
29 |
30 |
31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /data/PROJECTS.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "repoName": "discord-botboi-bot", 4 | "repoOwner": "alt-ab", 5 | "projectType": "Discord Bot", 6 | "award": "silver", 7 | "projectDescription": "A fun, get-to-know you Discord bot with over 15+ commands! It’s light-weight and hosted! I built it as one of my first project ideas, and I was able to develop off this concept for a programming apprenticeship I had! " 8 | }, 9 | { 10 | "repoName": "movie-picker", 11 | "repoOwner": "DBlack2021", 12 | "projectType": "Web App", 13 | "award": "silver", 14 | "projectDescription": "This project targets people who are struggling to figure out a TV show / movie to watch. Users can search for TV shows and movies and then pick one at random. Afterwards they can view stats about the movie and look at the cast and crew." 15 | }, 16 | { 17 | "repoName": "maya", 18 | "repoOwner": "ThinkFiveable", 19 | "repoLogo": "https://github.com/cnnor/Maya/raw/main/banner.png", 20 | "projectType": "Discord Bot", 21 | "award": "silver", 22 | "projectDescription": "Maya is a multi-purpose, community-driven, single-guild Discord bot built for the Fiveable student community. It was built with functionality and customizability in mind, offering featurful moderation commands, utilities, reaction roles, and channel linking." 23 | }, 24 | { 25 | "repoName": "guilded.js", 26 | "repoOwner": "zaida04", 27 | "repoLogo": "https://github.com/zaida04/guilded.js/raw/main/static/readme-header.png", 28 | "projectType": "Library", 29 | "award": "silver", 30 | "projectDescription": "Tools for interacting with the guilded.gg API. Usable in either JavaScript or TypeScript projects." 31 | }, 32 | { 33 | "repoName": "DeltaScheme", 34 | "repoOwner": "RayhanADev", 35 | "repoLogo": "https://raw.githubusercontent.com/RayhanADev/DeltaScheme/master/public/assets/images/logos/deltascheme_opengraphimage.png", 36 | "projectType": "Web App", 37 | "award": "silver", 38 | "projectDescription": "This is DeltaScheme. DeltaScheme simulates the business model of a Pyramid Scheme, except on the Internet, turning the horrific business model into a friendly game. The only way to sign up for the site is with a special code given out by recruiters. New members can then send their code out to more people and invite them for tokens! Created using NodeJS, Express, Cloud Firestore, GraphQL, and more! **Still a Work In Progress, Feel Free to Contribute**" 39 | }, 40 | { 41 | "repoName": "rent-a-ni.co", 42 | "repoOwner": "zaida04", 43 | "projectType": "API", 44 | "award": "silver", 45 | "projectDescription": "Link shortener built with Fastify." 46 | }, 47 | { 48 | "repoName": "Lucia", 49 | "repoOwner": "aidenybai", 50 | "projectType": "Library", 51 | "award": "silver", 52 | "projectDescription": "An augmentation layer for your webapp logic, allowing you to bind attributes to your HTML to add interactivity without writing any extra JavaScript. I built it with TypeScript and other tooling. Please read the Wiki if you are interested in contributing! https://github.com/aidenybai/lucia/wiki" 53 | }, 54 | { 55 | "repoName": "chrome_extension", 56 | "repoOwner": "shreyfirst", 57 | "repoLogo": "https://media.discordapp.net/attachments/706943886530183202/843226725273436200/df15b80c-aabd-46c0-8ddc-9fe20413cf28.jpeg", 58 | "projectType": "Chrome Extension", 59 | "award": "silver", 60 | "projectDescription": "I created Zoom Bookmarks with just plain old HTML and Javascript. It's a Chrome Extension that lets people save their online meeting meetings for easy access later. It is currently live on the Chrome Web Store: https://chrome.google.com/webstore/detail/zoom-bookmarks/haplbihlmhnffbihdfjhgnickameiphd - and will continue to update it as there are new PRs! This was one of my earliest projects, and I did a little teaching demo, which is the README too." 61 | }, 62 | { 63 | "repoName": "tether", 64 | "repoOwner": "RayhanADev", 65 | "repoLogo": "https://tether.rayhanadev.repl.co/public/tether_cover.png", 66 | "projectType": "Game", 67 | "award": "silver", 68 | "projectDescription": "Tether is an online game with support for all devices. It uses native Canvas graphics and smart animation techniques to build an all-out aesthetically pleasing and fun game!" 69 | }, 70 | { 71 | "repoName": "Brain-Controlled-Robotic-Joint", 72 | "repoOwner": "neeltron", 73 | "projectType": "Hardware", 74 | "award": "silver", 75 | "projectDescription": "This repository presents a brain-controlled robotic joint, which allows amputees to control an artificial limb using their brain." 76 | }, 77 | { 78 | "repoName": "ampl-ify", 79 | "repoOwner": "shreeyachand", 80 | "repoLogo": "https://raw.githubusercontent.com/shreeyachand/ampl-ify/main/cover.png", 81 | "projectType": "Web App", 82 | "award": "none", 83 | "projectDescription": "ampl-ify uses the Spotipy Python library to interact with the Spotify API and make users track recommendations based on the songs in their playlists, using a nearest neighbors algorithm." 84 | }, 85 | { 86 | "repoName": "randomjokesapp", 87 | "repoOwner": "nikshitak", 88 | "projectType": "Web App", 89 | "award": "none", 90 | "projectDescription": "This web app lets you see a joke every time you click the button, and there's hundereds of joke in the Official Joke API so that you will almost always get a new joke. This is really just meant to give a serotinin boost and to make you smile. This is the link to the web app: https://nikshitak.github.io/randomjokesapp/" 91 | }, 92 | { 93 | "repoName": "timer-bot", 94 | "repoOwner": "supersonik12", 95 | "projectType": "Discord Bot", 96 | "award": "none", 97 | "projectDescription": "A Discord bot that can set a timer. It alerts you with a message when the timer is up. It can also run Pomodoro-style study sessions." 98 | }, 99 | { 100 | "repoName": "Swiss-Knife-Translator", 101 | "repoOwner": "TobiA2028", 102 | "projectType": "Discord Bot", 103 | "award": "none", 104 | "projectDescription": "A Discord bot that allows users to translate a phrase or generate an inspirational quote in a different language. Built with the goal of making language learning a little more fun." 105 | }, 106 | { 107 | "repoName": "Hurricano", 108 | "repoOwner": "HurricanoBot", 109 | "projectType": "Discord Bot", 110 | "award": "none", 111 | "projectDescription": "An amazing open-source Discord bot using MongoDB with many features such as a customizable prefix, a reaction menu, music, role requirement giveaways and much more!" 112 | } 113 | ] 114 | -------------------------------------------------------------------------------- /lib/fetcher.js: -------------------------------------------------------------------------------- 1 | /** 2 | * useSWR() fetcher 3 | * @param {...any} args fetcher for useSWR() 4 | */ 5 | 6 | export default async function Fetcher(...args) { 7 | const res = await fetch(...args); 8 | return res.json(); 9 | } 10 | -------------------------------------------------------------------------------- /lib/getGithubData.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Retrieve Github GraphQL Data 3 | * @param {String} repoOwner - Owner of the Repository 4 | * @param {String} repoName - Name of the Repository 5 | */ 6 | export async function getGraphqlData(repoOwner, repoName) { 7 | const headers = {}; 8 | 9 | if (process.env.GITHUB_TOKEN) headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`; 10 | const body = JSON.stringify({ 11 | query: ` 12 | query RepositoryInfo($repoOwner: String!, $repoName: String!){ 13 | repository(owner: $repoOwner, name: $repoName) { 14 | owner { 15 | login 16 | } 17 | description 18 | name 19 | usesCustomOpenGraphImage 20 | openGraphImageUrl 21 | } 22 | }`, 23 | variables: { 24 | repoOwner, 25 | repoName 26 | } 27 | }); 28 | const { data, message } = await fetch("https://api.github.com/graphql", { 29 | headers, 30 | body, 31 | method: "POST" 32 | }).then((res) => res.json()); 33 | 34 | if (message) return message; 35 | return data; 36 | } 37 | 38 | /** 39 | * Retrieve Github Restful Data 40 | * @param {String} repoOwner - Owner of the Repository 41 | * @param {String} repoName - Name of the Repository 42 | */ 43 | export async function getRestfulData(repoOwner, repoName) { 44 | const headers = { 45 | Accept: "application/vnd.github.mercy-preview+json" 46 | }; 47 | 48 | if (process.env.GITHUB_TOKEN) headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`; 49 | const data = await fetch(`https://api.github.com/repos/${repoOwner}/${repoName}`, { 50 | headers, 51 | method: "GET" 52 | }).then((res) => { 53 | if (res.headers.raw()["x-ratelimit-remaining"][0] === 0) 54 | console.log("\u001b[31mHit Rate Limit!!!\u001b[39m"); 55 | return res.json(); 56 | }); 57 | 58 | return { 59 | owner: { login: data.owner.login }, 60 | description: data.description, 61 | name: data.name, 62 | usesCustomOpenGraphImage: null, 63 | openGraphImageUrl: null 64 | }; 65 | } 66 | -------------------------------------------------------------------------------- /lib/search.js: -------------------------------------------------------------------------------- 1 | import Fuse from "fuse.js"; 2 | 3 | export default function SearchData(q, data) { 4 | const options = { 5 | includeScore: true, 6 | // Search in `author` and in `tags` array 7 | keys: ["repoName", "repoOwner", "projectType"] 8 | }; 9 | 10 | const fuse = new Fuse(data, options); 11 | 12 | const results = fuse.search(q); 13 | return results.sort((a, b) => a.score - b.score).map((result) => result.item); 14 | } 15 | -------------------------------------------------------------------------------- /next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | const withMDX = require("@next/mdx")({ 2 | extension: /\.mdx$/ 3 | }); 4 | 5 | module.exports = withMDX({ 6 | pageExtensions: ["js", "jsx", "md", "mdx"] 7 | }); 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fiveable-open", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "eslint . --ext .js,.jsx,.ts,.tsx", 10 | "lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix" 11 | }, 12 | "dependencies": { 13 | "@mdx-js/loader": "^1.6.22", 14 | "@mdx-js/react": "^1.6.22", 15 | "@next/mdx": "^10.1.3", 16 | "framer-motion": "^4.1.4", 17 | "fuse.js": "^6.4.6", 18 | "next": "10.0.7", 19 | "next-themes": "^0.0.11", 20 | "react": "17.0.1", 21 | "react-dom": "17.0.1", 22 | "react-icons": "^4.2.0", 23 | "swr": "^0.4.2" 24 | }, 25 | "devDependencies": { 26 | "@commitlint/cli": "^12.0.1", 27 | "@commitlint/config-angular": "^12.0.1", 28 | "@types/node": "^14.14.35", 29 | "@types/react": "^17.0.3", 30 | "@typescript-eslint/eslint-plugin": "^4.18.0", 31 | "@typescript-eslint/parser": "^4.21.0", 32 | "autoprefixer": "^10.2.4", 33 | "eslint": "^7.22.0", 34 | "eslint-config-airbnb-typescript": "^12.3.1", 35 | "eslint-config-prettier": "^8.1.0", 36 | "eslint-plugin-import": "^2.22.1", 37 | "eslint-plugin-jsx-a11y": "^6.4.1", 38 | "eslint-plugin-prettier": "^3.3.1", 39 | "eslint-plugin-react": "^7.22.0", 40 | "eslint-plugin-react-hooks": "^4.2.0", 41 | "eslint-plugin-simple-import-sort": "^7.0.0", 42 | "husky": "^4.3.8", 43 | "lint-staged": "^10.5.4", 44 | "postcss": "^8.2.10", 45 | "prettier": "^2.2.1", 46 | "tailwindcss": "^2.0.3", 47 | "typescript": "^4.2.3" 48 | }, 49 | "prettier": { 50 | "printWidth": 110, 51 | "tabWidth": 4, 52 | "useTabs": false, 53 | "semi": true, 54 | "singleQuote": false, 55 | "trailingComma": "none", 56 | "bracketSpacing": true, 57 | "jsxBracketSameLine": true, 58 | "arrowParens": "always", 59 | "requirePragma": false, 60 | "insertPragma": false, 61 | "proseWrap": "always" 62 | }, 63 | "husky": { 64 | "hooks": { 65 | "pre-commit": "lint-staged", 66 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" 67 | } 68 | }, 69 | "lint-staged": { 70 | "*.{js,jsx,ts,tsx}": "eslint --fix" 71 | }, 72 | "commitlint": { 73 | "extends": [ 74 | "@commitlint/config-angular" 75 | ], 76 | "rules": { 77 | "scope-case": [ 78 | 2, 79 | "always", 80 | "pascal-case" 81 | ], 82 | "type-enum": [ 83 | 2, 84 | "always", 85 | [ 86 | "chore", 87 | "build", 88 | "ci", 89 | "docs", 90 | "feat", 91 | "fix", 92 | "perf", 93 | "refactor", 94 | "revert", 95 | "style", 96 | "test", 97 | "types", 98 | "wip" 99 | ] 100 | ] 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /pages/_app.js: -------------------------------------------------------------------------------- 1 | import "../styles/globals.css"; 2 | 3 | import { MDXProvider } from "@mdx-js/react"; 4 | import { ThemeProvider } from "next-themes"; 5 | 6 | import MDXComponents from "../components/MDXComponents"; 7 | 8 | function MyApp({ Component, pageProps }) { 9 | return ( 10 | 11 | 12 | {/* eslint-disable-next-line */} 13 | 14 | 15 | 16 | ); 17 | } 18 | 19 | export default MyApp; 20 | -------------------------------------------------------------------------------- /pages/_document.js: -------------------------------------------------------------------------------- 1 | import Document, { Head, Html, Main, NextScript } from "next/document"; 2 | 3 | export default class CustomDocument extends Document { 4 | render() { 5 | return ( 6 | 7 | 8 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /pages/about.mdx: -------------------------------------------------------------------------------- 1 | import Layout from "../components/layout"; 2 | import Footer from "../components/footer"; 3 | 4 | export default (children) => ( 5 |
6 | 7 |
8 | ); 9 | 10 | ## Goals 11 | 12 | The Fiveable Open Source Initiative aims to create more community and opportunities for students interested in 13 | all things STEM and coding related. No prior experience is necessary. Students have the opportunity to submit 14 | their open-source projects through making a pull request on this 15 | [repository](https://github.com/ThinkFiveable/open) to be featured on the website. This website also serves as 16 | a resource for students to discover open source projects to contribute to. 17 | 18 | ## What is open source? 19 | 20 | Open source projects are projects with public source code that anyone can modify, share, and make enhancements 21 | to. Contributors may add new features to the project or fix bugs that cause usability issues. Every open 22 | source project has a license that determines the way people can use, distribute, or modify the software. 23 | 24 | ## How can I get involved? 25 | 26 | Join the Fiveable Discord server at [discord.gg/thinkfiveable](https://discord.gg/thinkfiveable) and check out 27 | the #open-source channel which serves as the main discussion forum for this initiative. The GitHub repository 28 | can be found [here](https://github.com/ThinkFiveable/open). We are currently accepting submissions for open 29 | source projects through pull requests. 30 | 31 | ## How do I submit my project? 32 | 33 | Head over to our [GitHub repository](https://github.com/thinkfiveable/open) and navigate to the file 34 | `PROJECTS.JSON` located in the directory `data`. Add the information for your project in the following format: 35 | 36 | ```json 37 | { 38 | "repoName": "Name of your repo here", 39 | "repoLogo": "(optional) Attach a link to a cover image for your repo", 40 | "repoOwner": "GitHub username here", 41 | "projectType": "Type of project", 42 | "projectDescription": "Describe your project here." 43 | }, 44 | ``` 45 | 46 | Then, make a pull request, and ask someone to review it! If you need any help, check out our 47 | [Git tutorials](/docs/git) or ask in the #open-source channel on the Discord! 48 | -------------------------------------------------------------------------------- /pages/api/hello.js: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | 3 | export default (req, res) => { 4 | res.status(200).json({ name: "John Doe" }); 5 | }; 6 | -------------------------------------------------------------------------------- /pages/contributors.js: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | import { BsArrowLeftShort } from "react-icons/bs"; 3 | 4 | import Contributor from "../components/contributor"; 5 | import Footer from "../components/footer"; 6 | import HeadObject from "../components/head"; 7 | 8 | function Contributors() { 9 | return ( 10 |
11 | 12 |
13 | 14 |
15 | Back 16 |
17 | 18 | 19 |

Contributors

20 |
21 | 24 | 25 | 26 |
27 | 28 |
29 |
30 |
31 | ); 32 | } 33 | export default Contributors; 34 | -------------------------------------------------------------------------------- /pages/docs/git.mdx: -------------------------------------------------------------------------------- 1 | import Layout from "../../components/layout"; 2 | import Footer from "../../components/footer"; 3 | 4 | export default (children) => ( 5 |
6 | 27 |
28 | ); 29 | 30 | ## Prerequisites 31 | 32 | To use Git, you'll need to download it [here](https://git-scm.com/downloads). 33 | 34 | Be sure to set your username and email before making contributions. In your terminal, do the following: 35 | 36 | - `git config --global user.name "Your Name"` 37 | - `git config --global user.email "youremail@yourdomain.com"` 38 | 39 | ## Fork 40 | 41 | First, we will need our own copy of the repository to make changes on. You will need to create a fork by 42 | clicking on the `Fork` button in the top right. 43 | 44 | ## Clone 45 | 46 | Next, we'll want to get a copy of our repository on our computer locally by cloning our repository. We will 47 | need the HTTPS address on the repository page which you can copy/paste from the browser. We will now use our 48 | terminal's shell commands to move to the place where we want to put our directory copy. 49 | 50 | For example, if we wanted to change to our Documents directory, we would do the following: `cd Documents` 51 | 52 | To clone our repository, we use the following command in our terminal: 53 | `git clone [cloned-directory-name]` 54 | 55 | For example: `git clone https://github.com/your-username/open.git fiveable-open` 56 | 57 | Again, this will create a local copy of the repository at the directory specified earlier. You will then need 58 | to open these files in your preferred text editor to make your changes. 59 | 60 | ## Checkout 61 | 62 | It is highly recommended to switch to a new branch to make changes instead of committing to the main branch. 63 | Why? Say you commit to the main branch of your fork. You go ahead and make a PR, but oh no! Your PR was 64 | denied and was closed. You now have a problem, your main branch now has a bunch of commits that don't exist 65 | on the upstream repo. **Your fork is now out of sync with the upstream repo.** You could just revert those 66 | commits, but now you have a bunch of revert commits polluting your commit history, and those will be added to 67 | the upstream repo if you make another PR. Or you could rebase and remove history (which would a require a 68 | force push which we do NOT allow on this repo). Both of these options are not very good and will only cause 69 | hassle to the maintainers and to the contributor themselves. 70 | 71 | Sounds like a lot right? It's better to prevent all of this from happening in the beginning by just making 72 | changes to a new branch every time. So, say I want to add a bunch of badges to the readme, I'd make a branch 73 | `chore/readme-branch` or `chore/patch-1.` 74 | 75 | To create a new branch from your terminal, do the following: 76 | 77 | - `git branch ` to create a new branch 78 | - `git checkout ` to switch to your branch 79 | 80 | 81 | ## Pull 82 | 83 | You will need to use `git pull` to fetch the latest changes from another repository or local branch. When you 84 | run `git pull` in your terminal, remote content will be downloaded and immediately change the local state of 85 | your repository to match the new content. It is strongly recommended to not `git pull` when you have 86 | uncommitted changes. 87 | 88 | In the event that you do have uncommitted changes and want to `git pull`, you will need to do the following in 89 | your command line. First, `git stash` which "stashes" your changes away temporarily. Then, `git pull` to fetch 90 | the latest changes. Next, `git stash apply` to apply the changes back onto your local copy, and then 91 | `git stash drop` to remove those changes from the stash stack. 92 | 93 | ## Commit 94 | 95 | After making your changes, you will use terminal commands to commit them. Our commit message needs to explain 96 | what we've done. This message may be useful if we want to check our change history in the future, and it can 97 | also be useful to other contributors. 98 | 99 | The syntax for a commit message is as follows `git commit -m "your commit message here"`. 100 | 101 | For our repository, please ensure your commit messages follow 102 | [this standard](https://github.com/ThinkFiveable/open/blob/main/CONTRIBUTING.md#commiting). 103 | 104 | ## Push 105 | 106 | The next step is relatively simple; now that we've committed our changes, all we have to do is push our 107 | changes to the repository on GitHub. 108 | 109 | To push our changes, all we have to do is enter the following into the terminal `git push`. 110 | 111 | ## Pull Request 112 | 113 | To submit your new changes to the original project, you will need to create a pull request. Head back to your 114 | fork on GitHub, and you should be presented with a green button that says `Compare & pull request`. 115 | 116 | compare and pull request 121 | 122 | If you click that button, you will be asked to give your pull reqest a name and description. Please write a 123 | description that accurately reflects what you were trying to do. When you hit the `Create pull request` button 124 | on the screen, a maintainer of the project will be notified to review the suggested changes. 125 | 126 | compare and pull request 131 | 132 | As your PR waits to be merged, other peoples' PRs might be merged before yours, meaning you have to "update 133 | your branch" with the master branch. You can do it with either this button 134 | 135 | Update branch button 140 | 141 | or (the more preferred method as the above button won't always be avaliable), you can do these steps: 142 | 143 | - Add our repository as a remote URL (`git remote add upstream https://github.com/ThinkFiveable/open.git`) 144 | - Make sure you are on the branch you want to merge master into (`git checkout PR_BRANCH_NAME`) 145 | - Make sure you have the latest upstream changes (`git fetch upstream`) 146 | - Merge the upstream master branch into your PR branch (`git merge upstream/main`). At this stage you might 147 | run into what are called **MERGE CONFLICTS. You must resolve these before pushing to your fork.** See: 148 | [Merge Conflicts](#merge-conflicts) 149 | - Push your changes to your fork (`git push`) 150 | 151 | ## [Merge Conflicts](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/resolving-a-merge-conflict-on-github) 152 | 153 | Sometimes you might encounter a message saying that there are "merge conflicts" that must be resolved before 154 | merging. This happens when multiple people make different changes to the same line of the same file in the 155 | repository. This tutorial will go over resolving merge conflicts using GitHub's web interface. 156 | 157 | Near the bottom of your pull request, click the grey button `Resolve conflicts`. Delete the conflict markers 158 | `<<<<<<<`, `=======`, `>>>>>>>`, and make changes appropriately. Once you have resolved all conflicts, click 159 | the green button `Commit merge`. 160 | 161 | resolve merge conflicts 166 | -------------------------------------------------------------------------------- /pages/index.js: -------------------------------------------------------------------------------- 1 | import { motion } from "framer-motion"; 2 | import Link from "next/link"; 3 | import React from "react"; 4 | import { BsArrowRightShort } from "react-icons/bs"; 5 | 6 | import Footer from "../components/footer"; 7 | import HeadObject from "../components/head"; 8 | import Nav from "../components/nav"; 9 | import Modal from "../components/projectdetails"; 10 | import RepoData from "../data/PROJECTS.json"; 11 | import { getRestfulData } from "../lib/getGithubData"; 12 | 13 | export async function getStaticProps() { 14 | const reposPromise = []; 15 | RepoData.forEach(({ repoName, repoOwner }) => { 16 | // const { repository } = getGraphqlData(repoOwner, repoName); 17 | const repository = getRestfulData(repoOwner, repoName); 18 | reposPromise.push(repository); 19 | }); 20 | 21 | const repos = await Promise.all(reposPromise); 22 | const repoMeta = RepoData.reduce((result, item) => { 23 | const newRepoMeta = result; 24 | newRepoMeta[item.repoName.toLowerCase()] = item; 25 | return newRepoMeta; 26 | }, {}); 27 | 28 | const propRepos = repos.map((repo) => { 29 | return { 30 | repoName: repo.name, 31 | repoOwner: repo.owner.login, 32 | projectType: repoMeta[repo.name.toLowerCase()].projectType, 33 | projectDescription: repo.description, 34 | repoLogo: repo.openGraphImage ?? repoMeta[repo.name.toLowerCase()].repoLogo ?? null, 35 | award: repoMeta[repo.name.toLowerCase()].award 36 | }; 37 | }); 38 | 39 | return { 40 | props: { 41 | repos: propRepos 42 | } 43 | }; 44 | } 45 | 46 | export default function Home() { 47 | const headerOutputRange = [ 48 | `M0,192L48,197.3C96,203,192,213,288,208C384,203,480,181,576,176C672,171,768,181,864,192C960,203,1056,213,1152,213.3C1248,213,1344,203,1392,197.3L1440,192L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z`, 49 | `M0,192L48,197.3C96,203,192,213,288,229.3C384,245,480,267,576,250.7C672,235,768,181,864,181.3C960,181,1056,235,1152,234.7C1248,235,1344,181,1392,154.7L1440,128L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z`, 50 | `M0,224L48,218.7C96,213,192,203,288,202.7C384,203,480,213,576,234.7C672,256,768,288,864,277.3C960,267,1056,213,1152,192C1248,171,1344,181,1392,186.7L1440,192L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z`, 51 | `M0,160L48,176C96,192,192,224,288,240C384,256,480,256,576,240C672,224,768,192,864,197.3C960,203,1056,245,1152,250.7C1248,256,1344,224,1392,208L1440,192L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z` 52 | ]; 53 | const headerClipPathVariants = { 54 | beginning: { 55 | d: headerOutputRange[0] 56 | }, 57 | middle: { 58 | d: headerOutputRange[1] 59 | }, 60 | middle2: { 61 | d: headerOutputRange[2] 62 | }, 63 | end: { 64 | d: headerOutputRange[3] 65 | } 66 | }; 67 | return ( 68 |
69 | 70 |
71 |
72 |
73 |
74 |
75 |

Fiveable

76 |
77 | Open
Source
78 |
79 |
80 |
82 |
83 |

84 | We're building a community for discovery and learning. 85 |

86 |
87 | 88 | 89 |
Learn more.
90 | 91 |
92 | 93 |

94 | Not sure where to start? Learn{" "} 95 | 96 | Git 97 | 98 | . 99 |

100 |
101 |
102 | 105 | 116 | 117 | 118 |
119 | {RepoData.map( 120 | ({ repoName, repoOwner, projectType, projectDescription, repoLogo, award }) => ( 121 | 133 | ) 134 | )} 135 |
136 |
137 |
138 |
139 | ); 140 | } 141 | -------------------------------------------------------------------------------- /pages/search.js: -------------------------------------------------------------------------------- 1 | import { useRouter } from "next/router"; 2 | import { useState } from "react"; 3 | 4 | import BackButton from "../components/backbtn"; 5 | import HeadObject from "../components/head"; 6 | import SearchCard from "../components/searchcard"; 7 | import data from "../data/PROJECTS.json"; 8 | import SearchData from "../lib/search"; 9 | 10 | export default function Search() { 11 | const router = useRouter(); 12 | const [searchVal, updateSearch] = useState(router.query.q || ""); 13 | const results = SearchData(searchVal, data); 14 | return ( 15 |
16 | 17 |
18 |
19 |
20 | { 28 | updateSearch(evt.target.value); 29 | router.replace(`/search?q=${evt.target.value}`); 30 | }} 31 | /> 32 | 33 |
34 | 35 | {results.length > 0 ? ( 36 | results.map(({ repoName, repoOwner, projectType, repoLogo }) => ( 37 | 38 | 47 | 48 | )) 49 | ) : ( 50 |

51 | {searchVal === "" 52 | ? "Enter your search above." 53 | : "Nothing was found for this query."} 54 |

55 | )} 56 |
57 |
58 |
59 | ); 60 | } 61 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {} 5 | } 6 | }; 7 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkfiveable/open/3af98739e3637d239f3eedd5195d8d26b82d38f0/public/favicon.ico -------------------------------------------------------------------------------- /styles/globals.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Rubik:ital,wght@0,300;0,400;0,500;0,700;1,300;1,500&display=swap"); 2 | @import url("https://fonts.googleapis.com/css2?family=Inconsolata:wght@500&display=swap"); 3 | 4 | @tailwind base; 5 | @tailwind components; 6 | @tailwind utilities; 7 | 8 | .w-fitcontent { 9 | width: fit-content; 10 | } 11 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | purge: ["./pages/**/*.{js,ts,jsx,tsx}", "./components/**/*.{js,ts,jsx,tsx}"], 3 | darkMode: "class", 4 | theme: { 5 | extend: { 6 | fontFamily: { 7 | rubik: "Rubik, sans-serif", 8 | mono: "Inconsolata, monospace" 9 | }, 10 | colors: { 11 | blue: { 12 | DEFAULT: "#C1E8ED", 13 | dark: "#01A0B6" 14 | }, 15 | black: "#171717", 16 | gray: "#393939", 17 | gold: "#FFE800", 18 | silver: "#878787", 19 | bronze: "#FFB8A1", 20 | contributor: "#C9BEFF" 21 | }, 22 | flex: { 23 | 2: "1 1 40%" 24 | } 25 | } 26 | }, 27 | variants: { 28 | extend: {} 29 | }, 30 | plugins: [] 31 | }; 32 | -------------------------------------------------------------------------------- /tsconfig.eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["**/**.jsx", "**/**.js", "next-env.d.ts",] 4 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "strict": false, 12 | "forceConsistentCasingInFileNames": true, 13 | "noEmit": true, 14 | "esModuleInterop": true, 15 | "module": "esnext", 16 | "moduleResolution": "node", 17 | "resolveJsonModule": true, 18 | "isolatedModules": true, 19 | "jsx": "preserve" 20 | }, 21 | "include": [ 22 | "next-env.d.ts", 23 | "**/**.ts", 24 | "**/**.tsx" 25 | ], 26 | "exclude": [ 27 | "node_modules" 28 | ] 29 | } 30 | --------------------------------------------------------------------------------