Skip to content

Commit 7ecdc5c

Browse files
committed
chore: add remix app
1 parent 7368778 commit 7ecdc5c

14 files changed

+3663
-165
lines changed

apps/remix-app/.eslintrc.js

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/** @type {import('eslint').Linter.Config} */
2+
module.exports = {
3+
extends: ["@remix-run/eslint-config", "@remix-run/eslint-config/node"],
4+
};

apps/remix-app/.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
node_modules
2+
3+
/.cache
4+
/build
5+
/public/build
6+
.env

apps/remix-app/app/entry.client.tsx

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* By default, Remix will handle hydrating your app on the client for you.
3+
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
4+
* For more information, see https://remix.run/docs/en/main/file-conventions/entry.client
5+
*/
6+
7+
import { RemixBrowser } from "@remix-run/react";
8+
import { startTransition, StrictMode } from "react";
9+
import { hydrateRoot } from "react-dom/client";
10+
11+
startTransition(() => {
12+
hydrateRoot(
13+
document,
14+
<StrictMode>
15+
<RemixBrowser />
16+
</StrictMode>
17+
);
18+
});

apps/remix-app/app/entry.server.tsx

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/**
2+
* By default, Remix will handle generating the HTTP Response for you.
3+
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
4+
* For more information, see https://remix.run/docs/en/main/file-conventions/entry.server
5+
*/
6+
7+
import { PassThrough } from "node:stream";
8+
import type { EntryContext } from "@remix-run/node";
9+
import { Response } from "@remix-run/node";
10+
import { RemixServer } from "@remix-run/react";
11+
import isbot from "isbot";
12+
import { renderToPipeableStream } from "react-dom/server";
13+
14+
const ABORT_DELAY = 5_000;
15+
16+
export default function handleRequest(
17+
request: Request,
18+
responseStatusCode: number,
19+
responseHeaders: Headers,
20+
remixContext: EntryContext
21+
) {
22+
return isbot(request.headers.get("user-agent"))
23+
? handleBotRequest(
24+
request,
25+
responseStatusCode,
26+
responseHeaders,
27+
remixContext
28+
)
29+
: handleBrowserRequest(
30+
request,
31+
responseStatusCode,
32+
responseHeaders,
33+
remixContext
34+
);
35+
}
36+
37+
function handleBotRequest(
38+
request: Request,
39+
responseStatusCode: number,
40+
responseHeaders: Headers,
41+
remixContext: EntryContext
42+
) {
43+
return new Promise((resolve, reject) => {
44+
const { pipe, abort } = renderToPipeableStream(
45+
<RemixServer
46+
context={remixContext}
47+
url={request.url}
48+
abortDelay={ABORT_DELAY}
49+
/>,
50+
{
51+
onAllReady() {
52+
const body = new PassThrough();
53+
54+
responseHeaders.set("Content-Type", "text/html");
55+
56+
resolve(
57+
new Response(body, {
58+
headers: responseHeaders,
59+
status: responseStatusCode,
60+
})
61+
);
62+
63+
pipe(body);
64+
},
65+
onShellError(error: unknown) {
66+
reject(error);
67+
},
68+
onError(error: unknown) {
69+
responseStatusCode = 500;
70+
console.error(error);
71+
},
72+
}
73+
);
74+
75+
setTimeout(abort, ABORT_DELAY);
76+
});
77+
}
78+
79+
function handleBrowserRequest(
80+
request: Request,
81+
responseStatusCode: number,
82+
responseHeaders: Headers,
83+
remixContext: EntryContext
84+
) {
85+
return new Promise((resolve, reject) => {
86+
const { pipe, abort } = renderToPipeableStream(
87+
<RemixServer
88+
context={remixContext}
89+
url={request.url}
90+
abortDelay={ABORT_DELAY}
91+
/>,
92+
{
93+
onShellReady() {
94+
const body = new PassThrough();
95+
96+
responseHeaders.set("Content-Type", "text/html");
97+
98+
resolve(
99+
new Response(body, {
100+
headers: responseHeaders,
101+
status: responseStatusCode,
102+
})
103+
);
104+
105+
pipe(body);
106+
},
107+
onShellError(error: unknown) {
108+
reject(error);
109+
},
110+
onError(error: unknown) {
111+
console.error(error);
112+
responseStatusCode = 500;
113+
},
114+
}
115+
);
116+
117+
setTimeout(abort, ABORT_DELAY);
118+
});
119+
}

apps/remix-app/app/root.tsx

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { LinksFunction } from '@remix-run/node'
2+
import { Links, LiveReload, Meta, Outlet, Scripts, ScrollRestoration } from '@remix-run/react'
3+
import stylesheet from '~/tailwind.css'
4+
5+
export const links: LinksFunction = () => [{ rel: 'stylesheet', href: stylesheet }]
6+
7+
export default function App() {
8+
return (
9+
<html lang="en">
10+
<head>
11+
<meta charSet="utf-8" />
12+
<meta name="viewport" content="width=device-width,initial-scale=1" />
13+
<Meta />
14+
<Links />
15+
</head>
16+
<body>
17+
<Outlet />
18+
<ScrollRestoration />
19+
<Scripts />
20+
<LiveReload />
21+
</body>
22+
</html>
23+
)
24+
}

apps/remix-app/app/routes/_index.tsx

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import type { V2_MetaFunction } from "@remix-run/react";
2+
3+
export const meta: V2_MetaFunction = () => {
4+
return [{ title: "New Remix App" }];
5+
};
6+
7+
export default function Index() {
8+
return (
9+
<main className="flex min-h-screen flex-col items-center justify-between p-24">
10+
<div className="z-10 w-full max-w-5xl items-center justify-between font-mono text-sm lg:flex">
11+
<p className="fixed left-0 top-0 flex w-full justify-center border-b border-gray-300 bg-gradient-to-b from-zinc-200 pb-6 pt-8 backdrop-blur-2xl dark:border-neutral-800 dark:bg-zinc-800/30 dark:from-inherit lg:static lg:w-auto lg:rounded-xl lg:border lg:bg-gray-200 lg:p-4 lg:dark:bg-zinc-800/30">
12+
Get started by editing&nbsp;
13+
<code className="font-mono font-bold">pages/index.tsx</code>
14+
</p>
15+
<div className="fixed bottom-0 left-0 flex h-48 w-full items-end justify-center bg-gradient-to-t from-white via-white dark:from-black dark:via-black lg:static lg:h-auto lg:w-auto lg:bg-none">
16+
<a
17+
className="pointer-events-none flex place-items-center gap-2 p-8 lg:pointer-events-auto lg:p-0"
18+
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template-tw&utm_campaign=create-next-app"
19+
target="_blank"
20+
rel="noopener noreferrer"
21+
>
22+
By <img src="./notfound.png" alt="Vercel Logo" className="dark:invert" width={100} height={24} />
23+
</a>
24+
</div>
25+
</div>
26+
27+
<div className="relative flex place-items-center before:absolute before:h-[300px] before:w-[480px] before:-translate-x-1/2 before:rounded-full before:bg-gradient-radial before:from-white before:to-transparent before:blur-2xl before:content-[''] after:absolute after:-z-20 after:h-[180px] after:w-[240px] after:translate-x-1/3 after:bg-gradient-conic after:from-sky-200 after:via-blue-200 after:blur-2xl after:content-[''] before:dark:bg-gradient-to-br before:dark:from-transparent before:dark:to-blue-700/10 after:dark:from-sky-900 after:dark:via-[#0141ff]/40 before:lg:h-[360px]">
28+
<img className="relative dark:drop-shadow-[0_0_0.3rem_#ffffff70] dark:invert" src={'./notfound.png'} alt="Next.js Logo" width={180} height={37} />
29+
</div>
30+
31+
<div className="mb-32 grid text-center lg:mb-0 lg:grid-cols-4 lg:text-left">
32+
<a
33+
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=default-template-tw&utm_campaign=create-next-app"
34+
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
35+
target="_blank"
36+
rel="noopener noreferrer"
37+
>
38+
<h2 className={` mb-3 text-2xl font-semibold`}>
39+
Docs <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">-&gt;</span>
40+
</h2>
41+
<p className={` m-0 max-w-[30ch] text-sm opacity-50`}>Find in-depth information about Next.js features and API.</p>
42+
</a>
43+
44+
<a
45+
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=default-template-tw&utm_campaign=create-next-app"
46+
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
47+
target="_blank"
48+
rel="noopener noreferrer"
49+
>
50+
<h2 className={` mb-3 text-2xl font-semibold`}>
51+
Learn <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">-&gt;</span>
52+
</h2>
53+
<p className={` m-0 max-w-[30ch] text-sm opacity-50`}>Learn about Next.js in an interactive course with&nbsp;quizzes!</p>
54+
</a>
55+
56+
<a
57+
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=default-template-tw&utm_campaign=create-next-app"
58+
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
59+
target="_blank"
60+
rel="noopener noreferrer"
61+
>
62+
<h2 className={` mb-3 text-2xl font-semibold`}>
63+
Templates <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">-&gt;</span>
64+
</h2>
65+
<p className={` m-0 max-w-[30ch] text-sm opacity-50`}>Discover and deploy boilerplate example Next.js&nbsp;projects.</p>
66+
</a>
67+
68+
<a
69+
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=default-template-tw&utm_campaign=create-next-app"
70+
className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
71+
target="_blank"
72+
rel="noopener noreferrer"
73+
>
74+
<h2 className={` mb-3 text-2xl font-semibold`}>
75+
Deploy <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">-&gt;</span>
76+
</h2>
77+
<p className={` m-0 max-w-[30ch] text-sm opacity-50`}>Instantly deploy your Next.js site to a shareable URL with Vercel.</p>
78+
</a>
79+
</div>
80+
</main>
81+
);
82+
}

apps/remix-app/app/tailwind.css

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
@tailwind base;
2+
@tailwind components;
3+
@tailwind utilities;

apps/remix-app/package.json

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"private": true,
3+
"sideEffects": false,
4+
"scripts": {
5+
"build": "remix build",
6+
"dev": "remix dev",
7+
"start": "remix-serve build",
8+
"typecheck": "tsc",
9+
"prepare": "tw-patch"
10+
},
11+
"dependencies": {
12+
"@remix-run/node": "^1.15.0",
13+
"@remix-run/react": "^1.15.0",
14+
"@remix-run/serve": "^1.15.0",
15+
"isbot": "^3.6.8",
16+
"react": "^18.2.0",
17+
"react-dom": "^18.2.0"
18+
},
19+
"devDependencies": {
20+
"@remix-run/dev": "^1.15.0",
21+
"@remix-run/eslint-config": "^1.15.0",
22+
"@types/react": "^18.0.35",
23+
"@types/react-dom": "^18.0.11",
24+
"eslint": "^8.38.0",
25+
"tailwindcss": "^3.3.1",
26+
"tailwindcss-patch": "workspace:*",
27+
"typescript": "^4.9.3",
28+
"unplugin-tailwindcss-mangle": "workspace:*"
29+
},
30+
"engines": {
31+
"node": ">=14"
32+
}
33+
}

apps/remix-app/public/favicon.ico

16.6 KB
Binary file not shown.

apps/remix-app/remix.config.js

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/** @type {import('@remix-run/dev').AppConfig} */
2+
module.exports = {
3+
ignoredRouteFiles: ['**/.*'],
4+
// appDirectory: "app",
5+
// assetsBuildDirectory: "public/build",
6+
// serverBuildPath: "build/index.js",
7+
// publicPath: "/build/",
8+
future: {
9+
v2_errorBoundary: true,
10+
v2_meta: true,
11+
v2_normalizeFormMethod: true,
12+
v2_routeConvention: true,
13+
unstable_tailwind: true
14+
}
15+
// where to register webpack plugin ????
16+
}

apps/remix-app/remix.env.d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/// <reference types="@remix-run/dev" />
2+
/// <reference types="@remix-run/node" />

apps/remix-app/tailwind.config.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/** @type {import('tailwindcss').Config} */
2+
module.exports = {
3+
content: ['./app/**/*.{js,jsx,ts,tsx}'],
4+
theme: {
5+
extend: {}
6+
},
7+
plugins: []
8+
}

apps/remix-app/tsconfig.json

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
3+
"compilerOptions": {
4+
"lib": ["DOM", "DOM.Iterable", "ES2019"],
5+
"isolatedModules": true,
6+
"esModuleInterop": true,
7+
"jsx": "react-jsx",
8+
"moduleResolution": "node",
9+
"resolveJsonModule": true,
10+
"target": "ES2019",
11+
"strict": true,
12+
"allowJs": true,
13+
"forceConsistentCasingInFileNames": true,
14+
"baseUrl": ".",
15+
"paths": {
16+
"~/*": ["./app/*"]
17+
},
18+
19+
// Remix takes care of building everything in `remix build`.
20+
"noEmit": true
21+
}
22+
}

0 commit comments

Comments
 (0)