mirror of
https://github.com/BradNut/awesome-uses
synced 2025-09-08 17:40:31 +00:00
It's a site
This commit is contained in:
parent
8dde1405ba
commit
14c9b52729
20 changed files with 18350 additions and 1 deletions
71
.gitignore
vendored
71
.gitignore
vendored
|
|
@ -1,2 +1,71 @@
|
|||
.idea
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Typescript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# dotenv environment variable files
|
||||
.env*
|
||||
|
||||
# gatsby files
|
||||
.cache/
|
||||
public
|
||||
|
||||
# Mac files
|
||||
.DS_Store
|
||||
|
||||
# Yarn
|
||||
yarn-error.log
|
||||
.pnp/
|
||||
.pnp.js
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
haters/
|
||||
|
|
|
|||
3
README.md
Normal file
3
README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
## /uses website
|
||||
|
||||
Add yourself [here](./src/data.js)
|
||||
6
gatsby-browser.js
Normal file
6
gatsby-browser.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import React from 'react';
|
||||
import { FilterProvider } from './src/context/FilterContext';
|
||||
|
||||
export const wrapRootElement = ({ element }) => (
|
||||
<FilterProvider>{element}</FilterProvider>
|
||||
)
|
||||
30
gatsby-config.js
Normal file
30
gatsby-config.js
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
module.exports = {
|
||||
siteMetadata: {
|
||||
title: `/uses`,
|
||||
description: `A list of /uses pages detailing developer setups.`,
|
||||
author: `@wesbos`,
|
||||
},
|
||||
plugins: [
|
||||
{
|
||||
resolve: `gatsby-source-filesystem`,
|
||||
options: {
|
||||
name: `images`,
|
||||
path: `${__dirname}/src/images`,
|
||||
},
|
||||
},
|
||||
`gatsby-transformer-sharp`,
|
||||
`gatsby-plugin-sharp`,
|
||||
{
|
||||
resolve: `gatsby-plugin-manifest`,
|
||||
options: {
|
||||
name: `gatsby-starter-default`,
|
||||
short_name: `starter`,
|
||||
start_url: `/`,
|
||||
background_color: `#663399`,
|
||||
theme_color: `#663399`,
|
||||
display: `minimal-ui`,
|
||||
icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site.
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
60
gatsby-node.js
Normal file
60
gatsby-node.js
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
import people from './src/data.js';
|
||||
import { tags, countries } from './src/util/stats';
|
||||
|
||||
function sourceNodes({ actions, createNodeId, createContentDigest }) {
|
||||
// Add People to the GraphQL API, we randomize the data on each build so no one gets their feelings hurt
|
||||
people
|
||||
.sort(() => Math.random() - 0.5)
|
||||
.forEach(person => {
|
||||
const nodeMeta = {
|
||||
id: createNodeId(`person-${person.name}`),
|
||||
parent: null,
|
||||
children: [],
|
||||
internal: {
|
||||
type: `Person`,
|
||||
mediaType: `text/html`,
|
||||
content: JSON.stringify(person),
|
||||
contentDigest: createContentDigest(person),
|
||||
},
|
||||
};
|
||||
|
||||
actions.createNode({ ...person, ...nodeMeta });
|
||||
});
|
||||
|
||||
// Add tags to GraphQL API
|
||||
tags().forEach(tag => {
|
||||
const nodeMeta = {
|
||||
id: createNodeId(`tag-${tag.name}`),
|
||||
parent: null,
|
||||
children: [],
|
||||
internal: {
|
||||
type: `Tag`,
|
||||
mediaType: `text/html`,
|
||||
content: JSON.stringify(tag),
|
||||
contentDigest: createContentDigest(tag),
|
||||
},
|
||||
};
|
||||
|
||||
actions.createNode({ ...tag, ...nodeMeta });
|
||||
});
|
||||
|
||||
console.log(countries());
|
||||
// Add Countries to GraphQL API
|
||||
countries().forEach(country => {
|
||||
const nodeMeta = {
|
||||
id: createNodeId(`country-${country.name}`),
|
||||
parent: null,
|
||||
children: [],
|
||||
internal: {
|
||||
type: `Country`,
|
||||
mediaType: `text/html`,
|
||||
content: JSON.stringify(country),
|
||||
contentDigest: createContentDigest(country),
|
||||
},
|
||||
};
|
||||
|
||||
actions.createNode({ ...country, ...nodeMeta });
|
||||
});
|
||||
}
|
||||
|
||||
export { sourceNodes };
|
||||
17250
package-lock.json
generated
Normal file
17250
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
50
package.json
Normal file
50
package.json
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
{
|
||||
"name": "uses",
|
||||
"description": "What do you uses",
|
||||
"version": "7.7.7",
|
||||
"author": "Wes Bos",
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"wesbos"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"country-emoji": "^1.5.0",
|
||||
"esm": "^3.2.25",
|
||||
"gatsby": "^2.18.12",
|
||||
"gatsby-image": "^2.2.34",
|
||||
"gatsby-plugin-manifest": "^2.2.31",
|
||||
"gatsby-plugin-offline": "^3.0.27",
|
||||
"gatsby-plugin-react-helmet": "^3.1.16",
|
||||
"gatsby-plugin-sharp": "^2.3.5",
|
||||
"gatsby-source-filesystem": "^2.1.40",
|
||||
"gatsby-transformer-sharp": "^2.3.7",
|
||||
"normalize.css": "^8.0.1",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.12.0",
|
||||
"react-dom": "^16.12.0",
|
||||
"react-helmet": "^5.2.1",
|
||||
"styled-components": "^4.4.1"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npx --node-arg '-r esm' gatsby build",
|
||||
"develop": "npx --node-arg '-r esm' gatsby develop",
|
||||
"start": "npm run develop",
|
||||
"serve": "npx --node-arg '-r esm' gatsby serve",
|
||||
"clean": "gatsby clean"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-eslint": "^9.0.0",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-config-airbnb": "^17.1.1",
|
||||
"eslint-config-prettier": "^4.3.0",
|
||||
"eslint-config-wesbos": "0.0.19",
|
||||
"eslint-plugin-html": "^5.0.5",
|
||||
"eslint-plugin-import": "^2.19.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.2.3",
|
||||
"eslint-plugin-prettier": "^3.1.2",
|
||||
"eslint-plugin-react": "^7.17.0",
|
||||
"eslint-plugin-react-hooks": "^1.7.0",
|
||||
"prettier": "^1.19.1"
|
||||
}
|
||||
}
|
||||
69
src/components/Person.js
Normal file
69
src/components/Person.js
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
import React from 'react';
|
||||
import { name } from 'country-emoji';
|
||||
import iphone from '../../public/icons/iphone.png';
|
||||
import android from '../../public/icons/android.png';
|
||||
import windows from '../../public/icons/windows.svg';
|
||||
import apple from '../../public/icons/apple.svg';
|
||||
|
||||
const icons = { iphone, android, windows, apple };
|
||||
export default function Person({ person, currentTag }) {
|
||||
const url = new URL(person.url);
|
||||
const img = `https://logo.clearbit.com/${url.host}`;
|
||||
return (
|
||||
<div className="person">
|
||||
<div className="personInner">
|
||||
<img width="50" src={img} alt={person.name} />
|
||||
<h3>
|
||||
<a href={person.url} target="_blank" rel="noopener noreferrer">
|
||||
{person.name} {person.emoji}
|
||||
</a>
|
||||
</h3>
|
||||
<a
|
||||
className="displayLink"
|
||||
href={person.url}
|
||||
>{`${url.host}${url.pathname}`}</a>
|
||||
<p>{person.description}</p>
|
||||
|
||||
<ul className="tags">
|
||||
{person.tags.map(tag => (
|
||||
<li
|
||||
key={tag}
|
||||
className={`tag ${tag === currentTag ? 'currentTag' : ''}`}
|
||||
>
|
||||
{tag}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<div className="deets">
|
||||
<span className="country" title={name(person.country)}>
|
||||
{person.country}
|
||||
</span>
|
||||
{person.computer && (
|
||||
<span title={`Computer: ${person.computer}`}>
|
||||
<img
|
||||
height="40"
|
||||
src={icons[person.computer]}
|
||||
alt={person.computer}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
{person.phone && (
|
||||
<span title={`Uses an ${person.phone}`}>
|
||||
<img height="50" src={icons[person.phone]} alt={person.phone} />
|
||||
</span>
|
||||
)}
|
||||
|
||||
{person.twitter && (
|
||||
<span>
|
||||
<a href={`https://twitter.com/${person.twitter}`}>
|
||||
<span className="at">@</span>
|
||||
{person.twitter.replace('@', '')}
|
||||
</a>
|
||||
</span>
|
||||
)}
|
||||
{person.github && <span>{person.github}</span>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
51
src/components/Topics.js
Normal file
51
src/components/Topics.js
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import React, { useContext } from 'react';
|
||||
import FilterContext from '../context/FilterContext';
|
||||
|
||||
export default function Topics() {
|
||||
const { countries, tags, currentTag, setCurrentTag } = useContext(
|
||||
FilterContext
|
||||
);
|
||||
console.log(countries);
|
||||
return (
|
||||
<div className="tags">
|
||||
{tags.map(tag => (
|
||||
<label
|
||||
className={`tag ${tag.name === currentTag ? 'currentTag' : ''}`}
|
||||
htmlFor={`filter-${tag.name}`}
|
||||
key={`filter-${tag.name}`}
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
name="tag"
|
||||
id={`filter-${tag.name}`}
|
||||
value={tag.name}
|
||||
checked={tag.name === currentTag}
|
||||
onChange={e => setCurrentTag(e.currentTarget.value)}
|
||||
/>
|
||||
{tag.name}
|
||||
<span className="count">{tag.count}</span>
|
||||
</label>
|
||||
))}
|
||||
|
||||
{countries.map(tag => (
|
||||
<label
|
||||
className={`tag ${tag.emoji === currentTag ? 'currentTag' : ''}`}
|
||||
htmlFor={`filter-${tag.name}`}
|
||||
key={`filter-${tag.name}`}
|
||||
title={tag.name}
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
name="tag"
|
||||
id={`filter-${tag.name}`}
|
||||
value={tag.emoji}
|
||||
checked={tag.emoji === currentTag}
|
||||
onChange={e => setCurrentTag(e.currentTarget.value)}
|
||||
/>
|
||||
<span className="emoji">{tag.emoji}</span>
|
||||
<span className="count">{tag.count}</span>
|
||||
</label>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
26
src/components/header.js
Normal file
26
src/components/header.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import { Link } from 'gatsby';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
|
||||
const Header = ({ siteTitle }) => (
|
||||
<header className="header">
|
||||
<div>
|
||||
<h1>
|
||||
<Link to="/">/uses</Link>
|
||||
</h1>
|
||||
<p>
|
||||
A list of <code>/uses</code> pages detailing developer setups.
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
|
||||
Header.propTypes = {
|
||||
siteTitle: PropTypes.string,
|
||||
};
|
||||
|
||||
Header.defaultProps = {
|
||||
siteTitle: ``,
|
||||
};
|
||||
|
||||
export default Header;
|
||||
32
src/components/image.js
Normal file
32
src/components/image.js
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
import React from "react"
|
||||
import { useStaticQuery, graphql } from "gatsby"
|
||||
import Img from "gatsby-image"
|
||||
|
||||
/*
|
||||
* This component is built using `gatsby-image` to automatically serve optimized
|
||||
* images with lazy loading and reduced file sizes. The image is loaded using a
|
||||
* `useStaticQuery`, which allows us to load the image from directly within this
|
||||
* component, rather than having to pass the image data down from pages.
|
||||
*
|
||||
* For more information, see the docs:
|
||||
* - `gatsby-image`: https://gatsby.dev/gatsby-image
|
||||
* - `useStaticQuery`: https://www.gatsbyjs.org/docs/use-static-query/
|
||||
*/
|
||||
|
||||
const Image = () => {
|
||||
const data = useStaticQuery(graphql`
|
||||
query {
|
||||
placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 300) {
|
||||
...GatsbyImageSharpFluid
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
return <Img fluid={data.placeholderImage.childImageSharp.fluid} />
|
||||
}
|
||||
|
||||
export default Image
|
||||
184
src/components/layout.css
Normal file
184
src/components/layout.css
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
html {
|
||||
--purple: #1e1f5c;
|
||||
--blue: #203447;
|
||||
--lightblue: #1f4662;
|
||||
--blue2: #1C2F40;
|
||||
--yellow: #ffc600;
|
||||
--pink: #EB4471;
|
||||
--vape: #d7d7d7;
|
||||
background: var(--blue);
|
||||
color: var(--vape);
|
||||
font-family: 'Fira Mono';
|
||||
font-weight: 100;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: var(--yellow);
|
||||
color: var(--blue);
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
h1,h2,h3,h4,h5,h6 {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
|
||||
h1 a {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
a {
|
||||
color: var(--yellow);
|
||||
text-decoration-color: var(--pink);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.site {
|
||||
max-width: 1900px;
|
||||
margin: 5rem;
|
||||
}
|
||||
|
||||
.header {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
font-size: 6rem;
|
||||
}
|
||||
|
||||
main {
|
||||
display: grid;
|
||||
grid-gap: 3rem;
|
||||
max-width: 1900px;
|
||||
padding: 0 3rem;
|
||||
margin: 5rem auto;
|
||||
}
|
||||
|
||||
.people {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
|
||||
grid-gap: 5rem;
|
||||
}
|
||||
|
||||
.person {
|
||||
border: 1px solid var(--vape);
|
||||
border-radius: 5.34334px;
|
||||
box-shadow: 10px -10px 0 var(--blue2);
|
||||
display: grid;
|
||||
grid-template-rows: 1fr auto auto;
|
||||
}
|
||||
|
||||
.person h3 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.personInner {
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.person .tag {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.name {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.name.last {
|
||||
font-size: 5rem;
|
||||
}
|
||||
|
||||
.deets {
|
||||
display: flex;
|
||||
border-block-start: 1px solid var(--vape);
|
||||
}
|
||||
|
||||
.deets > * {
|
||||
flex: 1;
|
||||
border-inline-start: 1px solid var(--vape);
|
||||
text-align: center;
|
||||
padding: 1rem;
|
||||
display: grid;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
grid-template-columns: auto auto;
|
||||
}
|
||||
|
||||
.deets a {
|
||||
color: var(--vape);
|
||||
}
|
||||
|
||||
.deets .at {
|
||||
color: var(--yellow);
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.deets :first-child {
|
||||
border-inline-start: none;
|
||||
}
|
||||
|
||||
.deets .country {
|
||||
font-size: 3rem;
|
||||
}
|
||||
.deets .phone {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.displayLink {
|
||||
text-decoration: none;
|
||||
color: var(--vape);
|
||||
letter-spacing: 1px;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.displayLink:hover {
|
||||
color: var(--pink);
|
||||
}
|
||||
|
||||
|
||||
.tags {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.tag {
|
||||
background: var(--pink);
|
||||
margin: 2px;
|
||||
border-radius: 3px;
|
||||
font-size: 1.7rem;
|
||||
padding: 5px;
|
||||
color: hsla(0, 100%, 100%, 0.8);
|
||||
transition: background-color 0.2s;
|
||||
cursor: pointer;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.tag input { display: none; }
|
||||
|
||||
.tag.currentTag {
|
||||
background: var(--yellow);
|
||||
color: hsla(0, 100%, 0%, 0.8);
|
||||
}
|
||||
|
||||
.tag .emoji {
|
||||
text-shadow: 0 0 1px 2px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.tag .count {
|
||||
background: var(--blue);
|
||||
font-size: 1rem;
|
||||
color: white;
|
||||
padding: 2px;
|
||||
border-radius: 2px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
46
src/components/layout.js
Normal file
46
src/components/layout.js
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* Layout component that queries for data
|
||||
* with Gatsby's useStaticQuery component
|
||||
*
|
||||
* See: https://www.gatsbyjs.org/docs/use-static-query/
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useStaticQuery, graphql } from 'gatsby';
|
||||
|
||||
import Header from './header';
|
||||
import 'normalize.css';
|
||||
import './layout.css';
|
||||
|
||||
const Layout = ({ children }) => {
|
||||
const data = useStaticQuery(graphql`
|
||||
query SiteTitleQuery {
|
||||
site {
|
||||
siteMetadata {
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header siteTitle={data.site.siteMetadata.title} />
|
||||
<main>
|
||||
{children}
|
||||
<footer>
|
||||
© {new Date().getFullYear() - Math.floor(Math.random() * 777)} Made by{' '}
|
||||
<a href="https://wesbos.com">Wes Bos</a> with{' '}
|
||||
<a href="https://www.gatsbyjs.org">Gatsby</a>. Icons from icons8.com.
|
||||
</footer>
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Layout.propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
};
|
||||
|
||||
export default Layout;
|
||||
41
src/context/FilterContext.js
Normal file
41
src/context/FilterContext.js
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import React, { createContext, useState } from 'react';
|
||||
import { useStaticQuery, graphql } from 'gatsby';
|
||||
|
||||
const FilterContext = createContext();
|
||||
|
||||
const FilterProvider = function({ children }) {
|
||||
const [currentTag, setCurrentTag] = useState('all');
|
||||
|
||||
const { allTag, allCountry } = useStaticQuery(graphql`
|
||||
query FilterQuery {
|
||||
allTag {
|
||||
nodes {
|
||||
name
|
||||
count
|
||||
}
|
||||
}
|
||||
allCountry {
|
||||
nodes {
|
||||
count
|
||||
emoji
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
return (
|
||||
<FilterContext.Provider
|
||||
value={{
|
||||
tags: allTag.nodes,
|
||||
countries: allCountry.nodes,
|
||||
currentTag,
|
||||
setCurrentTag,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</FilterContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default FilterContext;
|
||||
export { FilterProvider };
|
||||
323
src/data.js
Normal file
323
src/data.js
Normal file
|
|
@ -0,0 +1,323 @@
|
|||
// Add yourself. Insert an object at any point - it doesn't matter if you go before someone else as results are randomized.
|
||||
|
||||
// please remove the comments before You PR
|
||||
const pages = [
|
||||
{
|
||||
name: 'Wes Bos',
|
||||
// Short description
|
||||
description:
|
||||
'Maker of this site. Web Developer, Tutorial Maker, Podcaster, BBQ Lover',
|
||||
// URL to your /uses page
|
||||
url: 'https://wesbos.com/uses',
|
||||
twitter: '@wesbos',
|
||||
// An emoji that describes you
|
||||
emoji: '🔥',
|
||||
// emoji of your country's flag
|
||||
country: '🇨🇦',
|
||||
// ONE of: apple, windows or linux
|
||||
computer: 'apple',
|
||||
// iphone or android
|
||||
phone: 'iphone',
|
||||
// Tags - You can add your own, but please keep it to one word. "Social vape entrepreneur influencer denver" isn't a tag.
|
||||
|
||||
// Dev Tags: Engineer, Developer, Designer, Front End, Back End, Full Stack,
|
||||
// Other: Tags: Entrepreneur, Teacher, Podcaster, YouTuber, Blogger, Speaker,
|
||||
// Language Tags: JavaScript, PHP, Rails, Ruby, TypeScript...
|
||||
tags: [
|
||||
'Developer',
|
||||
'Full Stack',
|
||||
'Entrepreneur',
|
||||
'Teacher',
|
||||
'YouTuber',
|
||||
'JavaScript',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Troy Forster',
|
||||
description: 'Consulting Technology Director and CTO for Hire',
|
||||
url: 'https://tforster.com/uses',
|
||||
twitter: '@tforster',
|
||||
emoji: '',
|
||||
country: '🇨🇦',
|
||||
computer: 'windows',
|
||||
phone: 'android',
|
||||
tags: [
|
||||
'Engineer',
|
||||
'Back End',
|
||||
'Front End',
|
||||
'Consultant',
|
||||
'Entrepreneur',
|
||||
'JavaScript',
|
||||
'C#',
|
||||
'PHP',
|
||||
'Serverless',
|
||||
'SOA',
|
||||
'Enterprise',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Kent C. Dodds',
|
||||
description: 'JavaScript Software Engineer, speaker, and trainer',
|
||||
url: 'https://kentcdodds.com/uses',
|
||||
emoji: '🙌',
|
||||
country: '🇺🇸',
|
||||
computer: 'apple',
|
||||
phone: 'android',
|
||||
tags: [
|
||||
'Developer',
|
||||
'Full Stack',
|
||||
'Entrepreneur',
|
||||
'Teacher',
|
||||
'YouTuber',
|
||||
'JavaScript',
|
||||
'Testing',
|
||||
'React',
|
||||
'Speaker',
|
||||
'Blogger',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Glenn Reyes',
|
||||
description:
|
||||
'Independent Software Engineer, trainer & speaker. Into sports & music.',
|
||||
url: 'https://glennreyes.com/uses',
|
||||
emoji: '💃',
|
||||
country: '🇺🇸',
|
||||
computer: 'apple',
|
||||
phone: 'iphone',
|
||||
tags: [
|
||||
'Developer',
|
||||
'Front End',
|
||||
'Entrepreneur',
|
||||
'Teacher',
|
||||
'JavaScript',
|
||||
'React',
|
||||
'GraphQL',
|
||||
'TypeScript',
|
||||
'Speaker',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Adam Jahnke',
|
||||
description:
|
||||
'Caffiend, motorcyclist, climber, recovering perfectionist. I love to make the complex simple.',
|
||||
url: 'https://adamyonk.com/uses',
|
||||
emoji: '⤫',
|
||||
country: '🇺🇸',
|
||||
computer: 'apple',
|
||||
phone: 'iphone',
|
||||
tags: ['Engineer', 'Full Stack', 'JavaScript', 'Ruby'],
|
||||
},
|
||||
{
|
||||
name: 'Andrew Healey',
|
||||
description: 'Software Engineer, Writer, Learner!',
|
||||
url: 'https://healeycodes.com/uses',
|
||||
emoji: '🦉',
|
||||
country: '🇬🇧',
|
||||
computer: 'apple',
|
||||
phone: 'iphone',
|
||||
tags: ['Software Engineer', 'Full Stack', 'JavaScript', 'Python', 'Writer'],
|
||||
},
|
||||
{
|
||||
name: 'Scott Tolinski',
|
||||
description: 'Web Developer, Tutorial Maker, Podcaster, Bboy',
|
||||
url: 'https://kit.com/leveluptutorials/podcasting-screencasting-gear',
|
||||
emoji: '💪🏻',
|
||||
country: '🇺🇸',
|
||||
computer: 'apple',
|
||||
phone: 'iphone',
|
||||
tags: ['Developer', 'FrontEnd', 'Entrepreneur', 'Teacher', 'JavaScript'],
|
||||
},
|
||||
{
|
||||
name: 'Josiah Wiebe',
|
||||
description: 'Designer & developer, lifelong learner.',
|
||||
url: 'https://jwie.be/uses/',
|
||||
emoji: '🚴',
|
||||
country: '🇨🇦',
|
||||
computer: 'apple',
|
||||
phone: 'iphone',
|
||||
tags: [
|
||||
'Full Stack',
|
||||
'Developer',
|
||||
'Designer',
|
||||
'Python',
|
||||
'JavaScript',
|
||||
'TypeScript',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Benjamin Lannon',
|
||||
description: 'Web Developer, Open Source Contributor, Livestreamer',
|
||||
url: 'https://lannonbr.com/uses/',
|
||||
emoji: '🎤',
|
||||
country: '🇺🇸',
|
||||
computer: 'apple',
|
||||
phone: 'iphone',
|
||||
tags: [
|
||||
'Developer',
|
||||
'Full Stack',
|
||||
'Blogger',
|
||||
'Teacher',
|
||||
'JavaScript',
|
||||
'GraphQL',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Nuno Maduro',
|
||||
description: 'Software engineer, Open Source contributor, Speaker',
|
||||
url: 'https://nunomaduro.com/uses/',
|
||||
emoji: '🏄♂️',
|
||||
country: '🇵🇹',
|
||||
computer: 'apple',
|
||||
phone: 'iphone',
|
||||
tags: [
|
||||
'Engineer',
|
||||
'Developer',
|
||||
'Speaker',
|
||||
'PHP',
|
||||
'JavaScript',
|
||||
'TypeScript',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Adrian Marin',
|
||||
description:
|
||||
'Product-Minded Software Engineer, Digital nomad, no-nonsense enjoyer of life, friends and family.',
|
||||
url: 'https://adrianthedev.com/uses',
|
||||
twitter: '@adrianthedev',
|
||||
emoji: '🥑',
|
||||
country: '🇷🇴',
|
||||
computer: 'apple',
|
||||
phone: 'iphone',
|
||||
tags: ['Developer', 'Full Stack', 'Entrepreneur', 'Rails', 'TypeScript'],
|
||||
},
|
||||
{
|
||||
name: 'Jahir Fiquitiva',
|
||||
description: 'Passionate and Creative Full Stack Developer',
|
||||
url: 'https://jahir.dev/uses',
|
||||
twitter: '@jahirfiquitiva',
|
||||
emoji: '💎',
|
||||
country: '🇨🇴',
|
||||
computer: 'apple',
|
||||
phone: 'iphone',
|
||||
tags: [
|
||||
'Developer',
|
||||
'Full Stack',
|
||||
'JavaScript',
|
||||
'Kotlin',
|
||||
'Python',
|
||||
'Kotlin',
|
||||
'React',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Brad Garropy',
|
||||
description:
|
||||
'Self taught frontender at Adobe, into lifting and country music.',
|
||||
url: 'https://bradgarropy.com/uses',
|
||||
twitter: '@bradgarropy',
|
||||
emoji: '🤠',
|
||||
country: '🇺🇸',
|
||||
computer: 'windows',
|
||||
phone: 'android',
|
||||
tags: [
|
||||
'Developer',
|
||||
'Front End',
|
||||
'Full Stack',
|
||||
'Streamer',
|
||||
'YouTuber',
|
||||
'Blogger',
|
||||
'JavaScript',
|
||||
'Python',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Josh Barker',
|
||||
description:
|
||||
'Front end engineer at Red Ventures. Soccer enthusiast. Lover of stories.',
|
||||
url: 'https://joshuabarker.com/uses',
|
||||
twitter: '@joshuafbarker',
|
||||
emoji: '⚽️',
|
||||
country: '🇺🇸',
|
||||
computer: 'apple',
|
||||
phone: 'iphone',
|
||||
tags: ['Developer', 'Front End', 'JavaScript'],
|
||||
},
|
||||
{
|
||||
name: 'Aaron Dunphy',
|
||||
description: 'Full Stack Developer, Coffee Lover and Photo Taker',
|
||||
url: 'https://aarondunphy.com/uses',
|
||||
twitter: '@aaronjohndunphy',
|
||||
emoji: '📷',
|
||||
country: '🇬🇧',
|
||||
computer: 'apple',
|
||||
phone: 'iphone',
|
||||
tags: [
|
||||
'Developer',
|
||||
'Full Stack',
|
||||
'Back End',
|
||||
'Laravel',
|
||||
'PHP',
|
||||
'JavaScript',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Mohamed Benhida',
|
||||
description: 'Web Developer, Open source contributor.',
|
||||
url: 'http://mohamedbenhida.com/uses',
|
||||
twitter: '@simo_benhida',
|
||||
emoji: '🔥',
|
||||
country: '🇲🇦',
|
||||
computer: 'apple',
|
||||
phone: 'iphone',
|
||||
tags: [
|
||||
'Developer',
|
||||
'Full Stack',
|
||||
'Entrepreneur',
|
||||
'Teacher',
|
||||
'Back End',
|
||||
'Laravel',
|
||||
'Vuejs',
|
||||
'Tailwindcss',
|
||||
'PHP',
|
||||
'JavaScript',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Andrew McCombe',
|
||||
// Short description
|
||||
description:
|
||||
'Experienced full stack web developer with a passion for testing.',
|
||||
url: 'https://www.euperia.com/uses',
|
||||
twitter: '@euperia',
|
||||
emoji: '🏁',
|
||||
country: '🇬🇧',
|
||||
computer: 'apple',
|
||||
phone: 'android',
|
||||
tags: [
|
||||
'Developer',
|
||||
'Full Stack',
|
||||
'Back End',
|
||||
'Laravel',
|
||||
'PHP',
|
||||
'JavaScript',
|
||||
'Vue',
|
||||
'LAMP',
|
||||
'ElasticSearch',
|
||||
'AWS',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Smakosh',
|
||||
description: 'Full stack JavaScript Developer, blogger and speaker.',
|
||||
url: 'https://smakosh.com/the-tech-tools-I-use',
|
||||
twitter: '@smakosh',
|
||||
emoji: '👌',
|
||||
country: '🇲🇦',
|
||||
computer: 'apple',
|
||||
phone: 'android & iphone',
|
||||
tags: ['Developer', 'Full Stack', 'Entrepreneur', 'Blogger', 'JavaScript'],
|
||||
},
|
||||
];
|
||||
|
||||
export default pages;
|
||||
BIN
src/images/gatsby-astronaut.png
Normal file
BIN
src/images/gatsby-astronaut.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 163 KiB |
BIN
src/images/gatsby-icon.png
Normal file
BIN
src/images/gatsby-icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
11
src/pages/404.js
Normal file
11
src/pages/404.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import React from 'react';
|
||||
|
||||
import Layout from '../components/layout';
|
||||
|
||||
const NotFoundPage = () => (
|
||||
<Layout>
|
||||
<p>WHAT R U DOING HERE</p>
|
||||
</Layout>
|
||||
);
|
||||
|
||||
export default NotFoundPage;
|
||||
47
src/pages/index.js
Normal file
47
src/pages/index.js
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
import React, { useContext } from 'react';
|
||||
import { useStaticQuery, graphql } from 'gatsby';
|
||||
import FilterContext from '../context/FilterContext';
|
||||
|
||||
import Layout from '../components/layout';
|
||||
import Person from '../components/Person';
|
||||
import Topics from '../components/Topics';
|
||||
|
||||
function IndexPage() {
|
||||
const { currentTag } = useContext(FilterContext);
|
||||
const { allPerson } = useStaticQuery(graphql`
|
||||
query People {
|
||||
allPerson {
|
||||
nodes {
|
||||
computer
|
||||
country
|
||||
description
|
||||
emoji
|
||||
id
|
||||
name
|
||||
phone
|
||||
tags
|
||||
twitter
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
const people = allPerson.nodes.filter(
|
||||
person =>
|
||||
currentTag === 'all' ||
|
||||
person.tags.includes(currentTag) ||
|
||||
currentTag === person.country
|
||||
);
|
||||
return (
|
||||
<Layout>
|
||||
<Topics />
|
||||
<div className="people">
|
||||
{people.map(person => (
|
||||
<Person key={person.name} person={person} currentTag={currentTag} />
|
||||
))}
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export default IndexPage;
|
||||
51
src/util/stats.js
Normal file
51
src/util/stats.js
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import { name } from 'country-emoji';
|
||||
import people from '../data.js';
|
||||
|
||||
function merge(prop) {
|
||||
return function(acc, obj) {
|
||||
return [...obj[prop], ...acc];
|
||||
};
|
||||
}
|
||||
|
||||
function countInstances(acc, tag) {
|
||||
acc[tag] = acc[tag] ? acc[tag] + 1 : 1;
|
||||
return acc;
|
||||
}
|
||||
|
||||
export function countries() {
|
||||
const data = people
|
||||
.map(person => ({
|
||||
name: name(person.country),
|
||||
emoji: person.country,
|
||||
}))
|
||||
.reduce((acc, country) => {
|
||||
if (acc[country.name]) {
|
||||
// exists, update
|
||||
acc[country.name].count = acc[country.name].count + 1;
|
||||
} else {
|
||||
acc[country.name] = {
|
||||
...country,
|
||||
count: 1,
|
||||
};
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const sorted = Object.entries(data)
|
||||
.map(([, country]) => country)
|
||||
.sort((a, b) => b.count - a.count);
|
||||
|
||||
return sorted;
|
||||
}
|
||||
|
||||
export function tags() {
|
||||
const allTags = people.reduce(merge('tags'), []);
|
||||
const counts = allTags.reduce(countInstances, {});
|
||||
// sort and filter for any tags that only have 1
|
||||
const tags = Object.entries(counts)
|
||||
.sort(([, countA], [, countB]) => countB - countA)
|
||||
.filter(([, count]) => count > 1)
|
||||
.map(([name, count]) => ({ name, count }));
|
||||
|
||||
return [{ name: 'all', count: people.length }, ...tags];
|
||||
}
|
||||
Loading…
Reference in a new issue