├── .DS_Store
├── .gitignore
├── .prettierrc
├── LICENSE
├── README.md
├── app
├── components
│ └── Button.tsx
├── cookies.ts
├── entry.client.tsx
├── entry.server.tsx
├── root.tsx
└── routes
│ ├── index.tsx
│ ├── pages.tsx
│ └── pages
│ └── $id.tsx
├── package-lock.json
├── package.json
├── public
├── .DS_Store
└── favicon.ico
├── remix.config.js
├── remix.env.d.ts
├── stitches.config.ts
└── tsconfig.json
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rossmoody/stitches-remix/73721b21db58744264bd8b2129d94d4b9f07f121/.DS_Store
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | /public/build
6 | .env
7 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "es5",
3 | "tabWidth": 2,
4 | "semi": false,
5 | "singleQuote": true
6 | }
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Ross Moody
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to Remix!
2 |
3 | - [Remix Docs](https://remix.run/docs)
4 |
5 | ## Development
6 |
7 | From your terminal:
8 |
9 | ```sh
10 | npm run dev
11 | ```
12 |
13 | This starts your app in development mode, rebuilding assets on file changes.
14 |
15 | ## Deployment
16 |
17 | First, build your app for production:
18 |
19 | ```sh
20 | npm run build
21 | ```
22 |
23 | Then run the app in production mode:
24 |
25 | ```sh
26 | npm start
27 | ```
28 |
29 | Now you'll need to pick a host to deploy it to.
30 |
31 | ### DIY
32 |
33 | If you're familiar with deploying node applications, the built-in Remix app server is production-ready.
34 |
35 | Make sure to deploy the output of `remix build`
36 |
37 | - `build/`
38 | - `public/build/`
39 |
40 | ### Using a Template
41 |
42 | 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.
43 |
44 | ```sh
45 | cd ..
46 | # create a new project, and pick a pre-configured host
47 | npx create-remix@latest
48 | cd my-new-remix-app
49 | # remove the new project's app (not the old one!)
50 | rm -rf app
51 | # copy your app over
52 | cp -R ../my-old-remix-app/app app
53 | ```
54 |
--------------------------------------------------------------------------------
/app/components/Button.tsx:
--------------------------------------------------------------------------------
1 | import { styled, darkTheme } from '../../stitches.config'
2 |
3 | export const Button = styled('button', {
4 | padding: '24px',
5 | color: '$bgBody',
6 | backgroundColor: '$text',
7 | [`${darkTheme}`]: {},
8 | })
9 |
10 | // Need to pass dark theme into Button component or the dark
11 | // theme variables aren't compiled and added to :root. This isn't
12 | // normally necessary.
13 |
--------------------------------------------------------------------------------
/app/cookies.ts:
--------------------------------------------------------------------------------
1 | import { createCookie } from 'remix'
2 |
3 | export let colorSchemeCookie = createCookie('color-scheme')
4 |
5 | export const getColorSchemeToken = async (request: Request) =>
6 | await colorSchemeCookie.parse(request.headers.get('Cookie'))
7 |
8 | export const getColorScheme = async (request: Request) => {
9 | const userSelectedColorScheme = await getColorSchemeToken(request)
10 | const systemPreferredColorScheme = request.headers.get(
11 | 'Sec-CH-Prefers-Color-Scheme'
12 | )
13 |
14 | return userSelectedColorScheme ?? systemPreferredColorScheme ?? 'light'
15 | }
16 |
--------------------------------------------------------------------------------
/app/entry.client.tsx:
--------------------------------------------------------------------------------
1 | import { hydrate } from 'react-dom'
2 | import { RemixBrowser } from 'remix'
3 |
4 | hydrate(, document)
5 |
--------------------------------------------------------------------------------
/app/entry.server.tsx:
--------------------------------------------------------------------------------
1 | import ReactDOMServer from 'react-dom/server'
2 | import { RemixServer, EntryContext } from 'remix'
3 | import { getCssText } from '../stitches.config'
4 |
5 | export default async function handleRequest(
6 | request: Request,
7 | responseStatusCode: number,
8 | responseHeaders: Headers,
9 | remixContext: EntryContext
10 | ) {
11 | const markup = ReactDOMServer.renderToString(
12 |
13 | ).replace(/<\/head>/, ``)
14 |
15 | return new Response('' + markup, {
16 | status: responseStatusCode,
17 | headers: {
18 | ...Object.fromEntries(responseHeaders),
19 | 'Content-Type': 'text/html',
20 | },
21 | })
22 | }
23 |
--------------------------------------------------------------------------------
/app/root.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Links,
3 | LiveReload,
4 | LoaderFunction,
5 | Meta,
6 | Outlet,
7 | Scripts,
8 | ScrollRestoration,
9 | useLoaderData,
10 | HeadersFunction,
11 | MetaFunction,
12 | } from 'remix'
13 | import { getColorScheme } from './cookies'
14 |
15 | export const meta: MetaFunction = () => ({
16 | title: 'Stitches Theme Example',
17 | })
18 |
19 | export const headers: HeadersFunction = () => ({
20 | 'Accept-CH': 'Sec-CH-Prefers-Color-Scheme',
21 | })
22 |
23 | export const loader: LoaderFunction = async ({ request }) => ({
24 | colorScheme: await getColorScheme(request),
25 | })
26 |
27 | export default function App() {
28 | const { colorScheme } = useLoaderData()
29 |
30 | return (
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | {process.env.NODE_ENV === 'development' && }
43 |
44 |
45 | )
46 | }
47 |
--------------------------------------------------------------------------------
/app/routes/index.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from '~/components/Button'
2 | import { ActionFunction, Form, redirect, Link } from 'remix'
3 | import { colorSchemeCookie, getColorScheme } from '../cookies'
4 |
5 | export const action: ActionFunction = async ({ request }) => {
6 | const currentColorScheme = await getColorScheme(request)
7 | const newColorScheme = currentColorScheme === 'light' ? 'dark' : 'light'
8 |
9 | return redirect(request.url, {
10 | headers: {
11 | 'Set-Cookie': await colorSchemeCookie.serialize(newColorScheme),
12 | },
13 | })
14 | }
15 |
16 | export default function Index() {
17 | return (
18 |
19 |
Home
20 |
23 |
24 | -
25 | Go to /pages
26 |
27 | -
28 | Go to /pages/hello
29 |
30 | -
31 | Go to /pages/goodbye
32 |
33 |
34 |
35 | )
36 | }
37 |
--------------------------------------------------------------------------------
/app/routes/pages.tsx:
--------------------------------------------------------------------------------
1 | import { Outlet, Link } from 'remix'
2 |
3 | export default function Pages() {
4 | return (
5 |
6 |
Pages
7 |
8 | -
9 | Go to /pages/hello
10 |
11 | -
12 | Go to /pages/goodbye
13 |
14 |
15 |
16 |
17 |
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/app/routes/pages/$id.tsx:
--------------------------------------------------------------------------------
1 | import { Link, useParams } from 'remix'
2 |
3 | export default function Hello() {
4 | const { id } = useParams()
5 |
6 | return (
7 |
8 |
Pages {id}
9 |
10 | -
11 | Go to home
12 |
13 | -
14 | Go to /pages
15 |
16 |
17 |
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "remix-app-template",
4 | "description": "",
5 | "license": "",
6 | "scripts": {
7 | "build": "remix build",
8 | "dev": "remix dev",
9 | "postinstall": "remix setup node",
10 | "start": "remix-serve build"
11 | },
12 | "dependencies": {
13 | "@remix-run/react": "^1.1.1",
14 | "@remix-run/serve": "^1.1.1",
15 | "@stitches/react": "^1.2.6",
16 | "react": "^17.0.2",
17 | "react-dom": "^17.0.2",
18 | "remix": "^1.1.1"
19 | },
20 | "devDependencies": {
21 | "@remix-run/dev": "^1.1.1",
22 | "@types/react": "^17.0.24",
23 | "@types/react-dom": "^17.0.9",
24 | "typescript": "^4.1.2"
25 | },
26 | "engines": {
27 | "node": ">=14"
28 | },
29 | "sideEffects": false
30 | }
31 |
--------------------------------------------------------------------------------
/public/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rossmoody/stitches-remix/73721b21db58744264bd8b2129d94d4b9f07f121/public/.DS_Store
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rossmoody/stitches-remix/73721b21db58744264bd8b2129d94d4b9f07f121/public/favicon.ico
--------------------------------------------------------------------------------
/remix.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @type {import('@remix-run/dev/config').AppConfig}
3 | */
4 | module.exports = {
5 | appDirectory: "app",
6 | assetsBuildDirectory: "public/build",
7 | publicPath: "/build/",
8 | serverBuildDirectory: "build",
9 | devServerPort: 8002,
10 | ignoredRouteFiles: [".*"]
11 | };
12 |
--------------------------------------------------------------------------------
/remix.env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/stitches.config.ts:
--------------------------------------------------------------------------------
1 | import { createStitches } from "@stitches/react";
2 |
3 | export const { styled, createTheme, globalCss, getCssText, theme } =
4 | createStitches({
5 | theme: {
6 | colors: {
7 | text: "#191919",
8 | bgBody: "#f8f9fa",
9 | anchor: "DarkGoldenRod",
10 | },
11 | },
12 | });
13 |
14 | export const darkTheme = createTheme("dark", {
15 | colors: {
16 | text: "#f8f9fa",
17 | bgBody: "#191919",
18 | anchor: "BlanchedAlmond",
19 | },
20 | });
21 |
22 | globalCss({
23 | body: {
24 | color: "$text",
25 | backgroundColor: "$bgBody",
26 | },
27 |
28 | a: {
29 | color: "$anchor",
30 | },
31 | })();
32 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
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 | "baseUrl": ".",
13 | "paths": {
14 | "~/*": ["./app/*"]
15 | },
16 |
17 | // Remix takes care of building everything in `remix build`.
18 | "noEmit": true
19 | }
20 | }
21 |
--------------------------------------------------------------------------------