├── .dockerignore
├── .eslintrc
├── .gitignore
├── Dockerfile
├── LICENSE.md
├── README.md
├── app
├── components
│ ├── container
│ │ ├── index.tsx
│ │ └── styles.css
│ ├── footer
│ │ ├── index.tsx
│ │ └── styles.css
│ ├── header
│ │ ├── index.tsx
│ │ └── styles.css
│ ├── hero
│ │ ├── index.tsx
│ │ └── styles.css
│ ├── search
│ │ ├── index.tsx
│ │ └── styles.css
│ ├── stack-grid
│ │ ├── index.tsx
│ │ └── styles.css
│ └── svgs
│ │ └── search.tsx
├── entry.client.tsx
├── entry.server.tsx
├── lib
│ └── meta.ts
├── root.tsx
├── routes
│ └── index.tsx
└── styles
│ └── base.css
├── content
└── stacks.json
├── fly.toml
├── package-lock.json
├── package.json
├── public
├── assets
│ └── og.png
└── favicon.ico
├── remix.config.js
├── remix.env.d.ts
├── start_with_migrations.sh
└── tsconfig.json
/.dockerignore:
--------------------------------------------------------------------------------
1 | build
2 | node_modules
3 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["@remix-run/eslint-config", "@remix-run/eslint-config/node"]
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | /public/build
6 | .env
7 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # base node image
2 | FROM node:16-bullseye-slim as base
3 |
4 | # Install openssl for Prisma
5 | RUN apt-get update && apt-get install -y openssl
6 |
7 | # Install all node_modules, including dev dependencies
8 | FROM base as deps
9 |
10 | RUN mkdir /app
11 | WORKDIR /app
12 |
13 | ADD package.json package-lock.json ./
14 | RUN npm install --production=false
15 |
16 | # Setup production node_modules
17 | FROM base as production-deps
18 |
19 | RUN mkdir /app
20 | WORKDIR /app
21 |
22 | COPY --from=deps /app/node_modules /app/node_modules
23 | ADD package.json package-lock.json ./
24 | RUN npm prune --production
25 |
26 | # Build the app
27 | FROM base as build
28 |
29 | ENV NODE_ENV=production
30 |
31 | RUN mkdir /app
32 | WORKDIR /app
33 |
34 | COPY --from=deps /app/node_modules /app/node_modules
35 |
36 | # If we're using Prisma, uncomment to cache the prisma schema
37 | # ADD prisma .
38 | # RUN npx prisma generate
39 |
40 | ADD . .
41 | RUN npm run build
42 |
43 | # Finally, build the production image with minimal footprint
44 | FROM base
45 |
46 | ENV NODE_ENV=production
47 |
48 | RUN mkdir /app
49 | WORKDIR /app
50 |
51 | COPY --from=production-deps /app/node_modules /app/node_modules
52 |
53 | # Uncomment if using Prisma
54 | # COPY --from=build /app/node_modules/.prisma /app/node_modules/.prisma
55 |
56 | COPY --from=build /app/build /app/build
57 | COPY --from=build /app/public /app/public
58 | ADD . .
59 |
60 | CMD ["npm", "run", "start"]
61 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2022 Nishiki Liu
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # Remix Directory
4 |
5 | This is a community-powered directory of [Remix stacks](https://remix.run/stacks).
6 |
7 | Remix is a modern web framework that treats progressive enhancement and developer experience as first-class citizens.
8 |
9 | ## Adding your stack
10 |
11 | Simply add relevant changes to `content/stacks.json` and open a pull request!
12 |
13 | ## Running locally
14 |
15 | ```
16 | npm install
17 | npm run dev
18 | ```
19 |
--------------------------------------------------------------------------------
/app/components/container/index.tsx:
--------------------------------------------------------------------------------
1 | import type { FC } from 'react'
2 | import styles from './styles.css'
3 |
4 | export const containerLinks = () => [
5 | { rel: 'stylesheet', href: styles }
6 | ]
7 |
8 | export const Container: FC = ({ children }) => (
9 |
10 | {children}
11 |
12 | )
13 |
--------------------------------------------------------------------------------
/app/components/container/styles.css:
--------------------------------------------------------------------------------
1 | .container {
2 | max-width: 70rem;
3 | padding: 0 2rem;
4 | margin: 0 auto;
5 | }
6 |
--------------------------------------------------------------------------------
/app/components/footer/index.tsx:
--------------------------------------------------------------------------------
1 | import styles from './styles.css'
2 |
3 | export const footerLinks = () => [
4 | { rel: 'stylesheet', href: styles }
5 | ]
6 |
7 | export const Footer = () => (
8 |
14 | )
15 |
--------------------------------------------------------------------------------
/app/components/footer/styles.css:
--------------------------------------------------------------------------------
1 | .footer {
2 | display: flex;
3 | justify-content: flex-end;
4 | padding: 8rem 0 4rem;
5 | }
6 |
--------------------------------------------------------------------------------
/app/components/header/index.tsx:
--------------------------------------------------------------------------------
1 | import { Link } from '@remix-run/react'
2 | import styles from './styles.css'
3 |
4 | export const headerLinks = () => [
5 | { rel: 'stylesheet', href: styles }
6 | ]
7 |
8 | export const Header = () => (
9 |
10 | {`Remix Directory`}
11 |
12 |
22 |
23 | )
24 |
--------------------------------------------------------------------------------
/app/components/header/styles.css:
--------------------------------------------------------------------------------
1 | .header {
2 | display: flex;
3 | justify-content: space-between;
4 | align-items: baseline;
5 | padding: 3rem 0;
6 | }
7 |
8 | .header__logo {
9 | font-size: 1.5rem;
10 | font-weight: 900;
11 | text-decoration: none;
12 | color: var(--color-white);
13 | }
14 |
15 | .header__items {
16 | padding: 0;
17 | list-style: none;
18 | }
19 |
20 | .header__link {
21 | font-weight: 700;
22 | text-decoration: none;
23 | color: var(--color-white);
24 | }
25 |
26 | .header__link:is(:focus, :hover) {
27 | text-decoration: underline;
28 | }
29 |
--------------------------------------------------------------------------------
/app/components/hero/index.tsx:
--------------------------------------------------------------------------------
1 | import type { ChangeEventHandler, FC } from 'react'
2 | import { Search, searchLinks } from '~/components/search'
3 | import styles from './styles.css'
4 |
5 | export const heroLinks = () => [
6 | { rel: 'stylesheet', href: styles },
7 | ...searchLinks()
8 | ]
9 |
10 | interface HeroProps {
11 | onSearchTermChange: ChangeEventHandler
12 | }
13 |
14 | export const Hero: FC = ({ onSearchTermChange }) => (
15 |
16 |
17 | {`Find the `}
18 | {`Remix stack`}
19 | {` that works for you. Or `}
20 | add your own
21 | {`.`}
22 |
23 |
24 |
28 |
29 | )
30 |
--------------------------------------------------------------------------------
/app/components/hero/styles.css:
--------------------------------------------------------------------------------
1 | .hero {
2 | display: flex;
3 | flex-direction: column;
4 | align-items: center;
5 | gap: 3rem;
6 | padding: 5rem 0;
7 | }
8 |
9 | .hero__heading {
10 | max-width: 60rem;
11 | font-size: 2rem;
12 | font-weight: 900;
13 | text-align: center;
14 | color: var(--color-white);
15 | }
16 |
17 | .hero a {
18 | text-decoration: underline;
19 | color: var(--color-green);
20 | }
21 |
22 | .hero a:first-of-type {
23 | color: var(--color-yellow);
24 | }
25 |
26 | @media (min-width: 48rem) {
27 | .hero {
28 | padding: 10rem 0;
29 | }
30 |
31 | .hero__heading {
32 | font-size: 3rem;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/components/search/index.tsx:
--------------------------------------------------------------------------------
1 | import type { ChangeEventHandler, FC } from 'react'
2 | import { SearchSvg } from '~/components/svgs/search'
3 | import styles from './styles.css'
4 |
5 | export const searchLinks = () => [
6 | { rel: 'stylesheet', href: styles }
7 | ]
8 |
9 | interface SearchProps {
10 | placeholder: string
11 | onSearchTermChange: ChangeEventHandler
12 | }
13 |
14 | export const Search: FC = ({
15 | placeholder = 'Search',
16 | onSearchTermChange
17 | }) => (
18 |
19 |
20 |
21 |
22 |
23 |
29 |
30 | )
31 |
--------------------------------------------------------------------------------
/app/components/search/styles.css:
--------------------------------------------------------------------------------
1 | .search {
2 | background-color: var(--color-input);
3 | width: 100%;
4 | max-width: 28rem;
5 | border-radius: var(--radius-full);
6 | position: relative;
7 | }
8 |
9 | .search__icon {
10 | position: absolute;
11 | left: 1rem;
12 | top: 50%;
13 | transform: translateY(-50%);
14 | pointer-events: none;
15 | }
16 |
17 | .search__input {
18 | background-color: transparent;
19 | display: block;
20 | width: 100%;
21 | padding: 1rem 1rem 1rem 3.25rem;
22 | border: 0;
23 | font-size: 1.25rem;
24 | color: var(--color-white);
25 | }
26 |
27 | .search__input:focus {
28 | border-radius: var(--radius-full);
29 | outline: var(--color-purple) solid 0.125rem;
30 | }
31 |
--------------------------------------------------------------------------------
/app/components/stack-grid/index.tsx:
--------------------------------------------------------------------------------
1 | import type { FC } from 'react'
2 | import styles from './styles.css'
3 |
4 | export const stackGridLinks = () => [
5 | { rel: 'stylesheet', href: styles }
6 | ]
7 |
8 | interface StackGridProps {
9 | stacks: {
10 | name: string
11 | description: string
12 | tags: string[]
13 | url: string
14 | }[]
15 | }
16 |
17 | export const StackGrid: FC = ({ stacks = [] }) => (
18 |
19 | {stacks.map((stack, stackIndex) => (
20 |
24 | {stack.name}
25 |
26 |
27 | {[stack.tags.map((tag, tagIndex) => (
28 | -
32 | {tag}
33 |
34 | ))]}
35 |
36 |
37 | {stack.description}
38 |
39 |
43 | {`View on GitHub`}
44 |
45 |
46 | ))}
47 |
48 | )
49 |
--------------------------------------------------------------------------------
/app/components/stack-grid/styles.css:
--------------------------------------------------------------------------------
1 | .stack-grid {
2 | display: grid;
3 | gap: 1rem;
4 | }
5 |
6 | .stack-grid__item {
7 | background-color: var(--color-gray);
8 | display: flex;
9 | flex-direction: column;
10 | gap: 1rem;
11 | padding: 2rem;
12 | border-radius: var(--radius);
13 | }
14 |
15 | .stack-grid__name {
16 | font-size: 1.25rem;
17 | font-weight: 700;
18 | color: var(--color-white);
19 | }
20 |
21 | .stack-grid__tags {
22 | display: flex;
23 | flex-wrap: wrap;
24 | gap: 0.25rem;
25 | padding: 0;
26 | list-style: none;
27 | }
28 |
29 | .stack-grid__tag {
30 | background-color: rgba(0, 0, 0, 0.25);
31 | display: block;
32 | padding: 0.25rem 0.4rem;
33 | font-family: var(--font-mono);
34 | font-size: 0.9rem;
35 | }
36 |
37 | .stack-grid__link {
38 | margin-top: auto;
39 | margin-left: auto;
40 | font-weight: 700;
41 | }
42 |
43 | @media (min-width: 48rem) {
44 | .stack-grid {
45 | grid-template-columns: repeat(2, 1fr);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/app/components/svgs/search.tsx:
--------------------------------------------------------------------------------
1 | export const SearchSvg = ({ width = 25, height = 25 }) => (
2 |
18 | )
19 |
--------------------------------------------------------------------------------
/app/entry.client.tsx:
--------------------------------------------------------------------------------
1 | import { RemixBrowser } from '@remix-run/react'
2 | import { hydrate } from 'react-dom'
3 |
4 | hydrate(, document)
5 |
--------------------------------------------------------------------------------
/app/entry.server.tsx:
--------------------------------------------------------------------------------
1 | import type { EntryContext } from '@remix-run/node'
2 | import { RemixServer } from '@remix-run/react'
3 | import { renderToString } from 'react-dom/server'
4 |
5 | export default function handleRequest (
6 | request: Request,
7 | responseStatusCode: number,
8 | responseHeaders: Headers,
9 | remixContext: EntryContext
10 | ) {
11 | let markup = renderToString(
12 |
13 | );
14 |
15 | responseHeaders.set('Content-Type', 'text/html')
16 |
17 | return new Response('' + markup, {
18 | status: responseStatusCode,
19 | headers: responseHeaders
20 | })
21 | }
22 |
--------------------------------------------------------------------------------
/app/lib/meta.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Returns all meta tags associated with a page title.
3 | */
4 | export function title (text: string) {
5 | return {
6 | title: text,
7 | 'twitter:title': text
8 | }
9 | }
10 |
11 | /**
12 | * Returns all meta tags associated with a page description.
13 | */
14 | export function description (text: string) {
15 | return {
16 | description: text,
17 | 'og:description': text,
18 | 'twitter:description': text
19 | }
20 | }
21 |
22 | /**
23 | * Returns all meta tags associated with a page image.
24 | */
25 | export function image (url: string) {
26 | return {
27 | 'og:image': url,
28 | 'twitter:image': url
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/root.tsx:
--------------------------------------------------------------------------------
1 | import type { LinksFunction, MetaFunction } from '@remix-run/node'
2 | import {
3 | Links,
4 | LiveReload,
5 | Meta,
6 | Outlet,
7 | Scripts,
8 | ScrollRestoration
9 | } from '@remix-run/react'
10 | import { title, description, image } from './lib/meta'
11 | import styles from '~/styles/base.css'
12 |
13 | export const meta: MetaFunction = () => ({
14 | charset: 'utf-8',
15 | viewport: 'width=device-width,initial-scale=1',
16 | ...title('Remix Directory'),
17 | ...description('Find the Remix stack that works for you.'),
18 | ...image('https://remix.directory/assets/og.png'),
19 | 'twitter:card': 'summary_large_image'
20 | })
21 |
22 | export const links: LinksFunction = () => [
23 | { rel: 'stylesheet', href: styles }
24 | ]
25 |
26 | export default function App () {
27 | return (
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | )
41 | }
42 |
--------------------------------------------------------------------------------
/app/routes/index.tsx:
--------------------------------------------------------------------------------
1 | import type { ChangeEventHandler } from 'react'
2 | import { useState } from 'react'
3 | import { LinksFunction } from '@remix-run/node'
4 | import { Container, containerLinks } from '~/components/container'
5 | import { Header, headerLinks } from '~/components/header'
6 | import { Hero, heroLinks } from '~/components/hero'
7 | import { StackGrid, stackGridLinks } from '~/components/stack-grid'
8 | import { Footer, footerLinks } from '~/components/footer'
9 |
10 | import { stacks } from '../../content/stacks.json'
11 |
12 | export const links: LinksFunction = () => [
13 | ...containerLinks(),
14 | ...headerLinks(),
15 | ...heroLinks(),
16 | ...stackGridLinks(),
17 | ...footerLinks()
18 | ]
19 |
20 | export default function Index () {
21 | let [searchTerm, setSearchTerm] = useState('')
22 | let onSearchTermChange: ChangeEventHandler = (event) => {
23 | setSearchTerm(event.target.value.toLowerCase())
24 | }
25 |
26 | // Apply a really trivial filtering mechanism for stacks for now. If this
27 | // project starts housing a much larger number of stacks, we can revisit!
28 | let filteredStacks = stacks.filter((stack) => {
29 | let { name, description, tags } = stack
30 | let hasNameMatch = name.toLowerCase().includes(searchTerm)
31 | let hasDescriptionMatch = description.toLowerCase().includes(searchTerm)
32 | let hasTagMatch = tags.includes(searchTerm)
33 | return hasNameMatch || hasDescriptionMatch || hasTagMatch
34 | })
35 |
36 | return (
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | )
48 | }
49 |
--------------------------------------------------------------------------------
/app/styles/base.css:
--------------------------------------------------------------------------------
1 | @import url("https://rsms.me/inter/inter.css");
2 |
3 | :root {
4 | --color-white: #fff;
5 | --color-gray: #292929;
6 | --color-blue: #59a8ff;
7 | --color-green: #6bd968;
8 | --color-yellow: #fecc1b;
9 | --color-purple: #5468ff;
10 |
11 | --color-background: #121212;
12 | --color-text: #d0d0d0;
13 | --color-input: #090a11;
14 |
15 | --font-main: "Inter", sans-serif;
16 | --font-mono: SFMono-Regular, 'Consolas', 'Liberation Mono', 'Menlo',
17 | monospace;
18 |
19 | --radius: 0.625rem;
20 | --radius-full: 100rem;
21 | }
22 |
23 | *, *::before, *::after {
24 | box-sizing: border-box;
25 | }
26 |
27 | * {
28 | margin: 0;
29 | }
30 |
31 | html {
32 | font-family: var(--font-main);
33 | }
34 |
35 | html, body {
36 | height: 100%;
37 | }
38 |
39 | body {
40 | background-color: var(--color-background);
41 | line-height: 1.5;
42 | }
43 |
44 | img, svg {
45 | display: block;
46 | max-width: 100%;
47 | }
48 |
49 | p, ul, ol {
50 | font-size: 1;
51 | color: var(--color-text);
52 | }
53 |
54 | button, input, textarea, select {
55 | font: inherit;
56 | }
57 |
58 | a {
59 | color: var(--color-blue);
60 | }
61 |
62 | a:is(:focus, :hover) {
63 | opacity: 0.8;
64 | }
65 |
66 | :focus {
67 | outline: none;
68 | }
69 |
70 | @supports (font-variation-settings: normal) {
71 | :root {
72 | --font-main: "Inter var", sans-serif;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/content/stacks.json:
--------------------------------------------------------------------------------
1 | {
2 | "stacks": [
3 | {
4 | "name": "The Blues Stack",
5 | "description": "Deployed to the edge (distributed) with a long-running Node.js server and PostgreSQL database. Intended for large and fast production-grade applications serving millions of users.",
6 | "tags": ["official", "fly", "docker", "postgresql", "github actions", "auth", "prisma", "tailwind", "cypress", "msw", "vitest", "testing library", "prettier", "eslint", "typescript"],
7 | "url": "https://github.com/remix-run/blues-stack"
8 | },
9 | {
10 | "name": "The Indie Stack",
11 | "description": "Deployed to a long-running Node.js server with a persistent SQLite database. This stack is great for websites with dynamic data that you control (blogs, marketing, content sites). It's also a perfect, low-complexity bootstrap for MVPs, prototypes, and proof-of-concepts that can later be updated to the Blues stack easily.",
12 | "tags": ["official", "fly", "docker", "sqlite", "github actions", "auth", "prisma", "tailwind", "cypress", "msw", "vitest", "testing library", "prettier", "eslint", "typescript"],
13 | "url": "https://github.com/remix-run/indie-stack"
14 | },
15 | {
16 | "name": "The Grunge Stack",
17 | "description": "Deployed to a serverless function running Node.js with DynamoDB for persistance. Intended for folks who want to deploy a production-grade application on AWS infrastructure serving millions of users.",
18 | "tags": ["official", "aws", "architect", "dynamodb", "github actions", "auth", "tailwind", "cypress", "msw", "vitest", "testing library", "prettier", "eslint", "typescript"],
19 | "url": "https://github.com/remix-run/grunge-stack"
20 | },
21 | {
22 | "name": "Speed Metal Stack",
23 | "description": "The Remix blog stack for deploying to Fly with MDX, SQLite, testing, linting, formatting, etc.",
24 | "tags": ["server", "sqlite", "fly", "tailwind", "mdx"],
25 | "url": "https://github.com/Girish21/speed-metal-stack"
26 | },
27 | {
28 | "name": "remix-worker-template",
29 | "description": "All-in-one remix starter template for Cloudflare Workers.",
30 | "tags": ["cloudflare", "tailwind", "playwright", "eslint", "prettier"],
31 | "url": "https://github.com/edmundhung/remix-worker-template"
32 | },
33 | {
34 | "name": "Supa Fly Stack",
35 | "description": "The Remix stack for deploying to Fly with Supabase, authentication, testing, linting, formatting, etc.",
36 | "tags": ["supabase", "fly", "auth", "tailwind", "cypress", "prisma", "msw", "prettier", "eslint", "typescript"],
37 | "url": "https://github.com/rphlmr/supa-fly-stack"
38 | },
39 | {
40 | "name": "remix-starter-serverless",
41 | "description": "A template for deploying Remix to AWS with the Serverless framework.",
42 | "tags": ["aws", "lambda", "typescript", "serverless"],
43 | "url": "https://github.com/shamsup/remix-starter-serverless"
44 | },
45 | {
46 | "name": "Azure Remix Stack",
47 | "description": "A Remix stack template for running a Remix app on Azure.",
48 | "tags": ["azure", "prisma", "tailwind", "cypress", "msw", "vitest", "testing library", "prettier", "eslint", "typescript"],
49 | "url": "https://github.com/aaronpowell/azure-remix-stack"
50 | },
51 | {
52 | "name": "Melodic Death Metal",
53 | "description": "The Remix Indie Stack without deployment.",
54 | "tags": ["sqlite", "github actions", "prisma", "tailwind", "cypress", "msw", "vitest", "testing library", "prettier", "eslint", "typescript"],
55 | "url": "https://github.com/baijanathTharu/melodic-death-metal"
56 | },
57 | {
58 | "name": "Chakra Remix Blues Stack",
59 | "description": "Chakra UI port for the Remix Blues Stack.",
60 | "tags": ["fly", "postgresql", "github actions", "prisma", "chakra", "cypress", "msw", "vitest", "testing library", "prettier", "eslint", "typescript"],
61 | "url": "https://github.com/anubra266/chakra-remix-stack-blues"
62 | },
63 | {
64 | "name": "Techno Stack",
65 | "description": "The Remix Stack for deploying to Kubernetes, talking to an existing Postgres db, authentication, testing, linting, formatting, etc.",
66 | "tags": ["kubernetes", "prisma", "tailwind", "cypress", "msw", "vitest", "testing library", "prettier", "eslint", "typescript"],
67 | "url": "https://github.com/BenMcH/techno-stack"
68 | },
69 | {
70 | "name": "K-pop Stack",
71 | "description": "A template for deploying Remix to Netlify Edge with Supabase",
72 | "tags": ["netlify", "supabase", "tailwind", "cypress", "testing library", "prettier", "eslint", "typescript"],
73 | "url": "https://github.com/netlify-templates/kpop-stack"
74 | },
75 | {
76 | "name": "RockSpec Stacks",
77 | "description": "A template for deploying a Progressive Web App with a persistent database, testing and authentication suites. A fun ride through Remix!",
78 | "tags": ["fly", "postgresql", "prisma", "cypress", "pwa", "prettier", "eslint", "typescript", "tailwind"],
79 | "url": "https://github.com/ShafSpecs/rockspec-stack"
80 | },
81 | {
82 | "name": "The Bossa Nova Stack",
83 | "description": "The Remix Stack with Clerk authentication, Supabase database, Chakra UI, testing, linting, and more.",
84 | "tags": ["vercel", "supabase", "postgres", "clerk", "cypress", "prettier", "eslint", "typescript", "chakra"],
85 | "url": "https://github.com/clerkinc/remix-bossa-nova-stack"
86 | },
87 | {
88 | "name": "Chop Suey Stack",
89 | "description": "A template for deploying Remix to Fly with EdgeDB. Comes with Clerk for simple authentication and opinionated configs for TypeScript, Prettier, and ESLint.",
90 | "tags": ["fly", "edgedb", "clerk", "prisma", "cypress", "prettier", "eslint", "typescript", "tailwind", "zod", "msw", "testing library", "github actions", "react hot toast", "react icons"],
91 | "url": "https://github.com/jkcorrea/remix-chop-suey-stack"
92 | },
93 | {
94 | "name": "DnB Stack",
95 | "description": "The Remix Stack for deploying to Vercel with testing, linting, formatting, structure and mock for 3rd party API integration.",
96 | "tags": ["vercel", "github actions", "vitest", "testing library", "husky", "prisma", "cypress", "prettier", "eslint", "typescript", "tailwind"],
97 | "url": "https://github.com/robipop22/dnb-stack"
98 | },
99 | {
100 | "name": "Eurodance Stack",
101 | "description": "The Remix Stack for GraphQL developers, brought by Vulcan.",
102 | "tags": ["vercel", "graphql", "storybook", "mongo", "codesandbox"],
103 | "url": "https://github.com/VulcanJS/eurodance-stack"
104 | },
105 | {
106 | "name": "Indie Thin Stack",
107 | "description": "The Remix Stack for deploying to Fly or simple Node server with authentication, testing, linting, formatting, etc. Great for integrating with headless CMS",
108 | "tags": ["fly", "docker", "github actions", "tailwind", "cypress", "msw", "vitest", "testing library", "prettier", "eslint", "typescript"],
109 | "url": "https://github.com/alvinthen/indie-thin-stack"
110 | },
111 | {
112 | "name": "Air Metal Stack",
113 | "description": "A Remix stack setup to run on Deno with support for Rust WASM modules!",
114 | "tags": ["deno", "deno deploy", "rust", "webassembly"],
115 | "url": "https://github.com/benwis/air-metal-stack"
116 | },
117 | {
118 | "name": "French House Stack",
119 | "description": "The Remix Stack for Web2 apps and Web3 DApps with authentication with Magic, testing, linting, formatting, etc.",
120 | "tags": ["magic", "cypress", "vitest", "testing library", "tailwind", "github actions", "prettier", "eslint", "husky", "typescript", "web3", "i18n"],
121 | "url": "https://github.com/janhesters/french-house-stack"
122 | },
123 | {
124 | "name": "Minimal House Remix Stack",
125 | "description": "The Remix Stack to setup Remix with minimal typsescript, tailwind, linting, and formatting. Worry about storage, testing, deployment later.",
126 | "tags": ["eslint", "typescript", "prettier", "tailwind"],
127 | "url": "https://github.com/BogDAAAMN/minimal-remix-stack"
128 | },
129 | {
130 | "name": "New Wave Stack",
131 | "description": "Custom Remix stack using Clerk for authentication and full user management.",
132 | "tags": ["clerk", "fauna", "netlify", "tailwind", "cypress", "jest", "testing library", "eslint", "typescript"],
133 | "url": "https://github.com/charles-clerk-dev/new-wave-stack"
134 | },
135 | {
136 | "name": "Remix Render Stack",
137 | "description": "A Remix stack for deploying remix to render.com with postgres",
138 | "tags": ["prism", "render.com", "postgresql"],
139 | "url": "https://github.com/TerribleDev/remix-render"
140 | },
141 | {
142 | "name": "Techno Stack",
143 | "description": "The Remix Stack for deploying to Kubernetes, talking to an existing Postgres Db, authentication, testing, linting, formatting, etc.",
144 | "tags": ["kubernetes", "docker", "github actions", "prisma", "tailwind", "cypress", "msw", "vitest", "testing library", "eslint", "typescript"],
145 | "url": "https://github.com/BenMcH/techno-stack"
146 | },
147 | {
148 | "name": "Prog Stack",
149 | "description": "Adapted from blues. Prisma is brilliant, but I like Hasura. Hasura is like prog, it gets better every time you get into it.",
150 | "tags": ["hasura", "fly", "docker", "tailwind", "cypress", "msw", "vitest", "testing library", "eslint", "typescript"],
151 | "url": "https://github.com/k1sul1/prog-stack"
152 | },
153 | {
154 | "name": "Acoustic Stack",
155 | "description": "A minimal Remix stack to serve as a starting point for demos and debugging.",
156 | "tags": ["tailwind", "vitest", "testing library", "prettier", "eslint", "typescript"],
157 | "url": "https://github.com/colbywhite/acoustic-stack"
158 | }
159 | ]
160 | }
161 |
--------------------------------------------------------------------------------
/fly.toml:
--------------------------------------------------------------------------------
1 | # fly.toml app configuration file generated for remix-directory on 2023-05-23T22:40:36-07:00
2 | #
3 | # See https://fly.io/docs/reference/configuration/ for information about how to use this file.
4 | #
5 |
6 | app = "remix-directory"
7 | primary_region = "lax"
8 | kill_signal = "SIGINT"
9 | kill_timeout = "5s"
10 |
11 | [experimental]
12 | auto_rollback = true
13 |
14 | [env]
15 | PORT = "8080"
16 |
17 | [[services]]
18 | protocol = "tcp"
19 | internal_port = 8080
20 | processes = ["app"]
21 |
22 | [[services.ports]]
23 | port = 80
24 | handlers = ["http"]
25 | force_https = true
26 |
27 | [[services.ports]]
28 | port = 443
29 | handlers = ["tls", "http"]
30 |
31 | [services.concurrency]
32 | type = "connections"
33 | hard_limit = 25
34 | soft_limit = 20
35 |
36 | [[services.tcp_checks]]
37 | interval = "15s"
38 | timeout = "2s"
39 | grace_period = "1s"
40 | restart_limit = 0
41 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "remix-directory",
3 | "private": true,
4 | "description": "",
5 | "license": "",
6 | "sideEffects": false,
7 | "scripts": {
8 | "build": "remix build",
9 | "deploy": "fly deploy --remote-only",
10 | "dev": "remix dev",
11 | "start": "remix-serve build"
12 | },
13 | "dependencies": {
14 | "@remix-run/node": "^1.4.1",
15 | "@remix-run/react": "^1.4.1",
16 | "@remix-run/serve": "^1.4.1",
17 | "react": "^17.0.2",
18 | "react-dom": "^17.0.2"
19 | },
20 | "devDependencies": {
21 | "@remix-run/dev": "^1.4.1",
22 | "@remix-run/eslint-config": "^1.4.1",
23 | "@types/react": "^17.0.24",
24 | "@types/react-dom": "^17.0.9",
25 | "eslint": "^8.11.0",
26 | "typescript": "^4.5.5"
27 | },
28 | "engines": {
29 | "node": ">=14"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/public/assets/og.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nshki/remix-directory/b905653906e71ff5746af75bb03a1cb76ff11438/public/assets/og.png
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nshki/remix-directory/b905653906e71ff5746af75bb03a1cb76ff11438/public/favicon.ico
--------------------------------------------------------------------------------
/remix.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @type {import('@remix-run/dev').AppConfig}
3 | */
4 | module.exports = {
5 | ignoredRouteFiles: [".*"],
6 | // appDirectory: "app",
7 | // assetsBuildDirectory: "public/build",
8 | // serverBuildPath: "build/index.js",
9 | // publicPath: "/build/",
10 | };
11 |
--------------------------------------------------------------------------------
/remix.env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/start_with_migrations.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -ex
4 | npx prisma migrate deploy
5 | npm run start
6 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------