Merge branch 'master' into pr/1525

This commit is contained in:
Blake Campbell 2023-04-11 23:34:13 -04:00
commit 237225749e
40 changed files with 14736 additions and 35726 deletions

13
.arc
View file

@ -1,13 +0,0 @@
@app
start-u1s
@static
@http
get /
@tables
data
scopeID *String
dataID **String
ttl TTL

View file

@ -14,7 +14,7 @@ jobs:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
node-version: 13.x
node-version: 16.x
- name: Cache/Restore node modules
uses: actions/cache@v1

View file

@ -17,7 +17,7 @@ jobs:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
node-version: 13.x
node-version: 16.x
- name: Cache/Restore node modules
uses: actions/cache@v1

6
.gitignore vendored
View file

@ -1,3 +1,4 @@
build/
# Logs
logs
*.log
@ -54,9 +55,7 @@ typings/
# dotenv environment variable files
.env*
# gatsby files
.cache/
public
# Mac files
.DS_Store
@ -78,3 +77,6 @@ haters/
.idea/
.history/
# Local Netlify folder
.netlify

1
.npmrc
View file

@ -1,3 +1,4 @@
fund=false
audit=false
legacy-peer-deps=true
shamefully-hoist=true

View file

@ -16,7 +16,7 @@
A /uses page lists a developer's setup, gear, software, and configs (what they *use*). It's a great reference for those looking to add to their library of tools or reconfigure ones they already use.
**The URL MUST to follow the format of use|uses|using|setup|environment at the end.**
**The URL MUST follow the format of use|uses|using|setup|environment at the end.**
### What Should I Include?

View file

@ -1,7 +0,0 @@
import React from 'react';
import { FilterProvider } from './src/context/FilterContext';
import './static/fonts.css';
export const wrapRootElement = ({ element }) => (
<FilterProvider>{element}</FilterProvider>
);

View file

@ -1,33 +0,0 @@
module.exports = {
siteMetadata: {
title: `/uses`,
description: `A list of /uses pages detailing developer setups.`,
author: `@wesbos`,
siteUrl: 'https://uses.tech',
},
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.
},
},
`gatsby-plugin-react-helmet`,
`gatsby-plugin-styled-components`,
],
};

View file

@ -1,91 +0,0 @@
const { tags, countries, devices, normalizeTag } = require('./src/util/stats');
const people = require('./src/data.js');
function unique(arr) {
return Array.from(new Set(arr));
}
function sourceNodes({ actions, createNodeId, createContentDigest }) {
const normalizedTagMap = tags().reduce((acc, tag) => {
const normalizedTag = normalizeTag(tag.name);
acc[normalizedTag] = tag.name;
return acc;
}, {});
// 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 normalizedPerson = {
...person,
// Clean out people that added basically the same tags twice
tags: unique(
person.tags.map((tag) => normalizedTagMap[normalizeTag(tag)] || tag)
),
};
const nodeMeta = {
id: createNodeId(`person-${normalizedPerson.name}`),
parent: null,
children: [],
internal: {
type: `Person`,
mediaType: `text/html`,
content: JSON.stringify(normalizedPerson),
contentDigest: createContentDigest(normalizedPerson),
},
};
actions.createNode({ ...normalizedPerson, ...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 });
});
// 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 });
});
// Add Devices to GraphQL API
devices().forEach((device) => {
const nodeMeta = {
id: createNodeId(`device-${device.name}`),
parent: null,
children: [],
internal: {
type: `device`,
mediaType: `text/html`,
content: JSON.stringify(device),
contentDigest: createContentDigest(device),
},
};
actions.createNode({ ...device, ...nodeMeta });
});
}
exports.sourceNodes = sourceNodes;

View file

@ -1 +0,0 @@
export { wrapRootElement } from './gatsby-browser';

View file

@ -1,103 +0,0 @@
We need to move these people over to the data.js file:
https://github.com/wesbos/awesome-uses/blob/master/src/data.js
Grab a random person, and fill out the info as best as possible.
If possible maybe ask the user on twitter to update or review theirs.
When done, check that person off.
* [x] [Wes Bos](https://wesbos.com/uses) — Web Developer, Tutorial Maker, Podcaster.
* [x] [Glenn Reyes](https://glennreyes.com/uses) - Independent Software Engineer, Trainer & Speaker.
* [x] [Smakosh](https://smakosh.com/the-tech-tools-I-use) - JavaScript Developer, indie maker.
* [ ] [Eric L. Barnes](https://ericlbarnes.com/uses/) - Laravel Developer, Maker, Writer
* [x] [Benjamin Lannon](https://lannonbr.com/uses/) - Web Developer, Open Source Contributor.
* [ ] [Thibault Maekelbergh](https://thibmaek.com/uses) - All-round developer, DIY enthousiast, record collector.
* [x] [Kent C. Dodds](https://kentcdodds.com/uses) - Web Developer, Educator, Live Streamer, Open Sourcerer.
* [ ] [Randy Oest, aka amazingrando](https://randyoest.com/uses/) - Lead Design and Frontend Engineer, Four Kitchens
* [ ] [Elijah Manor](https://elijahmanor.com/uses) - Front-End Developer and Educator
* [ ] [Dave Kiss](https://davekiss.com/uses) - Web Developer, Solopreneur, Adventurer
* [x] [Jonathan Suh](https://jonsuh.com/uses) - Designer, Developer
* [ ] [Manuel Wildauer](https://wildauer.io/uses) - Developer
* [ ] [Elliot Forbes](https://tutorialedge.net/uses/) - All-round Developer
* [ ] [Dr. Abstract](https://zimjs.com/uses/) - Founder of ZIM JavaScript Canvas Framework
* [ ] [Jay Collett](https://www.jaycollett.co/uses/) - Freelance web designer and front end developer with CraftCMS
* [ ] [Amit Merchant](https://www.amitmerchant.com/uses/) - Fullstack web developer, blogger.
* [ ] [Adam Greenough](https://adamgreenough.me/uses/) - Freelance Digital Designer & Web Developer
* [x] [Georgi Yanev](https://gyanev.com/uses/) - Web Developer, FPV drone pilot
* [ ] [Kumar Abhirup](https://kumar.now.sh/uses) - A 15yo Jnr. developer with a passion for learning 👋🏻
* [ ] [Chris Enns](https://chrisenns.com/uses/) - Podcast Editor & WordPress Wannabe
* [ ] [David Llop](https://davidllop.com/uses/) - Laravel & ChatBots Developer
* [ ] [Med Ben hartouz](https://benhartouz.com/uses/) - Fullstack Javascript Developer.
* [ ] [Łukasz Ostrowski](https://ostrowski.ninja/uses/) - Frontend developer
* [ ] [Tim Smith](https://www.iamtimsmith.com/uses) - Web developer, Blogger, and Freelancer
* [ ] [Jon Quach](https://jonquach.com/uses/) - Design Engineer
* [ ] [Tracy Osborn](https://limedaring.com/uses/) - Designer, Developer, Tech Author, Entreprenerd
* [ ] [Daniel Van Cuylenburg](https://dvanc.co/uses/) - Web Designer, Front-end Developer, Guitarist.
* [ ] [Aurel Tyson](https://aureltyson.info/uses) - iOS and backend developer
* [ ] [Nick Janetakis](https://nickjanetakis.com/uses) - Web developer, Sysadmin, Teacher
* [x] [Andrew Healey](https://healeycodes.com/uses/) - Fullstack Software Engineer, Blogger, Tutorial Creator.
* [ ] [Alex Carpenter](https://alexcarpenter.me/uses/) - Front-end Web Developer and Screencaster.
* [ ] [Wang Junxiao](http://www.feng0207.site/uses/) — Java Web Developer, Student.
* [x] [Jeff Wen](https://sinchang.me/uses/) - Web Developer, Open Source Contributor
* [ ] [Tracy Osborn](https://limedaring.com/uses/) - Designer, Developer, Tech Author, Entreprenerd
* [ ] [Bruno Brito](https://brunobrito.pt/uses/) - Web Developer, Content Creator, Digital Marketing 🇵🇹
* [ ] [Lemon 🍋](https://ahoylemon.xyz/uses/) - Web Developer, Podcaster, Human Who Makes Dumb Shit
* [ ] [Kevin Jalbert](https://kevinjalbert.com/uses/) - Developer Lead (React/Rails), Blogger.
* [x] [Swapnil Agarwal](https://swapnil.net/uses/) - Backend Developer, Aspiring Writer, Budding Designer
* [x] [Hugo Di Francesco](https://codewithhugo.com/uses/) - JavaScript Developer, Blogger
* [x] [Josiah Wiebe](https://jwie.be/uses/) - Full Stack Developer & Designer
* [ ] [Khalil Stemmler](https://khalilstemmler.com/uses/) - Fullstack Javascript Developer / Designer, Musician 🇨🇦
* [ ] [Pierre-Antoine _Leny_ Delnatte](https://leny.me/uses/) - Fullstack Web Developer, Bootcamp coach 🇧🇪
* [ ] [Harry Roberts](https://csswizardry.com/uses/) - Consultant Front-end Architect, designer, developer, writer and speaker.
* [ ] [Matt D. Smith](http://mds.is/using-stuff/) - Owner and Design Director at Studio Mds.
* [ ] [Ash Hitchcock](https://www.ashleyhitchcock.com/uses) - Front-end Developer 🇬🇧
* [ ] [Oscar te Giffel](https://oscartegiffel.com/uses/) - Fullstack Software engineer
* [ ] [John Michael Ferraris](https://jhnferraris.dev/uses/) - Fullstack Developer (that is still eager to learn), Runner
* [ ] [François Rabanel aka Pesko](https://peskoo.github.io/lasalledutemps/articles/2019-04/uses) - Fullstack Software Engineer
* [ ] [Jesse Burton](https://burtonmediainc.com/uses) - Web Developer, Freelancer, Blogger
* [ ] [Philipp John](https://www.jplace.de/uses) - Fullstack Web Developer
* [ ] [Enea Xharja](https://eneaxharja.com/uses) — Web Developer
* [ ] [Daniel Kim](https://www.danielkim.io/uses) — Software Engineer
* [ ] [Sam Baldwin](https://sambaldwin.info/uses) — Designer and front-end developer
* [ ] [Zack Eaton](https://zackeaton.com/uses/) - Student, Developer, Caffiene Enthusiast
* [x] [Brad Garropy](https://bradgarropy.com/uses) - self taught ⚛ frontender @ [adobe](https://www.adobe.com/). [blogger](https://bradgarropy.com), [streamer](https://youtube.com/bradgarropy), [tweeter](https://twitter.com/bradgarropy). 📝📺🐦
* [ ] [Stefan Zweifel](https://stefanzweifel.io/uses/) - Fullstack Web Developer
* [ ] [Ignacio Villanueva](https://ignaciodenuevo.com/uses) - Frontend Developer 🇪🇸
* [ ] [Sheree Peña](https://smariapena.com/uses) - Front Ender, Tester.
* [ ] [Pawel Grzybek](https://pawelgrzybek.com/uses/) - Software Engineer at Mindera
* [ ] [Jessica Dembe](https://www.jessicadembe.tech/uses/) - Software Engineer
* [ ] [Keziah Moselle](https://blog.keziahmoselle.fr/uses/) - Front-end developer
* [x] [Scott Zirkel](https://scottzirkel.com/uses) - Developer, Designer, Artist, Writer
* [x] [Maxence Poutord](https://www.maxpou.fr/uses/) - Front-end Engineer and Nomadic worker
* [x] [Jonathan Speek](https://speek.design/uses/) - Fullstack Developer, Designer, Musician
* [ ] [Nervewax](https://nervewax.com/uses/) - Designer / Developer
* [ ] [Niko Heikkilä](https://nikoheikkila.fi/uses/) - Backend Developer & DevOps Engineer at Paytrail
* [ ] [Sil van Diepen](https://silvandiepen.nl/uses/) - Creative Front-end Developer
* [ ] [Matthias Hampel](https://dev.to/fullstack_to/tools-services-i-use-je9) - Fullstack Software Engineer / DevOps Enthusiast
* [ ] [Ste Grainer](https://stegrainer.com/uses) - Product designer, front-end developer, and writer
* [x] [Scott Tolinski](https://kit.com/leveluptutorials/podcasting-screencasting-gear) - Web Developer, Tutorial Maker, Podcaster.
* [ ] [Ben Hong](https://www.bencodezen.io/uses/) - Senior Frontend Engineer @ Meltano GitLab
* [ ] [Danny de Vries](https://dandevri.es/uses/) - Indie Maker and Lecturer
* [x] [Scott Spence](https://scottspence.me/uses) - Web Engineer @ Karmarama
* [ ] [Stephen Senkomago Musoke](https://ssmusoke.com/uses/) - Software Engineer [METS](https://mets.or.ug/), [UCSF Informatics Hub](https://globalhealthsciences.ucsf.edu/resources/informatics-hub) & PHP lover by night 🇺🇬
* [ ] [Gideon Bamuleseyo](https://medium.com/developer-circle-kampala/what-i-use-my-tools-of-trade-552655db4b8d) - Software Engineer [Andela](https://andela.com/), JavaScript junkie 🇺🇬
* [ ] [Jason Cory Alvernaz](https://jasoncoryalvernaz.com/uses/) - Fullstack Web Developer, Freelancer, Designer
* [ ] [Freek Van der Herten](https://freek.dev/uses/) - Developer, Package Creator, Conference Speaker, Blogger 🇧🇪
* [ ] [Adam Wathan](https://adamwathan.me/uses/) - Fullstack Web Developer, Entrepeneur, Maker of courses, Speaker, Blogger, Podcaster 🇨🇦
* [x] [Josh Manders](https://joshmanders.com/uses/) - Full Snack Developer and Indie Maker 🌯
* [x] [Daniel Wirtz](https://danielwirtz.com/uses/) - Designer who codes @Crisp Studio
* [x] [Harry Wolff](https://hswolff.com/uses/) - Front-end engineer and YouTouber
* [x] [Pouria Ezzati](https://pouria.dev/uses/) - Web developer
* [x] [James Mills](https://jamesmills.co.uk/uses/) - Web Consultant
* [x] [Jeffrey Way](https://laracasts.com/blog/laracasts-uses) - Laracasts author
* [x] [Terry Godier](https://terrygodier.com/uses/) - Developer and Marketer
* [x] [David O'Trakoun](https://www.davidosomething.com/uses/) - Software Engineer
* [x] [Nuno Maduro](https://nunomaduro.com/uses/) - Software engineer, Open Source contributor, Speaker
* [x] [Erno Salo](https://endormi.io/uses/) - Full Stack Developer and Open Source Contributor
* [x] [James Brooks](https://james.brooks.page/uses/) - Software Developer at Laravel and Podcaster
* [x] [Béla Varga](http://ecmanauten.de/uses/) - Front-end Developer, Meetup & Event Organizer and UX/UI Designer
[awesome-badge]: https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg

13
netlify.toml Normal file
View file

@ -0,0 +1,13 @@
[build]
command = "remix build"
publish = "public"
[dev]
command = "remix watch"
port = 3000
autoLaunch = false
[[headers]]
for = "/build/*"
[headers.values]
"Cache-Control" = "public, max-age=31536000, s-maxage=31536000"

34825
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -5,69 +5,56 @@
"author": "Wes Bos",
"eslintConfig": {
"extends": [
"wesbos"
"wesbos/typescript"
]
},
"engines": {
"node": ">= 12"
"node": ">= 16"
},
"dependencies": {
"@actions/core": "^1.2.1",
"@actions/exec": "^1.0.3",
"@actions/github": "^2.0.1",
"@babel/core": "^7.16.7",
"@babel/eslint-parser": "^7.16.5",
"@babel/preset-react": "^7.16.7",
"@types/node": "^16.11.19",
"@typescript-eslint/eslint-plugin": "^5.9.1",
"@typescript-eslint/parser": "^5.9.1",
"@actions/core": "^1.10.0",
"@actions/exec": "^1.1.1",
"@actions/github": "^5.1.1",
"@babel/core": "^7.21.0",
"@babel/preset-react": "^7.18.6",
"@netlify/edge-functions": "^2.0.0",
"@netlify/functions": "^1.4.0",
"@netlify/remix-edge-adapter": "^1.0.0",
"@remix-run/dev": "^1.13.0",
"@remix-run/netlify": "^1.13.0",
"@remix-run/node": "^1.13.0",
"@remix-run/react": "^1.13.0",
"@remix-run/serve": "^1.13.0",
"@remix-run/server-runtime": "^1.13.0",
"@types/node": "^18.14.0",
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"country-emoji": "^1.5.6",
"eslint-config-airbnb-typescript": "^16.1.0",
"gatsby": "^4.5.0",
"gatsby-image": "^3.11.0",
"gatsby-plugin-manifest": "^4.5.0",
"gatsby-plugin-offline": "^5.5.0",
"gatsby-plugin-react-helmet": "^5.5.0",
"gatsby-plugin-sharp": "^4.5.0",
"gatsby-plugin-styled-components": "^5.5.0",
"gatsby-plugin-web-font-loader": "^1.0.4",
"gatsby-source-filesystem": "^4.5.0",
"gatsby-transformer-sharp": "^4.5.0",
"joi": "^17.5.0",
"isbot": "^3.6.6",
"joi": "^17.8.1",
"netlify-cli": "^13.0.0",
"normalize.css": "^8.0.1",
"prop-types": "^15.8.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-helmet": "^6.1.0",
"styled-components": "5.3.3",
"typescript": "^4.5.4"
"react-is": "^18.2.0",
"styled-components": "5.3.6",
"typescript": "^4.9.5"
},
"scripts": {
"build": "gatsby build",
"develop": "gatsby develop",
"start": "npm run develop",
"serve": "gatsby serve",
"clean": "gatsby clean"
"build": "netlify build",
"dev": "NODE_ENV=development netlify dev"
},
"devDependencies": {
"eslint": "^8.6.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-prettier": "^8.3.0",
"eslint-config-wesbos": "^3.0.2",
"eslint-plugin-html": "^6.2.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.28.0",
"eslint-plugin-react-hooks": "^4.3.0",
"husky": "^4.0.10",
"lint-staged": "^9.5.0",
"prettier": "^2.5.1"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
"@types/styled-components": "^5.1.26",
"eslint": "^8.34.0",
"eslint-config-wesbos": "^3.2.3",
"husky": "^8.0.3",
"lint-staged": "^13.1.2",
"postcss": "^8.4.21",
"postcss-nesting": "^11.2.1",
"prettier": "^2.8.4"
},
"lint-staged": {
"src/data.js": [

13649
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load diff

5
postcss.config.js Normal file
View file

@ -0,0 +1,5 @@
const postcssNesting = require("postcss-nesting");
module.exports = {
plugins: [postcssNesting()],
};

BIN
public/default.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 755 B

View file

@ -30,17 +30,23 @@ This readme is auto-generated from the data.js file, so please don't PR this fil
# Awesome Uses ![Awesome][awesome-badge]
* [Vladimir Vo](https://vldmr.website/uses) — Frontend developer with passion for great product design
* [uncenter](https://www.uncenter.org/uses) — Very incompetent developer
* [Donavon West](https://donavon.com/uses) — Spread Love {...❤️}
* [Justin Mahar](https://justinmahar.com/uses/) — Extremely bald Software Architect & Content Creator
* [Syofyan Zuhad](https://syofyan-profile.vercel.app/uses/) — Full Stack Software Engineer 🇮🇩
* [Zilvinas Kucinskas](https://www.ziku.dev/uses/) — Full Stack Ruby on Rails Engineer and Entrepreneur
* [Alex O'Reilly](https://alekzandriia.com/uses/) — Scientist turned Web developer from the Great White North.
* [Martin Bean](https://martinbean.dev/uses) — Web developer and software engineer.
* [Dominic Ruggiero](https://userexe.me/uses) — Student and idiot
* [Maicol Santos](https://maicolsantos.github.io/#/uses) — Front End Developer.
* [Carretta Riccardo](https://carrettariccardo.dev/uses/) — Software Developer & UX/UI Designer
* [Josh Medeski](https://www.joshmedeski.com/uses/) — Full-stack developer and content creator.
* [Simon Rogers](https://midnite.uk/uses) — Software Engineer
* [Allan Im](https://allanim.com/uses) — Software Engineer
* [Rev](https://cinnamoroll.me/uses) — A Software developer and artist based in Europe.
* [Vijay Goswmai](https://vijaygoswami.in/uses) — Full Stack Developer from Agra, Uttar Pradesh
* [Edimar Calebe Castanho](https://blog.calebe.dev.br/uses.html) — A passionate embedded systems developer from Brazil
* [Ihtisham Khan](https://iihtisham.com/uses.html) — Full-Stack Web Developer | Tech Enthusiast
* [Robb Knight](https://rknight.me/uses) — Developer, Podcaster, Lego Builder, Cat Owner
* [Riley](https://riley-uses.netlify.app/) — Software Developer
@ -189,10 +195,12 @@ This readme is auto-generated from the data.js file, so please don't PR this fil
* [Matías Hernández](https://github.com/matiasfh/uses) — Frontend Engineer, Podcaster, Father, Calisthenic Athlete
* [Sean Coker](https://sean.is/using) — Creator & Thinker. Sometimes simultaneously.
* [Michael Bonner](https://michaelbonner.dev/uses) — Full stack JavaScript and PHP developer in Salt Lake City, USA
* [Filip Kalousek](https://blog.filipkalousek.cz/uses/setup) — Frontend Developer & Idea Maker
* [Agu Valeriani](https://agustinvaleriani.com/uses) — Software developer, previously more full stack, lately focused on frontend. Enjoy traveling and gaming.
* [Yash Singh](https://www.yashsingh.us/uses) — Fullstack web software developer
* [Gabor Gyure](https://www.gaborgyure.com/uses) — Fullstack developer with lots of love for industry and engineering in Europe. In love with boardsports, the semantic and accessible web
* [Ben Brougher](https://benbrougher.tech/uses) — Full stack enterprise web devloper from the Pacific Northwest.
* [Dawit Mekonnen](https://dawit.dev/uses) — Full stack developer and javascript enthusiast.
* [Vincent Lejtzén](https://lejtzendesign.se/en/uses) — Front end developer with love for design, user experience and SEO.
* [Yves Engetschwiler](http://bee-interactive.ch/uses) — Developer, cms enthusiast, bicycle traveler, content creator, Independent at Bee Interactive
* [Sapan Bodiwala](https://sapanbodiwala.com/uses) — Full Stack Software Engineer
@ -344,7 +352,7 @@ This readme is auto-generated from the data.js file, so please don't PR this fil
* [Chris Otto](https://chrisotto.dev/uses/) — Software engineer. I enjoy JavaScript, DevOps and Testing.
* [Chris Berry](http://chrisberry.io/uses) — Designer / Developer 🦄, Linux advocate, mechanical keyboard connoisseur
* [James Quick](https://jamesqquick.com/uses) — Developer Advocate Engineer at @auth0 and content creator
* [Federico Vitale](https://fedevitale.dev/uses) — 20yo, Self Taught FullStack Developer, Full Time. Bikes lover, Tech (obviously) enthusiast.
* [Federico Vitale](https://fedevitale.dev/uses) — Software Engineer based in Rome
* [Vishwasa Navada K](https://vishwas.tech/uses) — Geek. Open source Enthusiast. Occasional blogger, photographer and traveler.
* [Silvestar Bistrović](https://www.silvestar.codes/uses/) — Fearless web engineer, CSS developer, JAMstack enthusiast, and WordPress theme specialist.
* [Adam Schwartz](https://adamschwartz.co/uses/) — Software developer, designer, film music composer
@ -370,6 +378,7 @@ This readme is auto-generated from the data.js file, so please don't PR this fil
* [Robin Bakker](https://robinbakker.nl/uses) — Web Developer
* [Alessia Bellisario](https://aless.co/uses) — Web engineer, mechanical keyboard builder, plotter art maker.
* [AriaieBOY](https://ariaieboy.ir/uses/) — Web Developer that loves creating and sharing🇩
* [Sunny](https://sny.sh/#uses) — Programmer, designer, musician, photographer and video editor.
* [Russell McWhae](https://russellmcwhae.ca/uses) — Backcountry skier, photographer, designer, and web developer from Canada
* [Karl Koch](https://www.kejk.tech/uses) — Product designer, frontend developer and musician. Building HomeHero and making other things.
* [Praveen Kumar Purushothaman](https://blog.praveen.science/my-personal-development-environment/) — Cook, Cat Lover, Front End Architect, Full Stack Web Developer Evangelist & Cloud Computing Consultant.
@ -402,6 +411,7 @@ This readme is auto-generated from the data.js file, so please don't PR this fil
* [Josiah Wiebe](https://jwie.be/uses/) — Designer & developer, lifelong learner.
* [Muhammad Oka](https://muhammadoka.dev/uses/) — Computer Science student, Cyber Security enthusiast.
* [Benjamin Lannon](https://lannonbr.com/uses/) — Web Developer, Open Source Contributor, Livestreamer
* [Dmytro Litvinov](https://dmytrolitvinov.com/uses/) — Full Stack Python developer from 🇺🇦
* [Braden Watkins](https://bradenwatkins.dev/uses) — Student, Full Stack Developer, Lover of all things analog
* [Rikin Patel](https://patelrikin.com/#uses) — Experienced Front-end developer, Passionate about Javascript
* [Joris Hens](https://www.goodbytes.be/uses) — Web development teacher, Security and hacking enthousiast, Cook.
@ -414,6 +424,7 @@ This readme is auto-generated from the data.js file, so please don't PR this fil
* [Adrian Marin](https://adrianthedev.com/uses) — Product-Minded Software Engineer, Digital nomad, no-nonsense enjoyer of life, friends and family.
* [Jahir Fiquitiva](https://jahir.dev/uses) — Passionate and Creative Full Stack Developer
* [Christophe Querton](https://kertof.com/what-i-use) — Software Engineer, xoogler, co-founder of @accelery. Full-stack, technical debt collector. Lover of the Outdoors, BBQ, sailing.
* [Adil Haddaoui](https://adilhaddaoui.com/uses) — Full stack Developer
* [Jorge Ruvalcaba](https://jorgearuv.dev/uses) — Software Engineer & Aspiring Entrepreneur who does things. Frontend at Vest
* [Michael Knepprath](https://mknepprath.com/uses) — Pokémon-obsessed Software Engineer & Designer. Twitter bots are my jam.
* [Matt TK Taylor](https://tk.gg/uses) — Product Manager in news & media
@ -643,6 +654,7 @@ This readme is auto-generated from the data.js file, so please don't PR this fil
* [Tomek Buszewski](https://www.buszewski.com/uses/) — Developer and team leader based in Warsaw, Poland.
* [Benjamin Mock](https://codesnacks.net/uses/) — coder, runner, reader, maker
* [Dan Holloran](https://danholloran.me/uses/) — Full Stack Developer
* [Sean Boult](https://boult.me/uses) — Full stack developer who likes ReactJS
* [Kevin Woblick](https://www.kovah.de/uses/) — I turn Pizza into Code and Photos
* [Michal Slepko](https://michalslepko.dev/uses) — Senior web developer learning iOS development. Live coding streamer on Twitch
* [Michał Miszczyszyn](https://typeofweb.com/michal-miszczyszyn-uses/) — Motivated full-stack developer not afraid to use any technology. Experienced developer and leader. He, him.

15
remix.config.js Normal file
View file

@ -0,0 +1,15 @@
const { config } = require("@netlify/remix-edge-adapter");
/** @type {import('@remix-run/dev').AppConfig} */
module.exports = {
...(process.env.NETLIFY || process.env.NETLIFY_LOCAL ? config : {}),
appDirectory: "src",
future: {
unstable_postcss: true,
},
ignoredRouteFiles: ["**/.*"],
server:
process.env.NETLIFY || process.env.NETLIFY_LOCAL
? "./server.js"
: undefined,
// serverBuildPath: ".netlify/functions-internal/server.js",
};

View file

@ -0,0 +1,13 @@
import people from '../src/data.js';
function stringLength(str) {
return Array.from(new Intl.Segmenter().segment(str)).length;
}
function checkEmojiLength(person) {
if(stringLength(person.emoji) > 1 && person.emoji) {
console.log(person.name, person.emoji);
}
}
people.map(checkEmojiLength);

View file

@ -111,6 +111,7 @@ module.exports.communicateValidationOutcome = async function (
].join('\n');
}
const { GITHUB_TOKEN } = process.env;
const { context } = github;
if (!GITHUB_TOKEN || !context.payload.pull_request) {
@ -120,13 +121,13 @@ module.exports.communicateValidationOutcome = async function (
core.info(`Comment contents:\n${comment}`);
return;
}
// TODO: Re-enable a way to comment on PRs that tests passed.
// const pullRequestNumber = context.payload.pull_request.number;
const pullRequestNumber = context.payload.pull_request.number;
const octokit = new github.GitHub(GITHUB_TOKEN);
await octokit.issues.createComment({
...context.repo,
issue_number: pullRequestNumber,
body: comment,
});
// const octokit = new github.getOctokit(GITHUB_TOKEN);
// await octokit.rest.pulls.createReviewComment({
// ...context.repo,
// pullRequestNumber,
// body: comment,
// });
};

20
server.ts Normal file
View file

@ -0,0 +1,20 @@
// Import path interpreted by the Remix compiler
import * as build from "@remix-run/dev/server-build";
import { createRequestHandler } from "@netlify/remix-edge-adapter";
export default createRequestHandler({
build,
// process.env.NODE_ENV is provided by Remix at compile time
mode: process.env.NODE_ENV,
});
export const config = {
cache: "manual",
path: "/*",
// Pass all assets to the netlify asset server
excluded_patterns: [
'^\\/_assets\\/[^\\/]*$',
'^\\/shared\\/[^\\/]*$',
'^\\/**\\/[^\\/]*$',
],
};

View file

@ -1,28 +1,4 @@
import React, { useState, useEffect } from 'react';
import styled from 'styled-components';
const BackToTopLink = styled.a`
position: fixed;
bottom: 1%;
right: 1%;
background: var(--pink);
color: white;
background: rgba(0, 0, 0, 0.5);
cursor: pointer;
border-radius: 3px;
padding: 1rem;
transition: opacity 0.2s;
opacity: 0;
text-decoration: none;
${props =>
props.percent > 0.25 &&
`
opacity: 1;
`}
@media screen and (max-width: 500px) {
display: none;
}
`;
function useScrollPosition() {
const [percent, setPercent] = useState(0);
@ -49,8 +25,8 @@ function useScrollPosition() {
export default function BackToTop() {
const percent = useScrollPosition();
return (
<BackToTopLink href="#top" title="Back To Top" percent={percent}>
<a className={`BackToTopLink ${percent > 0.25 ? 'Show' : ''}`} href="#top" title="Back To Top">
&uarr;
</BackToTopLink>
</a>
);
}

View file

@ -1,43 +1,29 @@
import React, { useState, useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import { name } from 'country-emoji';
import styled from 'styled-components';
import { Tag, Tags } from './Topics';
import * as icons from '../util/icons';
import { useParams } from '@remix-run/react';
function useIntersectionObserver(ref) {
const [isIntersecting, setIntersecting] = useState(false);
useEffect(function() {
const observer = new IntersectionObserver(function([entry]) {
console.log('Run once for every time its on screen');
console.log(entry);
});
// Observe the element we want to observve
observer.observe(ref.current);
return () => {
observer.unobserve(ref.current);
};
});
}
export default function Person({ person, currentTag }) {
export default function Person({ person }) {
const url = new URL(person.url);
const twitter = person.twitter ? `https://unavatar.io/${person.twitter.replace('@', '')}` : null;
const website = `https://unavatar.io/${url.host}`;
const unavatar = person.twitter ? `${twitter}?fallback=${website}` : website;
const img = `https://images.weserv.nl/?url=${unavatar}&w=100&l=9&af&il&n=-1`;
const { tag: currentTag } = useParams();
return (
<PersonWrapper>
<PersonInner>
<div className="PersonWrapper" style={{ contentVisibility: "auto", containIntrinsicHeight: '560px' }}>
<div className="PersonInner">
<header>
<img
width="50"
height="50"
src={img}
alt={person.name}
onError={({ currentTarget }) => {
currentTarget.onerror = null; // prevents looping
currentTarget.src = "/default.png";
}}
loading="lazy"
/>
<h3>
@ -57,15 +43,15 @@ export default function Person({ person, currentTag }) {
</a>
</header>
<p>{person.description}</p>
<Tags>
<ul className="Tags">
{person.tags.map(tag => (
<Tag key={tag} as="li" currentTag={tag === currentTag} small>
<li className={`Tag small ${tag === currentTag ? 'currentTag' : ''}`} key={tag}>
{tag}
</Tag>
</li>
))}
</Tags>
</PersonInner>
<PersonDeets>
</ul>
</div>
<div className="PersonDeets">
<span className="country" title={name(person.country)}>
{person.country}
</span>
@ -85,7 +71,7 @@ export default function Person({ person, currentTag }) {
)}
{person.twitter && (
<TwitterHandle>
<div className="TwitterHandle">
<a
href={`https://twitter.com/${person.twitter.replace('@', '')}`}
target="_blank"
@ -94,15 +80,14 @@ export default function Person({ person, currentTag }) {
<span className="at">@</span>
{person.twitter.replace('@', '')}
</a>
</TwitterHandle>
</div>
)}
</PersonDeets>
</PersonWrapper>
</div>
</div>
);
}
Person.propTypes = {
currentTag: PropTypes.string,
person: PropTypes.shape({
github: PropTypes.string,
name: PropTypes.string,
@ -112,7 +97,7 @@ Person.propTypes = {
tags: PropTypes.arrayOf(PropTypes.string),
country: PropTypes.string,
computer: PropTypes.oneOf(['apple', 'windows', 'linux']),
phone: PropTypes.oneOf(['iphone', 'android', 'windowsphone']),
phone: PropTypes.oneOf(['iphone', 'android', 'windowsphone', 'flipphone']),
twitter(props, propName, componentName) {
if (!/^@?(\w){1,15}$/.test(props[propName])) {
return new Error(
@ -123,97 +108,3 @@ Person.propTypes = {
},
}),
};
// Component Styles
const PersonWrapper = styled.div`
border: 1px solid var(--vape);
border-radius: 5.34334px;
box-shadow: 10px -10px 0 var(--blue2);
display: grid;
grid-template-rows: 1fr auto auto;
`;
const PersonInner = styled.div`
padding: 2rem;
h3 {
margin: 0;
a:visited {
color: var(--purple);
}
}
header {
display: grid;
grid-template-rows: auto auto;
grid-template-columns: auto 1fr;
grid-gap: 0 1rem;
@media all and (max-width: 400px) {
grid-template-columns: 1fr;
}
img {
grid-row: 1 / -1;
background: var(--lightblue);
font-size: 1rem;
}
.displayLink {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-decoration: none;
color: var(--vape);
letter-spacing: 1px;
font-size: 1.2rem;
text-overflow: ellipsis;
max-width: 100%;
overflow: hidden;
:hover,
:visited {
color: var(--pink);
}
}
}
`;
const PersonDeets = styled.div`
display: flex;
border-top: 1px solid var(--vape);
> * {
flex: 1;
border-left: 1px solid var(--vape);
text-align: center;
padding: 1rem;
display: grid;
align-items: center;
justify-content: center;
grid-template-columns: auto auto;
&:first-child {
border-left: 0;
}
}
a {
color: var(--vape);
}
.country {
font-size: 3rem;
padding-top: 2rem;
}
.phone {
padding: 0;
}
@media all and (max-width: 400px) {
display: grid;
grid-template-columns: 1fr 1fr;
> *:nth-child(1),
> *:nth-child(2) {
/* lol */
border-bottom: 1px solid var(--vape);
}
}
`;
const TwitterHandle = styled.span`
font-size: 1.24323423426928098420394802rem;
.at {
color: var(--yellow);
margin-right: 2px;
}
`;

View file

@ -1,138 +1,52 @@
import React, { useCallback, useContext } from 'react';
import styled from 'styled-components';
import FilterContext from '../context/FilterContext';
import { Link, useParams, useRouteLoaderData } from '@remix-run/react';
import * as icons from '../util/icons';
export default function Topics() {
const { countries, tags, devices, currentTag, setCurrentTag } = useContext(
FilterContext
);
const handleKeyDown = useCallback(
tagName => e => {
if (e.keyCode === 13) {
setCurrentTag(tagName);
}
},
[setCurrentTag]
);
const { tags, countries, devices } = useRouteLoaderData("root");
const params = useParams();
const currentTag = params.tag || 'all';
return (
<Tags>
{tags.map(tag => (
<Tag
currentTag={tag.name === currentTag}
htmlFor={`filter-${tag.name}`}
key={`filter-${tag.name}`}
clickable
onKeyDown={handleKeyDown(tag.name)}
tabIndex="0"
<div className="Tags">
{tags.map((tag) => (
<Link
prefetch="intent"
key={`tag-${tag.name}`}
to={
tag.name === "all" ? "/" : `/like/${encodeURIComponent(tag.name)}`
}
className={`Tag ${currentTag === tag.name ? "currentTag" : ""}`}
>
<input
type="radio"
name="tag"
id={`filter-${tag.name}`}
value={tag.name}
checked={tag.name === currentTag}
onChange={e => setCurrentTag(e.currentTarget.value)}
/>
{tag.name}
<TagCount>{tag.count}</TagCount>
</Tag>
<span className="TagCount">{tag.count}</span>
</Link>
))}
{countries.map(tag => (
<Tag
currentTag={tag.emoji === currentTag}
htmlFor={`filter-${tag.name}`}
{countries.map((tag) => (
<Link
to={`/like/${tag.emoji}`}
prefetch="intent"
className={`Tag ${currentTag === tag.emoji ? "currentTag" : ""}`}
key={`filter-${tag.name}`}
title={tag.name}
clickable
onKeyDown={handleKeyDown(tag.name)}
tabIndex="0"
>
<input
type="radio"
name="tag"
id={`filter-${tag.name}`}
value={tag.emoji}
checked={tag.emoji === currentTag}
onChange={e => setCurrentTag(e.currentTarget.value)}
/>
<TagEmoji>{tag.emoji}</TagEmoji>
<TagCount>{tag.count}</TagCount>
</Tag>
<span className="TagEmoji">{tag.emoji}</span>
<span className="TagCount">{tag.count}</span>
</Link>
))}
{devices.map(tag => (
<Tag
currentTag={tag.name === currentTag}
htmlFor={`filter-${tag.name}`}
{devices.map((tag) => (
<Link
to={`/like/${tag.name}`}
className={`Tag ${currentTag === tag.name ? "currentTag" : ""}`}
prefetch="intent"
key={`filter-${tag.name}`}
title={tag.name}
clickable
onKeyDown={handleKeyDown(tag.name)}
tabIndex="0"
>
<input
type="radio"
name="computer"
id={`filter-${tag.name}`}
value={tag.name}
checked={tag.name === currentTag}
onChange={e => setCurrentTag(e.currentTarget.value)}
/>
<img height="20px" src={icons[tag.name]} alt={tag.name} />
<TagCount>{tag.count}</TagCount>
</Tag>
<span className="TagCount">{tag.count}</span>
</Link>
))}
</Tags>
</div>
);
}
// Component Styles
const Tags = styled.ul`
list-style-type: none;
margin: 0;
padding: 0;
display: flex;
flex-wrap: wrap;
`;
const Tag = styled.label`
background: var(--pink);
margin: 2px;
border-radius: 3px;
font-size: ${props => (props.small ? `1.2rem;` : `1.7rem;`)};
padding: 5px;
color: hsla(0, 100%, 100%, 0.8);
transition: background-color 0.2s;
cursor: ${props => (props.clickable ? 'pointer' : 'default')};
display: grid;
grid-template-columns: 1fr auto;
align-items: center;
input {
display: none;
}
${props =>
props.currentTag &&
`
background: var(--yellow);
color: hsla(0, 100%, 0%, 0.8);
`}
`;
const TagEmoji = styled.span`
transform: scale(1.45);
`;
const TagCount = styled.span`
background: var(--blue);
font-size: 1rem;
color: white;
padding: 2px;
border-radius: 2px;
margin-left: 5px;
`;
export { Tag, Tags };

View file

@ -1,35 +1,23 @@
import React from 'react';
import { Link } from 'gatsby';
import PropTypes from 'prop-types';
import Helmet from 'react-helmet';
import styled from 'styled-components';
import FavIcon from './FavIcon';
function Header({ siteTitle, siteDescription, siteUrl }) {
return (
<HeaderWrapper className="header">
<div className="header HeaderWrapper">
<FavIcon />
<Helmet>
<html lang="en" amp />
<title>{siteTitle}</title>
<meta name="description" content={siteDescription} />
<link rel="canonical" href={siteUrl} />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:creator" content="@wesbos" />
<meta name="twitter:title" content={siteTitle} />
<meta name="twitter:description" content={siteDescription} />
<meta name="twitter:image" content={`${siteUrl}/twitter-card.png`} />
</Helmet>
<div>
<h1 id="top">
<Link to="/">/uses</Link>
<a href="/">/uses</a>
</h1>
<p>
A list of <code>/uses</code> pages detailing developer setups, gear,
software and configs.
</p>
</div>
</HeaderWrapper>
</div>
);
}
Header.propTypes = {
@ -45,11 +33,3 @@ Header.defaultProps = {
};
export default Header;
// Component Styles
const HeaderWrapper = styled.header`
text-align: center;
h1 {
font-size: 6rem;
}
`;

View file

@ -1,134 +1,41 @@
/**
* 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 styled, { createGlobalStyle } from 'styled-components';
import Header from './header';
import 'normalize.css';
const Layout = ({ children }) => {
const data = useStaticQuery(graphql`
query SiteTitleQuery {
site {
siteMetadata {
title
description
siteUrl
}
}
}
`);
export default function Layout({ children }) {
return (
<>
<GlobalStyle />
<Main>
<Header
siteTitle={data.site.siteMetadata.title}
siteDescription={data.site.siteMetadata.description}
siteUrl={data.site.siteMetadata.siteUrl}
/>
{children}
<footer>
<center ya-i-used-a-center-tag="sue me">
<p>
Made by <a href="https://wesbos.com">Wes Bos</a> with{' '}
<a href="https://www.gatsbyjs.org">Gatsby</a> ©{' '}
{new Date().getFullYear() - Math.floor(Math.random() * 777)}
</p>
<p>
Source on{' '}
<a href="https://github.com/wesbos/awesome-uses/">GitHub</a>. Add
yourself!
</p>
<p>
Icons from <a href="https://icons8.com">icons8.com</a>
</p>
<p>
Domain provided by <a href="https://get.tech/">.Tech</a>
</p>
<p>
Hosted on <a href="https://netlify.com">Netlify</a>
</p>
</center>
</footer>
</Main>
</>
<main className="Main">
<Header />
{children}
<footer>
<center ya-i-used-a-center-tag="sue me">
<p>
Made by <a href="https://wesbos.com">Wes Bos</a> with{" "}
<a href="https://www.remix.run">Remix</a> ©{" "}
{new Date().getFullYear()}
</p>
<p>
Source on{" "}
<a href="https://github.com/wesbos/awesome-uses/">GitHub</a>. Add
yourself!
</p>
<p>
Icons from <a href="https://icons8.com">icons8.com</a>
</p>
<p>
Domain provided by <a href="https://get.tech/">.Tech</a>
</p>
<p>
Hosted on <a href="https://netlify.com">Netlify</a>
</p>
<p suppressHydrationWarning>Rendered Fresh</p>
</center>
</footer>
</main>
);
};
Layout.propTypes = {
children: PropTypes.node.isRequired,
};
export default Layout;
// Global Styles
const GlobalStyle = createGlobalStyle`
html {
--purple: #b066ff;
--blue: #203447;
--lightblue: #1f4662;
--blue2: #1C2F40;
--yellow: #ffc600;
--pink: #EB4471;
--vape: #d7d7d7;
background: var(--blue);
color: var(--vape);
font-family: 'Fira Mono', monospace;
font-weight: 100;
font-size: 10px;
scroll-behavior: smooth;
}
body {
font-size: 2rem;
overflow-y: scroll;
}
h1,h2,h3,h4,h5,h6 {
font-weight: 500;
}
a {
color: var(--yellow);
text-decoration-color: var(--pink);
font-style: italic;
}
code {
background: var(--lightblue);
}
::selection {
background: var(--yellow);
color: var(--blue);
}
body::-webkit-scrollbar {
width: 12px;
}
html {
scrollbar-width: thin;
scrollbar-color: var(--yellow) var(--blue);
}
body::-webkit-scrollbar-track {
background: var(--blue);
}
body::-webkit-scrollbar-thumb {
background-color: var(--yellow) ;
border-radius: 6px;
border: 3px solid var(--blue);
}
`;
// Component Styles
const Main = styled.main`
display: grid;
grid-gap: 3rem;
max-width: 1900px;
padding: 0 3rem;
margin: 5rem auto;
`;

View file

@ -1,53 +0,0 @@
import React, { createContext, useState } from 'react';
import { useStaticQuery, graphql } from 'gatsby';
import PropTypes from 'prop-types';
const FilterContext = createContext();
const FilterProvider = function({ children }) {
const [currentTag, setCurrentTag] = useState('all');
const { allTag, allCountry, allDevice } = useStaticQuery(graphql`
query FilterQuery {
allTag {
nodes {
name
count
}
}
allCountry {
nodes {
count
emoji
name
}
}
allDevice {
nodes {
count
name
}
}
}
`);
return (
<FilterContext.Provider
value={{
tags: allTag.nodes,
countries: allCountry.nodes,
devices: allDevice.nodes,
currentTag,
setCurrentTag,
}}
>
{children}
</FilterContext.Provider>
);
};
FilterProvider.propTypes = {
children: PropTypes.element,
};
export default FilterContext;
export { FilterProvider };

View file

@ -21,6 +21,30 @@
* Keep this a commonjs export.
*/
module.exports = [
{
name: 'Vladimir Vo',
description: 'Frontend developer with passion for great product design',
url: 'https://vldmr.website/uses',
twitter: '@v1in_',
emoji: '🖖',
country: '🇵🇱',
computer: 'apple',
phone: 'iphone',
tags: [
'Astro',
'Front End',
'Developer',
'JavaScript',
'TypeScript',
'React',
'Next',
'JAMstack',
'Netlify',
'Vercel',
'HTML',
'CSS',
],
},
{
name: 'uncenter',
description: 'Very incompetent developer',
@ -38,6 +62,48 @@ module.exports = [
'Developer',
],
},
{
name: 'Donavon West',
description: 'Spread Love {...❤️}',
url: 'https://donavon.com/uses',
twitter: '@donavon',
emoji: '❤️',
country: '🇺🇸',
computer: 'apple',
phone: 'android',
tags: [
'API',
'Back End',
'Developer',
'Front End',
'Full Stack',
'Git',
'GitHub',
'GraphQL',
'HTML/CSS',
'JAMstack',
'JavaScript',
'macOS',
'Markdown',
'MDX',
'Netlify',
'Node.js',
'npm',
'Open Source Software',
'React',
'Remix',
'REST',
'Sass',
'SEO',
'Serverless',
'Software Developer',
'Software Engineer',
'TypeScript',
'VS Code',
'Web Developer',
'Web Development',
],
},
{
name: 'Justin Mahar',
description: 'Extremely bald Software Architect & Content Creator',
@ -148,6 +214,39 @@ module.exports = [
'Maker',
],
},
{
name: "Alex O'Reilly",
description: 'Scientist turned Web developer from the Great White North.',
url: 'https://alekzandriia.com/uses/',
twitter: '@alekzandriia',
// Allowing this multiple emoji because its cool
emoji: '🥼➡️👩‍💻',
country: '🇨🇦',
computer: 'apple',
phone: 'iphone',
tags: [
'Web Developer',
'Developer',
'Software Engineer',
'Designer',
'Full Stack',
'Front End',
'Backend',
'Wordpress',
'React',
'Gatsby',
'Javascript',
'HTML',
'CSS',
'SEO',
'Maker',
'Problem Solver',
'Artist',
'Student',
'Self Taught',
'No CS Degree',
],
},
{
name: 'Martin Bean',
description: 'Web developer and software engineer.',
@ -184,6 +283,30 @@ module.exports = [
computer: 'linux',
tags: ['Student', 'Node.js', 'Javascript', 'Ubuntu'],
},
{
name: 'Maicol Santos',
description: 'Front End Developer.',
url: 'https://maicolsantos.github.io/#/uses',
emoji: '🤘🏻',
country: '🇧🇷',
computer: 'apple',
phone: 'iphone',
tags: [
'JavaScript',
'TypeScript',
'React',
'React Native',
'Next',
'Vue.js',
'Angular',
'AlpineJS',
'Front End',
'Redux',
'React Query',
'GraphQL',
'Developer',
],
},
{
name: 'Carretta Riccardo',
description: 'Software Developer & UX/UI Designer',
@ -214,6 +337,35 @@ module.exports = [
'Designer',
],
},
{
name: 'Josh Medeski',
description: 'Full-stack developer and content creator.',
url: 'https://www.joshmedeski.com/uses/',
twitter: '@joshmedeski',
emoji: '😄',
country: '🇺🇸',
computer: 'apple',
phone: 'iphone',
tags: [
'Astro',
'CSS',
'Developer',
'Fish shell',
'Full Stack',
'JAMstack',
'Neovim',
'Netlify',
'Node.js',
'React',
'Remix',
'Remote',
'Tailwind CSS',
'Teacher',
'tmux',
'TypeScript',
'Vim',
],
},
{
name: 'Simon Rogers',
description: 'Software Engineer',
@ -303,6 +455,32 @@ module.exports = [
'UX',
],
},
{
name: 'Edimar Calebe Castanho',
description: 'A passionate embedded systems developer from Brazil',
url: 'https://blog.calebe.dev.br/uses.html',
emoji: '⚒️',
country: '🇧🇷',
computer: 'linux',
phone: 'iphone',
tags: [
'C',
'C++',
'Python',
'Node JS',
'Back End',
'Debian',
'Linux',
'FreeRTOS',
'Emacs',
'Git',
'Github',
'Gitlab',
'DevOps',
'Software Developer',
'Embedded software developer',
],
},
{
name: 'Ihtisham Khan',
description: 'Full-Stack Web Developer | Tech Enthusiast',
@ -509,7 +687,7 @@ module.exports = [
'Technologist, software creator, wannabe hacker. Father. Dog Lover.',
url: 'https://codewithlove.blog/uses',
twitter: '@amore_codes',
emoji: '👨‍💻 ',
emoji: '👨‍💻',
country: '🇺🇸',
computer: 'apple',
phone: 'iphone',
@ -1764,7 +1942,7 @@ module.exports = [
'Web Developer, open-source enthusiast, gamer, and lifelong learner.',
url: 'https://www.amrdiab.dev/uses',
twitter: '@AmrHdiab',
emoji: '🚀👨‍💻',
emoji: '👨‍💻',
country: '🇬🇧',
computer: 'windows',
phone: 'android',
@ -1793,7 +1971,7 @@ module.exports = [
'🧙‍♂️ Open Source Engineer at prestd, GitHub Star - 🏊‍♂️🚴‍♂️🏃‍♂️ Triathlete (IRONMAN distance) - 🌱 ᴘʟᴀɴᴛ-ʙᴀsᴇᴅ',
url: 'https://avelino.run/uses',
twitter: '@avelinorun',
emoji: '🏊‍♂️🚴‍♂️🏃‍♂️',
emoji: '🏊‍♂️',
country: '🇧🇷',
computer: 'apple',
phone: 'iphone',
@ -1813,7 +1991,7 @@ module.exports = [
description: 'Product Designer. Photographer. Traveler.',
url: 'https://desktopofsamuel.com/uses',
twitter: '@desktopofsamuel',
emoji: '🚀💻',
emoji: '🚀',
country: '🇭🇰',
computer: 'apple',
phone: 'iphone',
@ -1918,7 +2096,7 @@ module.exports = [
description:
'Web Developer, Product Manager, Digital Marketer, always trying to learn more.',
url: 'https://yourdigitalaid.com/uses/',
emoji: '☕☕☕☕',
emoji: '☕',
twitter: '@William65692091',
country: '🇨🇦',
computer: 'windows',
@ -3660,6 +3838,29 @@ module.exports = [
'Ionic',
],
},
{
name: 'Filip Kalousek',
description: 'Frontend Developer & Idea Maker',
url: 'https://blog.filipkalousek.cz/uses/setup',
country: '🇨🇿',
twitter: 'kalousekf',
emoji: '💡',
computer: 'windows',
phone: 'iphone',
tags: [
'Angular',
'Deno',
'TypeScript',
'PostgreSQL',
'Front End',
'Material UI',
'JavaScript',
'Vue',
'Fresh',
'Figma',
'MongoDB',
],
},
{
name: 'Agu Valeriani',
description:
@ -3770,6 +3971,32 @@ module.exports = [
'PowerShell',
],
},
{
name: 'Dawit Mekonnen',
description: 'Full stack developer and javascript enthusiast.',
url: 'https://dawit.dev/uses',
country: '🇪🇹',
emoji: '🦖',
computer: 'linux',
phone: 'android',
tags: [
'Full Stack',
'React',
'Node.js',
'TypeScript',
'Next.js',
'JavaScript',
'express.js',
'VS Code',
'HTML',
'CSS',
'PostgreSQL',
'Mongodb',
'Graphql',
'Docker',
'Hyper',
],
},
{
name: 'Vincent Lejtzén',
description:
@ -4257,7 +4484,7 @@ module.exports = [
'Fullstack Developer, Problemsolving, coffee and fancy terminaltricks!',
url: 'https://github.com/JonasJore/dotfiles/blob/master/uses-tech.md',
twitter: '@JonasJore',
emoji: '🍕',
emoji: '🍕',
country: '🇳🇴',
computer: 'linux',
phone: 'android',
@ -4277,7 +4504,7 @@ module.exports = [
description: 'Fullstack Developer',
url: 'https://marko-haberl.com/uses',
twitter: '@marko_haberl',
emoji: '🚀 💻',
emoji: '🚀',
country: '🇭🇷',
computer: 'linux',
phone: 'iphone',
@ -4319,7 +4546,7 @@ module.exports = [
description: 'Experienced Full Stack Software Engineer & Computers Lover',
url: 'https://adelrosarioh.me/uses',
twitter: '@adelrosarioh',
emoji: '💻 💻 💻',
emoji: '💻',
country: '🇩🇴',
computer: 'linux',
phone: 'android',
@ -5507,7 +5734,7 @@ module.exports = [
description: 'Software Engineer focused on Web Technologies from India.',
url: 'https://shubhambattoo.in/uses',
twitter: '@Shubham_batt',
emoji: '🖖🎧',
emoji: '🎧',
country: '🇮🇳',
computer: 'linux',
phone: 'android',
@ -5602,7 +5829,7 @@ module.exports = [
'Back end developer who likes to develop front end on free time 🤷‍♂️. And I also blog.',
url: 'https://aaronuurman.com/uses',
twitter: '@aaronuurman',
emoji: '🍕🍺',
emoji: '🍕',
country: '🇪🇪',
computer: 'linux',
phone: 'android',
@ -5691,7 +5918,7 @@ module.exports = [
'Team lead, Experienced full-stack engineer & non-stop learner. :wq',
url: 'https://www.notion.so/Things-Prakhil-uses-e995e61834c242f1b739be9f8819fb0c',
twitter: '@Prakhil_tp',
emoji: '🖮🌏🧘🔭',
emoji: '🌏',
country: '🇮🇳',
computer: 'linux',
phone: 'android',
@ -5868,7 +6095,7 @@ module.exports = [
'Full stack developer loving the Laravel ecosystem. Sometimes I write about it.',
url: 'https://clintgwinter.com/uses',
twitter: '@ClintWinter2',
emoji: '🤓⛺',
emoji: '⛺',
country: '🇺🇸',
computer: 'windows',
phone: 'android',
@ -7135,15 +7362,22 @@ module.exports = [
},
{
name: 'Federico Vitale',
description:
'20yo, Self Taught FullStack Developer, Full Time. Bikes lover, Tech (obviously) enthusiast.',
description: 'Software Engineer based in Rome',
url: 'https://fedevitale.dev/uses',
twitter: '@fedevitaledev',
emoji: '✌️',
country: '🇮🇹',
phone: 'iphone',
computer: 'apple',
tags: ['Developer', 'JavaScript', 'Go', 'Rust', 'Java', 'Full Stack'],
tags: [
'Developer',
'JavaScript',
'Go',
'Rust',
'TypeScript',
'React',
'Swift',
],
},
{
name: 'Vishwasa Navada K',
@ -7656,7 +7890,8 @@ module.exports = [
},
{
name: 'Sunny',
description: 'Programmer, designer, musician, photographer and video editor.',
description:
'Programmer, designer, musician, photographer and video editor.',
url: 'https://sny.sh/#uses',
emoji: '☀️',
country: '🇩🇪',
@ -8353,6 +8588,17 @@ module.exports = [
'GraphQL',
],
},
{
name: 'Dmytro Litvinov',
description: 'Full Stack Python developer from 🇺🇦',
url: 'https://dmytrolitvinov.com/uses/',
twitter: '@DmytroLitvinov',
emoji: '🪵',
country: '🇺🇦',
computer: 'apple',
phone: 'iphone',
tags: ['Developer', 'Web Developer', 'Full Stack', 'Python', 'Django'],
},
{
name: 'Braden Watkins',
description: 'Student, Full Stack Developer, Lover of all things analog',
@ -8608,6 +8854,35 @@ module.exports = [
'CSS',
],
},
{
name: 'Adil Haddaoui',
description: 'Full stack Developer',
url: 'https://adilhaddaoui.com/uses',
twitter: '@ADiLHADDAOUI',
emoji: '👨‍💻',
country: '🇲🇦',
computer: 'apple',
phone: 'iphone',
tags: [
'Full Stack',
'Developer',
'Javascript',
'TypeScript',
'React',
'Next.js',
'JAMStack',
'Tech Lead',
'Node.js',
'Frontend',
'MongoDB',
'GraphQL',
'CSS',
'HTML',
'Gatsby',
'SQL',
'MERN Stack',
],
},
{
name: 'Jorge Ruvalcaba',
description:
@ -10441,12 +10716,13 @@ module.exports = [
emoji: '🙃',
country: '🇬🇧',
computer: 'windows',
phone: 'android',
phone: 'iphone',
tags: [
'Developer',
'YouTuber',
'JavaScript',
'Svelte',
'SvelteKit',
'Sloths',
'Blogger',
'Speaker',
@ -10553,7 +10829,7 @@ module.exports = [
'Developer Advocate with a knack for public speaking & making videos',
url: 'https://fred.dev/uses',
twitter: '@fharper',
emoji: '✌🤦‍♂️',
emoji: '✌',
country: '🇨🇦',
computer: 'apple',
phone: 'iphone',
@ -11875,7 +12151,7 @@ module.exports = [
name: 'Thomas Large',
description: 'My name is Tom! I write code',
url: 'https://tomlarge.dev/uses',
emoji: ' 👨‍💻',
emoji: '👨‍💻',
country: '🏴󠁧󠁢󠁥󠁮󠁧󠁿',
computer: 'apple',
phone: 'iphone',
@ -13490,6 +13766,17 @@ module.exports = [
'Photographer',
],
},
{
name: 'Sean Boult',
description: 'Full stack developer who likes ReactJS',
url: 'https://boult.me/uses',
twitter: '@Hacksore',
emoji: '🫠',
country: '🇺🇸',
computer: 'apple',
phone: 'iphone',
tags: ['Full Stack', 'React', 'Typescript', 'Node.js', 'Hacking'],
},
{
name: 'Kevin Woblick',
description: 'I turn Pizza into Code and Photos',
@ -13984,7 +14271,7 @@ module.exports = [
'Javascript lover, FullStack enthusiast, React Learner (current), Pet lover',
url: 'https://gist.github.com/lakshmipriyamukundan/ddd224306ce962f4f159f1065f0f0c67',
twitter: '@lak_mee',
emoji: ':😺 ',
emoji: '😺',
country: '🇮🇳',
computer: 'linux',
phone: 'android',
@ -14119,7 +14406,7 @@ module.exports = [
description: 'Developer, writer, creator. Solutions Architect @ Vercel.',
url: 'https://leerob.io/uses',
twitter: '@leeerob',
emoji: '🏼🌴',
emoji: '🌴',
country: '🇺🇸',
computer: 'apple',
phone: 'iphone',

21
src/entry.client.tsx Normal file
View file

@ -0,0 +1,21 @@
import { RemixBrowser } from '@remix-run/react';
import { startTransition, StrictMode } from 'react';
import { hydrateRoot } from 'react-dom/client';
const hydrate = () => {
startTransition(() => {
hydrateRoot(
document,
<StrictMode>
<RemixBrowser />
</StrictMode>
);
});
};
if (window.requestIdleCallback) {
window.requestIdleCallback(hydrate);
} else {
// Safari doesn't support requestIdleCallback
// https://caniuse.com/requestidlecallback
window.setTimeout(hydrate, 1);
}

81
src/entry.server.tsx Normal file
View file

@ -0,0 +1,81 @@
import type { EntryContext } from '@remix-run/node';
import { RemixServer } from '@remix-run/react';
import { renderToReadableStream } from 'react-dom/server';
const ABORT_DELAY = 5000;
export async function streamToText(stream: ReadableStream<Uint8Array>): Promise<string> {
let result = '';
const reader = stream.pipeThrough(new TextDecoderStream()).getReader();
while (true) { // eslint-disable-line no-constant-condition
const { done, value } = await reader.read();
if (done) {
break;
}
result += value;
}
return result;
}
type CachedResponse = {
html: string;
date: Date;
}
const cache = new Map<string, CachedResponse>();
export default async function handleRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext
) {
// check if we have a cached response in memory
const cachedResponse = cache.get(request.url);
if (cachedResponse) {
// console.log('Serving from cache', request.url);
// if we have a cached response, check if it's less than 5 seconds old
const now = new Date();
const diff = now.getTime() - cachedResponse.date.getTime();
if (true || diff < 5000) {
// if it's less than 5 seconds old, return the cached response
responseHeaders.set('Content-Type', 'text/html');
return new Response(cachedResponse.html, {
headers: responseHeaders,
status: responseStatusCode,
});
}
}
let didError = false;
const chunks: Uint8Array[] = [];
const body = await renderToReadableStream(
<RemixServer context={remixContext} url={request.url} />,
{
onError: (error: unknown) => {
didError = true;
console.error(error);
}
}
);
// tee the stream so we can cache it and send it to the client
const [toReponse, toCache] = body.tee();
streamToText(toCache).then(html => {
console.log('Caching', request.url);
cache.set(request.url, {
html: html.replace('Rendered Fresh', `Rendered from cache ${new Date().toISOString()}`),
date: new Date(),
});
});
const headers = new Headers(responseHeaders);
headers.set("Content-Type", "text/html");
const response = new Response(toReponse, {
headers,
status: didError ? 500 : responseStatusCode,
});
return response;
}

View file

Before

Width:  |  Height:  |  Size: 708 KiB

After

Width:  |  Height:  |  Size: 708 KiB

View file

@ -1,62 +0,0 @@
import React, { useContext } from 'react';
import { useStaticQuery, graphql } from 'gatsby';
import styled from 'styled-components';
import FilterContext from '../context/FilterContext';
import Layout from '../components/layout';
import Person from '../components/Person';
import Topics from '../components/Topics';
import BackToTop from '../components/BackToTop';
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 ||
currentTag === person.computer ||
currentTag === person.phone
);
return (
<Layout>
<Topics />
<People>
{people.map(person => (
<Person key={person.name} person={person} currentTag={currentTag} />
))}
</People>
<BackToTop />
</Layout>
);
}
export default IndexPage;
// Component Styles
const People = styled.div`
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
grid-gap: 5rem;
@media all and (max-width: 400px) {
grid-template-columns: 1fr;
}
`;

64
src/root.tsx Normal file
View file

@ -0,0 +1,64 @@
import type { LinksFunction, MetaFunction } from '@remix-run/node';
import {
Links,
LiveReload,
Meta,
Outlet,
Scripts
} from '@remix-run/react';
import Layout from './components/layout';
import styles from './styles.css';
import { countries, devices, tags } from './util/stats';
import twitterCard from './images/twitter-card.png';
export const links: LinksFunction = () => [
{ rel: 'stylesheet', href: styles },
];
export function loader() {
return {
tags: tags(),
countries: countries(),
devices: devices(),
}
}
const metaData = {
description: `A list of /uses pages detailing developer setups.`,
siteUrl: 'https://uses.tech',
author: `@wesbos`,
title: '/uses',
}
export const meta: MetaFunction = () => ({
charset: 'utf-8',
title: '/uses',
viewport: 'width=device-width,initial-scale=1',
});
export default function App() {
return (
<html lang="en">
<head>
<Meta />
<link rel="icon" href="https://fav.farm/🖥" />
<meta name="description" content={metaData.description} />
<link rel="canonical" href={metaData.siteUrl} />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:creator" content="@wesbos" />
<meta name="twitter:title" content={metaData.title} />
<meta name="twitter:description" content={metaData.description} />
<meta name="twitter:image" content={`https://uses.tech${twitterCard}`} />
<Links />
</head>
<body>
<Layout>
<Outlet />
{/* <ScrollRestoration /> */}
<Scripts />
<LiveReload />
</Layout>
</body>
</html>
);
}

27
src/routes/index.tsx Normal file
View file

@ -0,0 +1,27 @@
import { useLoaderData, useParams } from '@remix-run/react';
import { json, LoaderArgs } from '@remix-run/server-runtime';
import React, { useContext } from 'react';
import Topics from '../components/Topics';
import BackToTop from '../components/BackToTop';
import Person from '../components/Person';
import { getPeople } from 'src/util/stats';
export async function loader({ params }: LoaderArgs) {
const people = getPeople(params.tag);
return {people};
}
export default function Index() {
const { people } = useLoaderData();
return (
<>
<Topics />
<div className="People">
{people.map(person => (
<Person key={person.name} person={person} />
))}
</div>
<BackToTop />
</>
);
}

1
src/routes/like/$tag.tsx Normal file
View file

@ -0,0 +1 @@
export { default, loader } from '../index';

290
src/styles.css Normal file
View file

@ -0,0 +1,290 @@
/* Fonts */
@font-face {
font-family: 'Fira Mono';
font-weight: 400;
font-style: normal;
src: url('./fonts/fira_mono-regular-webfont.woff2') format('woff2'),
url('./fonts/fira_mono-regular-webfont.woff') format('woff');
font-display: swap;
}
@font-face {
font-family: 'Fira Mono';
font-weight: 400;
font-style: italic;
src: url('./fonts/fira_mono-regular_italic-webfont.woff2') format('woff2'), url('../src/fonts/fira_mono-regular_italic-webfont.woff') format('woff');
font-display: swap;
}
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
/* Global Styles */
:root {
--purple: #b066ff;
--blue: #203447;
--lightblue: #1f4662;
--blue2: #1C2F40;
--yellow: #ffc600;
--pink: #EB4471;
--vape: #d7d7d7;
background: var(--blue);
color: var(--vape);
font-family: 'Fira Mono', monospace;
font-weight: 100;
font-size: 10px;
scroll-behavior: smooth;
}
body {
font-size: 2rem;
overflow-y: scroll;
margin: 0;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 500;
}
a {
color: var(--yellow);
text-decoration-color: var(--pink);
font-style: italic;
}
code {
background: var(--lightblue);
}
::selection {
background: var(--yellow);
color: var(--blue);
}
body::-webkit-scrollbar {
width: 12px;
}
html {
scrollbar-width: thin;
scrollbar-color: var(--yellow) var(--blue);
}
body::-webkit-scrollbar-track {
background: var(--blue);
}
body::-webkit-scrollbar-thumb {
background-color: var(--yellow);
border-radius: 6px;
border: 3px solid var(--blue);
}
.PersonWrapper {
border: 1px solid var(--vape);
border-radius: 5.34334px;
box-shadow: 10px -10px 0 var(--blue2);
display: grid;
grid-template-rows: 1fr auto auto;
}
.PersonInner {
padding: 2rem;
& h3 {
margin: 0;
& a:visited {
color: var(--purple);
}
}
& header {
display: grid;
grid-template-rows: auto auto;
grid-template-columns: auto 1fr;
grid-gap: 0 1rem;
@media all and (max-width: 400px) {
grid-template-columns: 1fr;
}
& img {
grid-row: 1 / -1;
font-size: 1rem;
}
& .displayLink {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-decoration: none;
color: var(--vape);
letter-spacing: 1px;
font-size: 1.2rem;
text-overflow: ellipsis;
max-width: 100%;
overflow: hidden;
&:hover,
&:visited {
color: var(--pink);
}
}
}
}
.PersonDeets {
display: flex;
border-top: 1px solid var(--vape);
>* {
flex: 1;
border-left: 1px solid var(--vape);
text-align: center;
padding: 1rem;
display: grid;
align-items: center;
justify-content: center;
grid-template-columns: auto auto;
&:first-child {
border-left: 0;
}
}
& a {
color: var(--vape);
}
& .country {
font-size: 3rem;
padding-top: 2rem;
}
& .phone {
padding: 0;
}
@media all and (max-width: 400px) {
display: grid;
grid-template-columns: 1fr 1fr;
>*:nth-child(1),
>*:nth-child(2) {
/* lol */
border-bottom: 1px solid var(--vape);
}
}
}
.TwitterHandle {
font-size: 1.24323423426928098420394802rem;
& .at {
color: var(--yellow);
margin-right: 2px;
}
}
.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;
text-decoration: none;
&.small {
font-size: 1.2rem;
}
padding: 5px;
color: hsla(0, 100%, 100%, 0.8);
transition: background-color 0.2s;
display: grid;
grid-template-columns: 1fr auto;
align-items: center;
& input {
display: none;
}
&.currentTag {
background: var(--yellow);
color: hsla(0, 100%, 0%, 0.8);
}
}
.TagEmoji {
transform: scale(1.45);
}
.TagCount {
background: var(--blue);
font-size: 1rem;
color: white;
padding: 2px;
border-radius: 2px;
margin-left: 5px;
}
.BackToTopLink {
position: fixed;
bottom: 1%;
right: 1%;
color: white;
background: rgba(0, 0, 0, 0.5);
cursor: pointer;
border-radius: 3px;
padding: 1rem;
transition: opacity 0.2s;
opacity: 0;
text-decoration: none;
&.Show {
opacity: 1;
}
@media screen and (max-width: 500px) {
display: none;
}
}
.HeaderWrapper {
text-align: center;
& 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(350px, 1fr));
grid-gap: 5rem;
@media all and (max-width: 400px) {
grid-template-columns: 1fr;
}
}

View file

@ -1,8 +1,9 @@
const { name } = require('country-emoji');
const people = require('../data.js');
import { name } from 'country-emoji';
import people from '../data.js';
type Person = typeof people[0];
function merge(prop) {
return function (acc, obj) {
function merge(prop: string) {
return function (acc: any, obj: Record<any, any>) {
// Remove duplicated values.
const values = [...new Set(obj[prop])];
return [...values, ...acc];
@ -14,24 +15,24 @@ function countInstances(acc, tag) {
return acc;
}
function normalizeTag(tag) {
export function normalizeTag(tag) {
return (
tag
// Common mispellings currently seen in the data
// Do we want to go this far?
.replace(/frontend/i, 'Front End')
.replace(/TailwindCSS/i, 'Tailwind CSS')
.replace(/backend/i, 'Back End')
.replace(/fullstack/i, 'Full Stack')
.replace(/a11y/i, 'Accessibility')
.replace(/next.?js/i, 'Next')
.replace(/react.?js/i, 'React')
// Or is lowercase enough?
.toLowerCase()
);
}
function countries() {
export function countries() {
const data = people
.map((person) => ({
name: name(person.country),
@ -52,17 +53,17 @@ function countries() {
const sorted = Object.entries(data)
.map(([, country]) => country)
.sort((a, b) => b.count - a.count);
.sort((a, b) => b.count - a.count)
.filter(Boolean);
return sorted;
}
function tags() {
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)
// Only show the tag if this topic has 3 or more people in it
.filter(([, count]) => count >= 3)
.map(([name, count]) => ({ name, count }));
@ -83,23 +84,60 @@ function tags() {
delete lowercaseTagMap[normalizedName];
}
return acc;
}, []);
}, [])
// Sort by name first
.sort((a, b) => b.name.toLowerCase() > a.name.toLowerCase())
// Sort by count
.sort((a, b) => b.count - a.count);
return [{ name: 'all', count: people.length }, ...normalizedTags];
}
function devices() {
export function devices() {
const all = [
...people.map((person) => person.computer),
...people.map((person) => person.phone),
];
].filter(Boolean);
return Object.entries(all.reduce(countInstances, {}))
.map(([device, count]) => ({ name: device, count }))
.sort((a, b) => b.count - a.count);
.sort((a, b) => b.count - a.count)
.map((device) => {
return device;
})
}
exports.normalizeTag = normalizeTag;
exports.countries = countries;
exports.tags = tags;
exports.devices = devices;
function unique(arr: string[]) {
return Array.from(new Set(arr));
}
const normalizedTagMap = tags().reduce((acc, tag) => {
const normalizedTag = normalizeTag(tag.name);
acc[normalizedTag] = tag.name;
return acc;
}, {});
export function getPeople(tag?: string) {
return [...people]
.sort(() => Math.random() - 0.5)
.map((person) => {
const normalizedPerson = {
...person,
// Clean out people that added basically the same tags twice
tags: unique(
person.tags.map((tag) => normalizedTagMap[normalizeTag(tag)] || tag)
),
};
return {
...normalizedPerson,
id: `person-${normalizedPerson.name}`,
};
})
.filter((person) => {
if (!tag) {
return true;
}
return person.tags.includes(tag) || person.country === tag || person.phone === tag || person.computer === tag;
})
}

View file

@ -1,16 +0,0 @@
/* Fonts */
@font-face {
font-family: 'Fira Mono';
font-weight: 400;
font-style: normal;
src: url('../src/fonts/fira_mono-regular-webfont.woff2') format('woff2'),
url('../src/fonts/fira_mono-regular-webfont.woff') format('woff');
font-display: swap;
}
@font-face {
font-family: 'Fira Mono';
font-weight: 400;
font-style: italic;
src: url('../src/fonts/fira_mono-regular_italic-webfont.woff2') format('woff2'), url('../src/fonts/fira_mono-regular_italic-webfont.woff') format('woff');
font-display: swap;
}

19
tsconfig.json Normal file
View file

@ -0,0 +1,19 @@
{
"include": ["remix.env.d.ts", "./**/*", "**/*.ts", "**/*.tsx"],
"compilerOptions": {
"strict": true,
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
"moduleResolution": "node",
"esModuleInterop": true,
"module": "esnext",
"target": "esnext",
"baseUrl": ".",
"allowJs": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"jsx": "react-jsx",
"noEmit": true,
"resolveJsonModule": true
}
}