Learn more about Remix Stacks.
npm init remix -- --template markmals/lo-fi-stack
- Preact UI runtime
- Atomic styling with Tailwind CSS
- Style processing with PostCSS
- Default support for build-time imports, nesting, and autoprefixer
- Store and sync app data with Cloud Firestore using Holocron
- Simple sign-in and account management with Firebase Authentication
- Deploy to Fly.io
- Component stories with Storybook
- Unit testing with Vitest and Testing Library
- Code formatting with Prettier
- Linting with ESLint
- Git hooks with Husky
- Static types with TypeScript
- Flat routing convention
- Type-safe routing
- Reccomended Visual Studio Code extensions
Not a fan of bits of the stack? Fork it, change it, and use npm init remix -- --template your/repo
! Make it your own.
From your terminal:
npm run dev
This starts your app in development mode, rebuilding assets on file changes.
- Create a Firebase Project
- Enable Auth (with email) and Firestore
- Add a Web App
- Get the admin-sdk and Web Client Config Object
- Save them to SERVICE_ACCOUNT and CLIENT_CONFIG in the
.env
-file
signIn
returns a Firebase session-cookie-string, when sign-in is successfull. Then Remix cookieSessionStorage
is used to set, read and destroy it.
signUp
creates a user and calls sign-in to receive the session cookie.
requireAuth
uses firebase-admin
to verify the session cookie. When this check fails, it throws a redirect
to the login page. Use this method to protect loaders and actions. The returned UserRecord
can be handy to request or manipulate data from the Firestore for this user.
The default setup exports Holocron databases connected to Firestore collections.
Requests to the Firestore are made using the firebase-admin
-SDK. You need to check validity of your requests manually, since firestore.rules
don't apply to admin requests.
For lower level tests of utilities and individual components, we use vitest
. We have DOM-specific assertion helpers via @testing-library/jest-dom
.
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 npm run typecheck
.
This project uses ESLint for linting. That is configured in .eslintrc.js
.
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 npm run format
script you can run to format all files in the project.
-
Sign up and log in to Fly
flyctl auth signup
- Setup Fly. It might ask if you want to deploy, say no since you haven't built the app yet.
flyctl launch
Once you've followed the setup instructions, all you need to do is run this:
npm run deploy
You can run flyctl info
to get the url and ip address of your server.
Check out the fly docs for more information.
This repo has been modified to add static site generation capabilities.
Ensure you have wget
installed:
which wget
If not, install it:
brew install wget
To build your site statically, first do a normal build and boot the production server as shown above.
Then, in a separate terminal tab do:
npm run build-static
This will generate a static
directory with the HTML files and assets you need to serve a fully hydrated Remix site. It uses wget
to pull HTML, CSS, and JS from the server you have running in the other tab. It pulls all the URLs listed in static-urls.txt
. Once it completes, you can shut down the local server.
To test out your static build, run:
npm run serve-static
To deploy, just copy the static
dir to your static hosting provider.
IMPORTANT
This isn't typically how Remix works (we usually have a server) so you'll want to note a few things about this setup:
loader
still works (seeapp/routes/one.tsx
andapp/routes/two.tsx
) so you can still grab data from the filesystem or from your database and put it into your markup viauseLoaderData
- Although the page is fully hydrated with React on it (we are still rendering the
<Scripts>
element inapp/root.tsx
) all navigation on the site should be done with a full document reload (using<Link reloadDocument>
). This is because no server is running to be able to dynamically serve the data we need for the new route when we do a client-side transition to it. However, the data is already encoded in the HTML in thestatic
output directory we generated in thebuild-static
command. - Other features that require a server (like
action
) will not work.