-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
🧰 Frontend Infrastructure and Tooling 🛠️ #3
Changes from 16 commits
462bb39
62063bc
e9d569b
584c7fa
2906f62
3a08feb
e6c6551
225fffd
b53b4ed
cc6cb86
a5f04a9
7d21dfd
b3bcb72
57dd9ec
909cd0e
8953850
5486951
398b274
c92b293
1177252
520a10b
1b838b3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
_ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#!/bin/sh | ||
. "$(dirname "$0")/_/husky.sh" | ||
|
||
cd client | ||
node_modules/.bin/lint-staged |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module.exports = { | ||
presets: ['next/babel'], | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/** | ||
* ESLint configuration for napari hub client. All client code is linted using | ||
* this configuration. That includes JS tooling modules, configuration scripts | ||
* (next.config.js, plopfile.js, etc.), E2E tests, and application source code. | ||
* | ||
* Files with specific configurations are handled using the ESLint `overrides` | ||
* feature. We use overrides over nested `.eslintrc.js` files (for example | ||
* `src/.eslintrc.js` and `src/pages/.eslintrc.js`) to make this configuration | ||
* file the Single Source of Truth for ESLint configuration. | ||
*/ | ||
|
||
const configs = { | ||
dev: require.resolve('./eslint/dev'), | ||
e2e: require.resolve('./eslint/e2e'), | ||
react: require.resolve('./eslint/react'), | ||
tests: require.resolve('./eslint/tests'), | ||
typescript: require.resolve('./eslint/typescript'), | ||
}; | ||
|
||
module.exports = { | ||
root: true, | ||
extends: ['airbnb/base', 'prettier', configs.dev], | ||
plugins: ['simple-import-sort'], | ||
|
||
overrides: [ | ||
// TypeScript scripts | ||
{ | ||
files: ['*.ts'], | ||
extends: [configs.typescript, configs.dev], | ||
}, | ||
|
||
// Unit tests | ||
{ | ||
files: ['./src/**/*.test.ts', './jest/**/*.ts'], | ||
extends: [configs.typescript, configs.dev, configs.tests], | ||
}, | ||
|
||
// E2E tests | ||
{ | ||
files: ['./tests/**/*.ts'], | ||
extends: [configs.typescript, configs.dev, configs.e2e], | ||
}, | ||
|
||
// TypeScript and React source code. | ||
{ | ||
files: ['./src/**/*.ts', './src/**/*.tsx'], | ||
extends: [configs.typescript, configs.react], | ||
}, | ||
|
||
/* | ||
Disable explicit return types for TSX files. Prefer inferred return | ||
types for React component: | ||
https://kentcdodds.com/blog/how-to-write-a-react-component-in-typescript | ||
*/ | ||
{ | ||
files: ['./src/**/*.tsx'], | ||
rules: { | ||
'@typescript-eslint/explicit-module-boundary-types': 'off', | ||
}, | ||
}, | ||
|
||
/* | ||
Prefer default exports for Next.js pages and SCSS modules. | ||
Next.js routing needs the pages to be exported as default exports, and | ||
the team has no plans to add support for the time being: | ||
https://github.com/vercel/next.js/issues/7275 | ||
SCSS modules export from the `default` export, so their type | ||
definitions are generated using `export default styles`. | ||
*/ | ||
{ | ||
files: ['./src/pages/**/*.tsx', './src/**/*.module.scss.d.ts'], | ||
rules: { | ||
'import/no-default-export': 'off', | ||
'import/prefer-default-export': 'error', | ||
}, | ||
}, | ||
], | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
|
||
# Created by https://www.toptal.com/developers/gitignore/api/node | ||
# Edit at https://www.toptal.com/developers/gitignore?templates=node | ||
|
||
### Node ### | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
lerna-debug.log* | ||
|
||
# Diagnostic reports (https://nodejs.org/api/report.html) | ||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json | ||
|
||
# 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 | ||
*.lcov | ||
|
||
# nyc test coverage | ||
.nyc_output | ||
|
||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) | ||
.grunt | ||
|
||
# Bower dependency directory (https://bower.io/) | ||
bower_components | ||
|
||
# node-waf configuration | ||
.lock-wscript | ||
|
||
# Compiled binary addons (https://nodejs.org/api/addons.html) | ||
build/Release | ||
|
||
# Dependency directories | ||
node_modules/ | ||
jspm_packages/ | ||
|
||
# TypeScript v1 declaration files | ||
typings/ | ||
|
||
# TypeScript cache | ||
*.tsbuildinfo | ||
|
||
# Optional npm cache directory | ||
.npm | ||
|
||
# Optional eslint cache | ||
.eslintcache | ||
|
||
# Optional stylelint cache | ||
.stylelintcache | ||
|
||
# Microbundle cache | ||
.rpt2_cache/ | ||
.rts2_cache_cjs/ | ||
.rts2_cache_es/ | ||
.rts2_cache_umd/ | ||
|
||
# Optional REPL history | ||
.node_repl_history | ||
|
||
# Output of 'npm pack' | ||
*.tgz | ||
|
||
# Yarn Integrity file | ||
.yarn-integrity | ||
|
||
# dotenv environment variables file | ||
.env | ||
.env.test | ||
.env*.local | ||
|
||
# parcel-bundler cache (https://parceljs.org/) | ||
.cache | ||
.parcel-cache | ||
|
||
# Next.js build output | ||
.next | ||
|
||
# Nuxt.js build / generate output | ||
.nuxt | ||
dist | ||
|
||
# Storybook build outputs | ||
.out | ||
.storybook-out | ||
storybook-static | ||
|
||
# rollup.js default build output | ||
dist/ | ||
|
||
# Gatsby files | ||
.cache/ | ||
# Comment in the public line in if your project uses Gatsby and not Next.js | ||
# https://nextjs.org/blog/next-9-1#public-directory-support | ||
# public | ||
|
||
# vuepress build output | ||
.vuepress/dist | ||
|
||
# Serverless directories | ||
.serverless/ | ||
|
||
# FuseBox cache | ||
.fusebox/ | ||
|
||
# DynamoDB Local files | ||
.dynamodb/ | ||
|
||
# TernJS port file | ||
.tern-port | ||
|
||
# Stores VSCode versions used for testing VSCode extensions | ||
.vscode-test | ||
|
||
# Temporary folders | ||
tmp/ | ||
temp/ | ||
|
||
# End of https://www.toptal.com/developers/gitignore/api/node | ||
|
||
|
||
.vercel |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
'*.{js,ts,tsx,scss,md,yml,yaml,json}': | ||
- prettier --write | ||
'*.{js,ts,tsx}': | ||
- eslint --fix | ||
'*.scss': | ||
- stylelint --fix |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
v15.13.0 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Plop Templates don't have a prettier formatter unfortunately :( | ||
plop-templates | ||
|
||
# Package lock | ||
pnpm-lock.yaml | ||
|
||
# Next build | ||
.next | ||
|
||
# Jest snapshots | ||
*.snap |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
arrowParens: always | ||
singleQuote: true | ||
trailingComma: all | ||
tabWidth: 2 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
extends: | ||
- stylelint-config-recommended | ||
- stylelint-config-sass-guidelines | ||
- stylelint-config-css-modules | ||
|
||
rules: | ||
# Enforce camel case CSS classes for CSS modules because camel case | ||
# properties can be accessed using dot notation. For comparison: | ||
# `styles['some-class']` vs `styles.someClass` | ||
selector-class-pattern: | ||
- ^[a-z][a-zA-Z0-9]+$ | ||
- message: 'Classes should be camelCase' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah we probably just need to add There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I actually left this in on purpose to suggest extensions for the project and also enforce that VSCode use the TypeScript version in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh that's a great idea!! I didn't think of that 💡 My VSCode adds No other reasons other than that! |
||
"recommendations": [ | ||
"msjsdiag.debugger-for-chrome", | ||
"dbaeumer.vscode-eslint", | ||
"eamodio.gitlens", | ||
"ms-vscode.vscode-typescript-next", | ||
"silvenon.mdx", | ||
"esbenp.prettier-vscode", | ||
"jpoissonnier.vscode-styled-components", | ||
"bradlc.vscode-tailwindcss" | ||
] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unblocker 😆 But highly recommends this spellchecker extension too! https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I actually had to fix the location of the vscode settings too, so I went ahead and added it to the commit. I also use this extension 💯 |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"typescript.tsdk": "node_modules/typescript/lib" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# Client | ||
|
||
napari hub website implemented with Next.js and TypeScript! We use a lot of | ||
cool frontend tech for the website: | ||
|
||
- :zap: [React](https://reactjs.org/) + [Next.js](https://nextjs.org/) | ||
- :crossed_swords: [TypeScript](https://www.typescriptlang.org/) | ||
- :art: [SCSS modules](https://github.com/css-modules/css-modules) | ||
- :nail_care: [Tailwind CSS](https://tailwindcss.com/) for utility styles | ||
- :racing_car: [Tailwind JIT](https://tailwindcss.com/docs/just-in-time-mode) for on-demand Tailwind styles | ||
- :package: [pnpm](https://github.com/pnpm/pnpm) for package management | ||
- :camera_flash: [Jest](https://jestjs.io/) + [React Testing Library](https://testing-library.com/docs/react-testing-library/intro) for unit and snapshot tests | ||
- :performing_arts: [Jest](https://jestjs.io/) + [Playwright](https://github.com/microsoft/playwright) for E2E tests | ||
- :mag: [ESlint](https://eslint.org/) + [Stylelint](https://stylelint.io/) for TypeScript and SCSS linting | ||
- :gear: [Plop](https://plopjs.com/documentation/) for boilerplate automation | ||
|
||
## Setup Dev Environment | ||
|
||
### Node.js | ||
|
||
We use Node.js and various packages on NPM for building napari hub. For | ||
package management, we use [pnpm](https://github.com/pnpm/pnpm). | ||
|
||
It's recommended you use NVM so you don't have to manage multiple Node.js versions yourself: | ||
|
||
- Bash: [nvm](https://github.com/nvm-sh/nvm) | ||
- Fish: [nvm.fish](https://github.com/jorgebucaran/nvm.fish) | ||
- Zsh: [zsh-nvm](https://github.com/lukechilds/zsh-nvm) | ||
|
||
When you have NVM setup, run the following commands: | ||
|
||
```sh | ||
# Installs Node.js version defined in `.nvmrc` | ||
nvm install | ||
|
||
# Uses project defined Node.js version | ||
nvm use | ||
|
||
# Install pnpm globally | ||
npm -g install pnpm | ||
|
||
# Install project dependencies | ||
pnpm install | ||
``` | ||
|
||
## Development Mode | ||
|
||
To run the app in development mode, run the following command: | ||
|
||
```sh | ||
pnpm dev | ||
``` | ||
|
||
This will start the Next.js dev server with [fast refresh](https://nextjs.org/docs/basic-features/fast-refresh). Edit some code and watch it update in the browser without having to refresh :heart_eyes: | ||
|
||
## Plop Generators | ||
|
||
We use [Plop](https://plopjs.com/documentation/) to automate common | ||
boilerplate in the codebase. You can run Plop without any arguments and get a | ||
list of generators you can use: | ||
|
||
```sh | ||
pnpm plop | ||
``` | ||
|
||
If you want to use a specific generator, you can pass the name as the first | ||
argument: | ||
|
||
```sh | ||
# Run component generator | ||
pnpm plop component | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
module.exports = { | ||
rules: { | ||
'import/no-extraneous-dependencies': 'off', | ||
'no-console': 'off', | ||
'no-param-reassign': 'off', | ||
'no-underscore-dangle': 'off', | ||
}, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module.exports = { | ||
extends: [require.resolve('./jest'), 'plugin:jest-playwright/recommended'], | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
const { resolve } = require('path'); | ||
|
||
const pkg = require('../package.json'); | ||
|
||
module.exports = { | ||
parserOptions: { | ||
project: resolve(__dirname, '../tsconfig.jest.json'), | ||
}, | ||
|
||
extends: ['plugin:jest/recommended', 'plugin:jest/style'], | ||
|
||
settings: { | ||
/* | ||
Jest version has to be passed explicitly because ESlint throws an error | ||
about not being able to find the Jest version. This is likely due to | ||
the frontend being stored in `client/`. | ||
https://git.io/JYhAJ | ||
*/ | ||
jest: { | ||
version: pkg.devDependencies.jest, | ||
}, | ||
}, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally on precommit, my projects have been only running
prettier
and let Github Action run linters on each PR. That way we only need to run linter locally if GH action fails the linter instead of running lint on every local commit!E.g., https://github.com/chanzuckerberg/khepri/blob/develop/.github/workflows/tests.yml#L17
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds like a great idea now that I think about it. I was planning on having some GitHub actions for linting each PR too. Now that I think about it, we'd be linting every commit AND after the is released PR. So much time spent on linting when it could be done once when it's time for review. Occasionally I also find myself doing
git commit --no-verify
when doing a quick commit or while rebasing.Thank you for the suggestion, I went ahead and updated the
.lintstagedrc.yml
file 😄