Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
i701 committed May 24, 2023
0 parents commit b4f09e6
Show file tree
Hide file tree
Showing 23 changed files with 13,178 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/** @type {import('eslint').Linter.Config} */
module.exports = {
extends: ["@remix-run/eslint-config", "@remix-run/eslint-config/node"],
};
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules

/.cache
/build
/public/build
.env
53 changes: 53 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Welcome to Remix!

- [Remix Docs](https://remix.run/docs)

## Development

From your terminal:

```sh
npm run dev
```

This starts your app in development mode, rebuilding assets on file changes.

## Deployment

First, build your app for production:

```sh
npm run build
```

Then run the app in production mode:

```sh
npm start
```

Now you'll need to pick a host to deploy it to.

### DIY

If you're familiar with deploying node applications, the built-in Remix app server is production-ready.

Make sure to deploy the output of `remix build`

- `build/`
- `public/build/`

### Using a Template

When you ran `npx create-remix@latest` there were a few choices for hosting. You can run that again to create a new project, then copy over your `app/` folder to the new project that's pre-configured for your target server.

```sh
cd ..
# create a new project, and pick a pre-configured host
npx create-remix@latest
cd my-new-remix-app
# remove the new project's app (not the old one!)
rm -rf app
# copy your app over
cp -R ../my-old-remix-app/app app
```
120 changes: 120 additions & 0 deletions app/components/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import React from "react"
import {
Navbar,
Typography,
Button,
IconButton,
Collapse,
} from "@material-tailwind/react"
import { Link } from "@remix-run/react"

export default function Example() {
const [openNav, setOpenNav] = React.useState(false)

React.useEffect(() => {
window.addEventListener(
"resize",
() => window.innerWidth >= 960 && setOpenNav(false)
)
}, [])

const navList = (
<ul className="mb-4 mt-2 flex flex-col gap-2 lg:mb-0 lg:mt-0 lg:flex-row lg:items-center lg:gap-6">
<Typography
as="li"
variant="small"
color="blue-gray"
className="p-1 font-normal"
>
<Link to="/todos" className="flex items-center">
Todos
</Link>
</Typography>
<Typography
as="li"
variant="small"
color="blue-gray"
className="p-1 font-normal"
>
<Link to="#" className="flex items-center">
Completed
</Link>
</Typography>
<Typography
as="li"
variant="small"
color="blue-gray"
className="p-1 font-normal"
>
<Link to="#" className="flex items-center">
Pending
</Link>
</Typography>
</ul>
)

return (
<>
<Navbar className="sticky inset-0 z-10 h-max max-w-full rounded-none py-2 px-4 lg:px-8 lg:py-4">
<div className="flex items-center justify-between text-blue-gray-900">
<Link to="/" className="mr-4 cursor-pointer py-1.5 font-medium">
Remix Todo
</Link>
<div className="flex items-center gap-4">
<div className="mr-4 hidden lg:block">{navList}</div>
<Button
variant="gradient"
size="sm"
className="hidden lg:inline-block"
>
<span>Buy Now</span>
</Button>
<IconButton
variant="text"
className="ml-auto h-6 w-6 text-inherit hover:bg-transparent focus:bg-transparent active:bg-transparent lg:hidden"
ripple={false}
onClick={() => setOpenNav(!openNav)}
>
{openNav ? (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
className="h-6 w-6"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={2}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
) : (
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-6 w-6"
fill="none"
stroke="currentColor"
strokeWidth={2}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M4 6h16M4 12h16M4 18h16"
/>
</svg>
)}
</IconButton>
</div>
</div>
<Collapse open={openNav}>
{navList}
<Button variant="gradient" size="sm" fullWidth className="mb-2">
<span>Buy Now</span>
</Button>
</Collapse>
</Navbar>
</>
)
}
21 changes: 21 additions & 0 deletions app/entry.client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* By default, Remix will handle hydrating your app on the client for you.
* 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` ✨
* For more information, see https://remix.run/file-conventions/entry.client
*/

import { RemixBrowser } from "@remix-run/react"
import { startTransition, StrictMode } from "react"
import { hydrateRoot } from "react-dom/client"
import { ThemeProvider } from "@material-tailwind/react"

startTransition(() => {
hydrateRoot(
document,
<StrictMode>
<ThemeProvider>
<RemixBrowser />
</ThemeProvider>
</StrictMode>
)
})
120 changes: 120 additions & 0 deletions app/entry.server.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/**
* By default, Remix will handle generating the HTTP Response for you.
* 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` ✨
* For more information, see https://remix.run/file-conventions/entry.server
*/

import { PassThrough } from "node:stream";

import type { EntryContext } from "@remix-run/node";
import { Response } from "@remix-run/node";
import { RemixServer } from "@remix-run/react";
import isbot from "isbot";
import { renderToPipeableStream } from "react-dom/server";

const ABORT_DELAY = 5_000;

export default function handleRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext
) {
return isbot(request.headers.get("user-agent"))
? handleBotRequest(
request,
responseStatusCode,
responseHeaders,
remixContext
)
: handleBrowserRequest(
request,
responseStatusCode,
responseHeaders,
remixContext
);
}

function handleBotRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext
) {
return new Promise((resolve, reject) => {
const { pipe, abort } = renderToPipeableStream(
<RemixServer
context={remixContext}
url={request.url}
abortDelay={ABORT_DELAY}
/>,
{
onAllReady() {
const body = new PassThrough();

responseHeaders.set("Content-Type", "text/html");

resolve(
new Response(body, {
headers: responseHeaders,
status: responseStatusCode,
})
);

pipe(body);
},
onShellError(error: unknown) {
reject(error);
},
onError(error: unknown) {
responseStatusCode = 500;
console.error(error);
},
}
);

setTimeout(abort, ABORT_DELAY);
});
}

function handleBrowserRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext
) {
return new Promise((resolve, reject) => {
const { pipe, abort } = renderToPipeableStream(
<RemixServer
context={remixContext}
url={request.url}
abortDelay={ABORT_DELAY}
/>,
{
onShellReady() {
const body = new PassThrough();

responseHeaders.set("Content-Type", "text/html");

resolve(
new Response(body, {
headers: responseHeaders,
status: responseStatusCode,
})
);

pipe(body);
},
onShellError(error: unknown) {
reject(error);
},
onError(error: unknown) {
console.error(error);
responseStatusCode = 500;
},
}
);

setTimeout(abort, ABORT_DELAY);
});
}
54 changes: 54 additions & 0 deletions app/root.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import type { LinksFunction } from "@remix-run/node"
import {
Links,
LiveReload,
Meta,
Outlet,
Scripts,
ScrollRestoration,
} from "@remix-run/react"
import type { PropsWithChildren } from "react"

import stylesheet from "~/tailwind.css"
import Navbar from "./components/Navbar"

export const links: LinksFunction = () => [
{ rel: "stylesheet", href: stylesheet },
{
rel: "stylesheet",
href: "https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap",
},
]

function Document({
children,
title = "Remix: So great, it's funny!",
}: PropsWithChildren<{ title?: string }>) {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<Meta />
<Links />
</head>
<body>
{children}
<ScrollRestoration />
<Scripts />
<LiveReload />
</body>
</html>
)
}

export default function App() {
return (
<Document>
<Navbar />
<div className="py-4 max-w-lg mx-auto">
<Outlet />
</div>
</Document>
)
}
Loading

0 comments on commit b4f09e6

Please sign in to comment.