Skip to content

Commit

Permalink
feat: example of remix-app
Browse files Browse the repository at this point in the history
  • Loading branch information
belgattitude committed Dec 3, 2021
1 parent b1b03f9 commit ffbd5ab
Show file tree
Hide file tree
Showing 34 changed files with 2,875 additions and 93 deletions.
5 changes: 5 additions & 0 deletions .changeset/olive-pumas-itch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'remix-app': major
---

Initial example of remix.run app
4 changes: 4 additions & 0 deletions .eslintrc.base.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ module.exports = {
},
{
files: ['*.js'],
parser: 'espree',
parserOptions: {
ecmaVersion: 2020,
},
rules: {
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/no-explicit-any': 'off',
Expand Down
34 changes: 34 additions & 0 deletions apps/remix-app/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// See ../../.eslintrc.base.js
module.exports = {
root: true,
ignorePatterns: ['public/build', 'api/build'],
extends: [
'../../.eslintrc.base.js',
// Add specific rules for react and nextjs
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:jsx-a11y/recommended',
],
// By loading testing-library as a plugin, we can only enable it
// on test files via overrides.
plugins: ['testing-library'],
env: {
browser: true,
es6: true,
node: true,
},
rules: {
'react/prop-types': 'off',
'react/react-in-jsx-scope': 'off',
'jsx-a11y/anchor-is-valid': 'off',
'react/no-unescaped-entities': 'off',
'import/no-unresolved': [2, { ignore: [`\.css$`] }],
},
overrides: [
{
// For performance run jest/recommended on test files, not regular code
files: ['**/*.test.{ts,tsx}'],
extends: ['plugin:testing-library/react'],
},
],
};
8 changes: 8 additions & 0 deletions apps/remix-app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
node_modules

.cache
.vercel
.output

public/build
api/build
34 changes: 34 additions & 0 deletions apps/remix-app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Welcome to Remix!

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

## Deployment

After having run the `create-remix` command and selected "Vercel" as a deployment target, you only need to [import your Git repository](https://vercel.com/new) into Vercel, and it will be deployed.

If you'd like to avoid using a Git repository, you can also deploy the directory by running [Vercel CLI](https://vercel.com/cli):

```sh
npm i -g vercel
vercel
```

It is generally recommended to use a Git repository, because future commits will then automatically be deployed by Vercel, through its [Git Integration](https://vercel.com/docs/concepts/git).

## Development

To run your Remix app locally, make sure your project's local dependencies are installed:

```sh
npm install
```

Afterwards, start the Remix development server like so:

```sh
npm run dev
```

Open up [http://localhost:3000](http://localhost:3000) and you should be ready to go!

If you're used to using the `vercel dev` command provided by [Vercel CLI](https://vercel.com/cli) instead, you can also use that, but it's not needed.
6 changes: 6 additions & 0 deletions apps/remix-app/api/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// @ts-check
const { createRequestHandler } = require('@remix-run/vercel');

module.exports = createRequestHandler({
build: require('./build'),
});
4 changes: 4 additions & 0 deletions apps/remix-app/app/entry.client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { hydrate } from 'react-dom';
import { RemixBrowser } from 'remix';

hydrate(<RemixBrowser />, document);
21 changes: 21 additions & 0 deletions apps/remix-app/app/entry.server.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { renderToString } from 'react-dom/server';
import { RemixServer } from 'remix';
import type { EntryContext } from 'remix';

export default function handleRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext
) {
const markup = renderToString(
<RemixServer context={remixContext} url={request.url} />
);

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

return new Response('<!DOCTYPE html>' + markup, {
status: responseStatusCode,
headers: responseHeaders,
});
}
177 changes: 177 additions & 0 deletions apps/remix-app/app/root.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
import {
Link,
Links,
LiveReload,
Meta,
Outlet,
Scripts,
ScrollRestoration,
useCatch,
} from 'remix';
import type { LinksFunction } from 'remix';

import darkStylesUrl from '~/styles/dark.css';
import globalStylesUrl from '~/styles/global.css';

// https://remix.run/api/app#links
export const links: LinksFunction = () => {
return [
{ rel: 'stylesheet', href: globalStylesUrl },
{
rel: 'stylesheet',
href: darkStylesUrl,
media: '(prefers-color-scheme: dark)',
},
];
};

// https://remix.run/api/conventions#default-export
// https://remix.run/api/conventions#route-filenames
export default function App() {
return (
<Document>
<Layout>
<Outlet />
</Layout>
</Document>
);
}

// https://remix.run/docs/en/v1/api/conventions#errorboundary
export function ErrorBoundary({ error }: { error: Error }) {
console.error(error);
return (
<Document title="Error!">
<Layout>
<div>
<h1>There was an error</h1>
<p>{error.message}</p>
<hr />
<p>
Hey, developer, you should replace this with what you want your
users to see.
</p>
</div>
</Layout>
</Document>
);
}

// https://remix.run/docs/en/v1/api/conventions#catchboundary
export function CatchBoundary() {
const caught = useCatch();

let message;
switch (caught.status) {
case 401:
message = (
<p>
Oops! Looks like you tried to visit a page that you do not have access
to.
</p>
);
break;
case 404:
message = (
<p>Oops! Looks like you tried to visit a page that does not exist.</p>
);
break;

default:
throw new Error(caught.data || caught.statusText);
}

return (
<Document title={`${caught.status} ${caught.statusText}`}>
<Layout>
<h1>
{caught.status}: {caught.statusText}
</h1>
{message}
</Layout>
</Document>
);
}

function Document({
children,
title,
}: {
children: React.ReactNode;
title?: string;
}) {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
{title ? <title>{title}</title> : null}
<Meta />
<Links />
</head>
<body>
{children}
<ScrollRestoration />
<Scripts />
{process.env.NODE_ENV === 'development' && <LiveReload />}
</body>
</html>
);
}

function Layout({ children }: { children: React.ReactNode }) {
return (
<div className="remix-app">
<header className="remix-app__header">
<div className="container remix-app__header-content">
<Link to="/" title="Remix" className="remix-app__header-home-link">
<RemixLogo />
</Link>
<nav aria-label="Main navigation" className="remix-app__header-nav">
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<a href="https://remix.run/docs">Remix Docs</a>
</li>
<li>
<a href="https://github.com/remix-run/remix">GitHub</a>
</li>
</ul>
</nav>
</div>
</header>
<div className="remix-app__main">
<div className="container remix-app__main-content">{children}</div>
</div>
<footer className="remix-app__footer">
<div className="container remix-app__footer-content">
<p>&copy; You!</p>
</div>
</footer>
</div>
);
}

function RemixLogo() {
return (
<svg
viewBox="0 0 659 165"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
aria-labelledby="remix-run-logo-title"
role="img"
width="106"
height="30"
fill="currentColor">
<title id="remix-run-logo-title">Remix Logo</title>
<path d="M0 161V136H45.5416C53.1486 136 54.8003 141.638 54.8003 145V161H0Z M133.85 124.16C135.3 142.762 135.3 151.482 135.3 161H92.2283C92.2283 158.927 92.2653 157.03 92.3028 155.107C92.4195 149.128 92.5411 142.894 91.5717 130.304C90.2905 111.872 82.3473 107.776 67.7419 107.776H54.8021H0V74.24H69.7918C88.2407 74.24 97.4651 68.632 97.4651 53.784C97.4651 40.728 88.2407 32.816 69.7918 32.816H0V0H77.4788C119.245 0 140 19.712 140 51.2C140 74.752 125.395 90.112 105.665 92.672C122.32 96 132.057 105.472 133.85 124.16Z" />
<path d="M229.43 120.576C225.59 129.536 218.422 133.376 207.158 133.376C194.614 133.376 184.374 126.72 183.35 112.64H263.478V101.12C263.478 70.1437 243.254 44.0317 205.11 44.0317C169.526 44.0317 142.902 69.8877 142.902 105.984C142.902 142.336 169.014 164.352 205.622 164.352C235.83 164.352 256.822 149.76 262.71 123.648L229.43 120.576ZM183.862 92.6717C185.398 81.9197 191.286 73.7277 204.598 73.7277C216.886 73.7277 223.542 82.4317 224.054 92.6717H183.862Z" />
<path d="M385.256 66.5597C380.392 53.2477 369.896 44.0317 349.672 44.0317C332.52 44.0317 320.232 51.7117 314.088 64.2557V47.1037H272.616V161.28H314.088V105.216C314.088 88.0638 318.952 76.7997 332.52 76.7997C345.064 76.7997 348.136 84.9917 348.136 100.608V161.28H389.608V105.216C389.608 88.0638 394.216 76.7997 408.04 76.7997C420.584 76.7997 423.4 84.9917 423.4 100.608V161.28H464.872V89.5997C464.872 65.7917 455.656 44.0317 424.168 44.0317C404.968 44.0317 391.4 53.7597 385.256 66.5597Z" />
<path d="M478.436 47.104V161.28H519.908V47.104H478.436ZM478.18 36.352H520.164V0H478.18V36.352Z" />
<path d="M654.54 47.1035H611.788L592.332 74.2395L573.388 47.1035H527.564L568.78 103.168L523.98 161.28H566.732L589.516 130.304L612.3 161.28H658.124L613.068 101.376L654.54 47.1035Z" />
</svg>
);
}
44 changes: 44 additions & 0 deletions apps/remix-app/app/routes/demos/about.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Outlet } from 'remix';
import type { MetaFunction, LinksFunction } from 'remix';

import stylesUrl from '~/styles/demos/about.css';

export const meta: MetaFunction = () => {
return {
title: 'About Remix',
};
};

export const links: LinksFunction = () => {
return [{ rel: 'stylesheet', href: stylesUrl }];
};

export default function Index() {
return (
<div className="about">
<div className="about__intro">
<h2>About Us</h2>
<p>
Ok, so this page isn't really <em>about us</em>, but we did want to
show you a few more things Remix can do.
</p>
<p>
Did you notice that things look a little different on this page? The
CSS that we import in the route file and include in its{' '}
<code>links</code> export is only included on this route and its
children.
</p>
<p>
Wait a sec...<em>its children</em>? To understand what we mean by
this,{' '}
<a href="https://remix.run/tutorial/4-nested-routes-params">
read all about nested routes in the docs
</a>
.
</p>
<hr />
<Outlet />
</div>
</div>
);
}
17 changes: 17 additions & 0 deletions apps/remix-app/app/routes/demos/about/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Link } from 'remix';

export default function AboutIndex() {
return (
<div>
<p>
You are looking at the index route for the <code>/about</code> URL
segment, but there are nested routes as well!
</p>
<p>
<strong>
<Link to="whoa">Check out one of them here.</Link>
</strong>
</p>
</div>
);
}
20 changes: 20 additions & 0 deletions apps/remix-app/app/routes/demos/about/whoa.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Link } from 'remix';

export default function AboutIndex() {
return (
<div>
<p>
Whoa, this is a nested route! We render the <code>/about</code> layout
route component, and its <code>Outlet</code> renders our route
component. 🤯
</p>
<p>
<strong>
<Link to="..">
Go back to the <code>/about</code> index.
</Link>
</strong>
</p>
</div>
);
}
Loading

0 comments on commit ffbd5ab

Please sign in to comment.