Skip to content

jkcorrea/remix-chop-suey-stack

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

28 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Remix Chop Suey Stack

Forked from Supa Fly Stack.
Learn more about Remix Stacks.

Quickstart

npx create-remix --template jkcorrea/remix-chop-suey-stack

What's in it?

The hits:

Bonus tracks:

Not a fan of bits of the stack? Fork it, change it, and use npx create-remix --template your/repo! Make it your own.

Alternatives from the community

If you want to try out EdgeDB and Remix but don't like this particular stack, check out these amazing starters:

Why?

I run my startup on Redwood + Supabase + Prisma. All great projects that I still recommend, but a few things have been paining me:

  • Prisma can feel janky. Migrations occasionally get out of sync, rollbacks are a mess, schemas aside from public aren't supported in migrations, generated queries can start to suck for complex logic.
  • Supabase, as of today, requires a minor in SQL to get shit done (though, I do agree it is the right approach, I just don't have time to think about DB management right now)
  • My Redwood codebase got a bit bloated. There's more "state" in the system than I'd like, making it difficult to add new code without breaking old code. I didn't make use of many of the niceties of Redwood (Cells, Storybook, tests, etc), and so have a lot of bloat for no reason in the project now.

My thought is that EdgeDB will take care of the shaky migration + SQL management problems, while Remix may help me reduce the state & logic to reason about between the front & back ends.

It ended up being a lot of exploratory work to get all these technologies working together since they're all fairly new, so I figured I should package it up as a template while I'm at it 🀠

PRO TIP: For extra productivity, the author recommends listening to System of a Down while developing on this stack 🀘

TODO

a.k.a. things that will never get done

  • Deploy to Fly w/ EdgeDB (& document)
  • Database dev/test seeds
  • Setup some actual unit tests
  • Mock auth (so we don't have to create/delete users on the real Clerk api)
  • Consider moving over to Playwright for e2e tests

Setup

EdgeDB

First install the cli via the EdgeDB installation guide, then in this project directory run (the initializer prompts to do this for you):

edgedb project init # Initialize a local db instance
yarn generate:edgeql # Generate the query builder

Clerk Auth

Setup an account at Clerk.dev to your liking. When ready, copy the relevant API keys into your .env.

Development

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

yarn dev

Migrations

When adding migrations, you'll want to re-generate your EdgeDB query builder with a yarn edgedb-js --output-file ./app/db/edgeql --force-overwrite. Or, simply apply your migrations via:

yarn db:migrate # will apply migration AND regenerate the query builder

Relevant Files

This is a pretty simple CRUD app, but it's a good example of how you can build a full stack app with Prisma, Supabase and Remix. The main functionality is creating users, logging in and out (handling access and refresh tokens + refresh on expire), and creating and deleting notes.

  • DB
    • app/db/db.server.ts - initializes the EdgeDB client
    • app/db/edgeql/ - contains the generated EdgeQL query builder.
    • app/models/ - abstracts away EdgeQL queries to keep loaders/actions simple
    • dbschema/ - contains your EdgeQL schema & migrations
  • Auth
    • app/routes/__auth - login & signup pages, wrapped by a Remix layout route. Clerk makes auth really simple.
    • app/settings - I wanted users to have a unified settings page for everything account + non-account related, so this shows how to do that with Clerk components
  • App
    • app/__app - Realizing this is a poor naming choice now. Basically just wanted to demo some simple CRUD with toasts & loading state transitions.
  • Test
    • cypress/ - e2e tests live here
    • mocks/ - not yet implemented, but could use this to mock out db/3rd-party requests (e.g. mocking auth without connecting to Clerk)
    • TODO: implement some unit tests to demo vitest.

Deployment

Do what you know if you are a Fly.io expert.

NOTE: Deploying EdgeDB is left as an exercise to the reader. I have not flushed out the best way to deploy it yet and it seems the EdgeDB maintainers have plans for a cloud-hosted version of it coming soon, so I'm waiting for that. In the meantime, you'll have to host your own and supply the EDGEDB_DSN to your Fly app.

This Remix Stack comes with GitHub Actions that automatically deploy your app to production and staging environments on Fly.

Prior to your first deployment, you'll need to do a few things:

  • Install Fly

  • Sign up and log in to Fly

    fly auth signup

    Note: If you have more than one Fly account, ensure that you are signed into the same account in the Fly CLI as you are in the browser. In your terminal, run fly auth whoami and ensure the email matches the Fly account signed into the browser.

  • Create two apps on Fly, one for staging and one for production:

    fly create remix-chop-suey-stack
    fly create remix-chop-suey-stack-staging
    • Initialize Git.
    git init
  • Create a new GitHub Repository, and then add it as the remote for your project. Do not push your app yet!

    git remote add origin <ORIGIN_URL>
  • Add a FLY_API_TOKEN to your GitHub repo. To do this, go to your user settings on Fly and create a new token, then add it to your repo secrets with the name FLY_API_TOKEN.

  • Add your other secrets from .env to your Fly app. You can do this with a command similar to:

    # staging
    fly secrets set CLERK_FRONTEND_API="CLERK_FRONTEND_API" --app remix-chop-suey-stack-staging
    fly secrets set CLERK_API_KEY="CLERK_API_KEY" --app remix-chop-suey-stack-staging
    fly secrets set CLERK_JWT_KEY="CLERK_JWT_KEY" --app remix-chop-suey-stack-staging
    fly secrets set EDGEDB_DSN="EDGEDB_DSN" --app remix-chop-suey-staging-stack # See above note about deploying EdgeDB
    
    # production
    fly secrets set CLERK_FRONTEND_API="CLERK_FRONTEND_API" --app remix-chop-suey-stack
    fly secrets set CLERK_API_KEY="CLERK_API_KEY" --app remix-chop-suey-stack
    fly secrets set CLERK_JWT_KEY="CLERK_JWT_KEY" --app remix-chop-suey-stack
    fly secrets set EDGEDB_DSN="EDGEDB_DSN" --app remix-chop-suey-stack # See above note about deploying EdgeDB

Now that everything is set up you can commit and push your changes to your repo. Every commit to your main branch will trigger a deployment to your production environment, and every commit to your dev branch will trigger a deployment to your staging environment.

GitHub Actions

We use GitHub Actions for continuous integration and deployment. Anything that gets into the main branch will be deployed to production after running tests/build/etc. Anything in the dev branch will be deployed to staging.

πŸ‘‰ You have to add some env secrets for cypress. πŸ‘ˆ

Add the same secrets as above to your GitHub actions (https://docs.github.com/en/actions/security-guides/encrypted-secrets).

Testing

Cypress

We use Cypress for our End-to-End tests in this project. You'll find those in the cypress directory. As you make changes, add to an existing file or create a new file in the cypress/e2e directory to test your changes.

We use @testing-library/cypress for selecting elements on the page semantically.

To run these tests in development, complete your .env and run yarn test:e2e:dev which will start the dev server for the app as well as the Cypress client. Make sure the database is running in docker as described above.

We also have a utility to auto-delete the user at the end of your test. Just make sure to add this in each test file:

afterEach(() => {
  cy.teardownAuth();
});

That way, we can keep your test db clean and keep your tests isolated from one another.

Vitest

For lower level tests of utilities and individual components, we use vitest. We have DOM-specific assertion helpers via @testing-library/jest-dom.

Type Checking

This project uses TypeScript. It's recommended to get TypeScript set up for your editor to get a really great in-editor experience with type checking and auto-complete. To run type checking across the whole project, run yarn typecheck.

Linting

This project uses ESLint for linting. That is configured in .eslintrc.js.

Formatting

We use Prettier for auto-formatting in this project. It's recommended to install an editor plugin (like the VSCode Prettier plugin) to get auto-formatting on save. There's also a yarn format script you can run to format all files in the project.