generated from NYCPlanning/ae-remix-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 07ea193
Showing
23 changed files
with
20,575 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/** @type {import('eslint').Linter.Config} */ | ||
module.exports = { | ||
root: true, | ||
parserOptions: { | ||
ecmaVersion: "latest", | ||
sourceType: "module", | ||
ecmaFeatures: { | ||
jsx: true, | ||
}, | ||
}, | ||
env: { | ||
browser: true, | ||
commonjs: true, | ||
es6: true, | ||
}, | ||
|
||
// Base config | ||
extends: ["eslint:recommended", "plugin:prettier/recommended"], | ||
|
||
overrides: [ | ||
// React | ||
{ | ||
files: ["**/*.{js,jsx,ts,tsx}"], | ||
plugins: ["react", "jsx-a11y"], | ||
extends: [ | ||
"plugin:react/recommended", | ||
"plugin:react/jsx-runtime", | ||
"plugin:react-hooks/recommended", | ||
"plugin:jsx-a11y/recommended", | ||
], | ||
settings: { | ||
react: { | ||
version: "detect", | ||
}, | ||
formComponents: ["Form"], | ||
linkComponents: [ | ||
{ name: "Link", linkAttribute: "to" }, | ||
{ name: "NavLink", linkAttribute: "to" }, | ||
], | ||
"import/resolver": { | ||
typescript: {}, | ||
}, | ||
}, | ||
}, | ||
|
||
// Typescript | ||
{ | ||
files: ["**/*.{ts,tsx}"], | ||
plugins: ["@typescript-eslint", "import"], | ||
parser: "@typescript-eslint/parser", | ||
settings: { | ||
"import/internal-regex": "^~/", | ||
"import/resolver": { | ||
node: { | ||
extensions: [".ts", ".tsx"], | ||
}, | ||
typescript: { | ||
alwaysTryTypes: true, | ||
}, | ||
}, | ||
}, | ||
extends: [ | ||
"plugin:@typescript-eslint/recommended", | ||
"plugin:import/recommended", | ||
"plugin:import/typescript", | ||
], | ||
}, | ||
|
||
// Node | ||
{ | ||
files: [".eslintrc.cjs", "vite.config.js"], | ||
env: { | ||
node: true, | ||
}, | ||
}, | ||
], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
node_modules | ||
|
||
/.cache | ||
/build | ||
/public/build | ||
.env | ||
/test-results/ | ||
/playwright-report/ | ||
/blob-report/ | ||
/playwright/.cache/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
npx lint-staged |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
v20.12.2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Description | ||
|
||
Template for Remix applications with Deck.gl and @nycplanning/streetscape (based on Chakra UI) | ||
|
||
## Dev setup | ||
- `nvm use` | ||
- `npm i` | ||
- `npm run dev` | ||
|
||
## E2E Testing | ||
This application is currently configured to use Playwright for end to end testing. | ||
|
||
Tests should be kept in the `./tests` folder and can be run with the `npm run test` command. | ||
|
||
The `playwright.config` is used to configure tests and can be used to select which browsers we run our tests on, including mobile. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { render } from "@testing-library/react"; | ||
import { Atlas } from "./atlas.client"; | ||
|
||
describe("Atlas", () => { | ||
it("should render", () => { | ||
const { container } = render(<Atlas />); | ||
expect(container.querySelector("#deckgl-wrapper")).toBeInTheDocument(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { DeckGL } from "@deck.gl/react"; | ||
import { Map } from "react-map-gl/maplibre"; | ||
import "maplibre-gl/dist/maplibre-gl.css"; | ||
|
||
const INITIAL_VIEW_STATE = { | ||
longitude: -74.0008, | ||
latitude: 40.7018, | ||
zoom: 10, | ||
bearing: 0, | ||
pitch: 0, | ||
}; | ||
|
||
export function Atlas() { | ||
return ( | ||
<DeckGL | ||
initialViewState={INITIAL_VIEW_STATE} | ||
controller={true} | ||
style={{ height: "100vh", width: "100vw" }} | ||
> | ||
<Map | ||
mapStyle={"https://tiles.planninglabs.nyc/styles/positron/style.json"} | ||
></Map> | ||
</DeckGL> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { render, screen } from "@testing-library/react"; | ||
import { Header } from "./header"; | ||
|
||
describe("Header", () => { | ||
it("should render", () => { | ||
render(<Header />); | ||
expect(screen.getByText(/Hello world/)).toBeInTheDocument(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { Box, Button } from "@nycplanning/streetscape"; | ||
|
||
export function Header() { | ||
return ( | ||
<Box | ||
bg="gray.700" | ||
w="100%" | ||
p={4} | ||
color="white" | ||
position="absolute" | ||
zIndex={2} | ||
> | ||
<Button variant="secondary" size="sm"> | ||
Hello world! | ||
</Button> | ||
</Box> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import createEmotionCache from "@emotion/cache"; | ||
import { CacheProvider } from "@emotion/react"; | ||
import { RemixBrowser } from "@remix-run/react"; | ||
import { startTransition, StrictMode } from "react"; | ||
import { hydrateRoot } from "react-dom/client"; | ||
|
||
const hydrate = () => { | ||
const emotionCache = createEmotionCache({ key: "css" }); | ||
|
||
startTransition(() => { | ||
hydrateRoot( | ||
document, | ||
<StrictMode> | ||
<CacheProvider value={emotionCache}> | ||
<RemixBrowser /> | ||
</CacheProvider> | ||
</StrictMode>, | ||
); | ||
}); | ||
}; | ||
|
||
if (typeof requestIdleCallback === "function") { | ||
requestIdleCallback(hydrate); | ||
} else { | ||
// Safari doesn't support requestIdleCallback | ||
// https://caniuse.com/requestidlecallback | ||
setTimeout(hydrate, 1); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import { PassThrough } from "stream"; | ||
|
||
import createEmotionCache from "@emotion/cache"; | ||
import { CacheProvider as EmotionCacheProvider } from "@emotion/react"; | ||
import createEmotionServer from "@emotion/server/create-instance"; | ||
import type { EntryContext } from "@remix-run/node"; | ||
import { RemixServer } from "@remix-run/react"; | ||
import { isbot } from "isbot"; | ||
import { renderToPipeableStream } from "react-dom/server"; | ||
|
||
const ABORT_DELAY = 5000; | ||
|
||
const handleRequest = ( | ||
request: Request, | ||
responseStatusCode: number, | ||
responseHeaders: Headers, | ||
remixContext: EntryContext, | ||
) => | ||
isbot(request.headers.get("user-agent") || "") | ||
? handleBotRequest( | ||
request, | ||
responseStatusCode, | ||
responseHeaders, | ||
remixContext, | ||
) | ||
: handleBrowserRequest( | ||
request, | ||
responseStatusCode, | ||
responseHeaders, | ||
remixContext, | ||
); | ||
export default handleRequest; | ||
|
||
const handleBotRequest = ( | ||
request: Request, | ||
responseStatusCode: number, | ||
responseHeaders: Headers, | ||
remixContext: EntryContext, | ||
) => | ||
new Promise((resolve, reject) => { | ||
let didError = false; | ||
const emotionCache = createEmotionCache({ key: "css" }); | ||
|
||
const { pipe, abort } = renderToPipeableStream( | ||
<EmotionCacheProvider value={emotionCache}> | ||
<RemixServer context={remixContext} url={request.url} /> | ||
</EmotionCacheProvider>, | ||
{ | ||
onAllReady: () => { | ||
const reactBody = new PassThrough(); | ||
const emotionServer = createEmotionServer(emotionCache); | ||
|
||
const bodyWithStyles = emotionServer.renderStylesToNodeStream(); | ||
reactBody.pipe(bodyWithStyles); | ||
|
||
responseHeaders.set("Content-Type", "text/html"); | ||
|
||
resolve( | ||
new Response(bodyWithStyles as unknown as BodyInit, { | ||
headers: responseHeaders, | ||
status: didError ? 500 : responseStatusCode, | ||
}), | ||
); | ||
|
||
pipe(reactBody); | ||
}, | ||
onShellError: (error: unknown) => { | ||
reject(error); | ||
}, | ||
onError: (error: unknown) => { | ||
didError = true; | ||
|
||
console.error(error); | ||
}, | ||
}, | ||
); | ||
|
||
setTimeout(abort, ABORT_DELAY); | ||
}); | ||
|
||
const handleBrowserRequest = ( | ||
request: Request, | ||
responseStatusCode: number, | ||
responseHeaders: Headers, | ||
remixContext: EntryContext, | ||
) => | ||
new Promise((resolve, reject) => { | ||
let didError = false; | ||
const emotionCache = createEmotionCache({ key: "css" }); | ||
|
||
const { pipe, abort } = renderToPipeableStream( | ||
<EmotionCacheProvider value={emotionCache}> | ||
<RemixServer context={remixContext} url={request.url} /> | ||
</EmotionCacheProvider>, | ||
{ | ||
onShellReady: () => { | ||
const reactBody = new PassThrough(); | ||
const emotionServer = createEmotionServer(emotionCache); | ||
|
||
const bodyWithStyles = emotionServer.renderStylesToNodeStream(); | ||
reactBody.pipe(bodyWithStyles); | ||
|
||
responseHeaders.set("Content-Type", "text/html"); | ||
|
||
resolve( | ||
new Response(bodyWithStyles as unknown as BodyInit, { | ||
headers: responseHeaders, | ||
status: didError ? 500 : responseStatusCode, | ||
}), | ||
); | ||
|
||
pipe(reactBody); | ||
}, | ||
onShellError: (error: unknown) => { | ||
reject(error); | ||
}, | ||
onError: (error: unknown) => { | ||
didError = true; | ||
|
||
console.error(error); | ||
}, | ||
}, | ||
); | ||
|
||
setTimeout(abort, ABORT_DELAY); | ||
}); |
Oops, something went wrong.