Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ node_modules
/prisma/data.db
/prisma/data.db-journal
/tests/prisma
/prisma/generated

/test-results/
/playwright-report/
Expand Down
2 changes: 1 addition & 1 deletion app/routes/users/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { searchUsers } from '@prisma/client/sql'
import { searchUsers } from '#prisma/generated/sql.ts'

Check warning on line 1 in app/routes/users/index.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

`#prisma/generated/sql.ts` import should occur after import of `#app/utils/misc.tsx`
import { Img } from 'openimg/react'
import { redirect, Link } from 'react-router'
import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
Expand Down
6 changes: 5 additions & 1 deletion app/utils/auth.server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import crypto from 'node:crypto'
import { type Connection, type Password, type User } from '@prisma/client'
import {

Check warning on line 2 in app/utils/auth.server.ts

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

`#prisma/generated/client.ts` import should occur after import of `remix-utils/safe-redirect`
type Connection,
type Password,
type User,
} from '#prisma/generated/client.ts'
import bcrypt from 'bcryptjs'
import { redirect } from 'react-router'
import { Authenticator } from 'remix-auth'
Expand Down
7 changes: 5 additions & 2 deletions app/utils/db.server.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import 'dotenv/config'
import { styleText } from 'node:util'
import { remember } from '@epic-web/remember'
// Changed import due to issue: https://github.com/remix-run/react-router/pull/12644
import { PrismaClient } from '@prisma/client/index.js'
import { PrismaClient } from '#prisma/generated/client.ts'
import { PrismaBetterSQLite3 } from '@prisma/adapter-better-sqlite3'

Check warning on line 5 in app/utils/db.server.ts

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

`@prisma/adapter-better-sqlite3` import should occur before import of `#prisma/generated/client.ts`

export const prisma = remember('prisma', () => {
// NOTE: if you change anything in this function you'll need to restart
Expand All @@ -10,7 +11,9 @@
// Feel free to change this log threshold to something that makes sense for you
const logThreshold = 20

const adapter = new PrismaBetterSQLite3({ url: process.env.DATABASE_URL })
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Prisma Adapter: Mismatched Connection Type

The PrismaBetterSQLite3 adapter is initialized with { url: process.env.DATABASE_URL }, but this adapter requires a better-sqlite3 Database instance, not a URL string. The adapter expects an already-instantiated database connection from the better-sqlite3 package. This will cause a runtime error when the application tries to connect to the database.

Fix in Cursor Fix in Web

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, my friend cursor its fine :)

const client = new PrismaClient({
adapter,
log: [
{ level: 'query', emit: 'event' },
{ level: 'error', emit: 'stdout' },
Expand Down
1 change: 0 additions & 1 deletion docs/database.md
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,6 @@ You've got a few options:
re-generating the migration after fixing the error.
3. If you do care about the data and don't have a backup, you can follow these
steps:

1. Comment out the
[`exec` section from `litefs.yml` file](https://github.com/epicweb-dev/epic-stack/blob/main/other/litefs.yml#L31-L37).

Expand Down
9 changes: 5 additions & 4 deletions docs/decisions/031-imports.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ and manually modify.
Despite the magic of Path aliases, they are actually a standard `package.json`
supported feature. Sort of.
[The `"imports"` field](https://nodejs.org/api/packages.html#imports) in
`package.json` allows you to configure aliases for your imports.
TypeScript also uses this for its own Path aliases since version 5.4
so you get autocomplete and type checking for your imports.
`package.json` allows you to configure aliases for your imports. TypeScript also
uses this for its own Path aliases since version 5.4 so you get autocomplete and
type checking for your imports.

By using the `"imports"` field, you don't have to do any special configuration
for `vitest` or `eslint` to be able to resolve imports. They just resolve them
Expand All @@ -44,7 +44,8 @@ again it's just a matter of familiarity. So it's no big deal.

## Decision

We're going to configure `"imports"` in the `package.json` to use path aliases for imports.
We're going to configure `"imports"` in the `package.json` to use path aliases
for imports.

We'll set it to `"#*": "./*"` which will allow us to import anything in the root
of the repo with `#<dirname>/<filepath>`.
Expand Down
12 changes: 0 additions & 12 deletions docs/decisions/039-passkeys.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ username/password and OAuth providers. While these methods are widely used, they
come with various security challenges:

1. Password-based authentication:

- Users often reuse passwords across services
- Passwords can be phished or stolen
- Password management is a burden for users
Expand Down Expand Up @@ -39,14 +38,12 @@ using:
The authentication flow works as follows:

1. Registration:

- Server generates a challenge and sends registration options
- Client creates a new key pair and signs the challenge with the private key
- Public key and metadata are sent to the server for storage
- Private key remains securely stored in the authenticator

2. Authentication:

- Server generates a new challenge
- Client signs it with the stored private key
- Server verifies the signature using the stored public key
Expand All @@ -64,19 +61,16 @@ While passkeys represent the future of authentication, we maintain support for
password and OAuth authentication because:

1. Adoption and Transition:

- Passkey support is still rolling out across platforms and browsers
- Users need time to become comfortable with the new technology
- Organizations may have existing requirements for specific auth methods

2. Fallback Options:

- Some users may not have compatible devices
- Enterprise environments might restrict biometric authentication
- Backup authentication methods provide reliability

3. User Choice:

- Different users have different security/convenience preferences
- Some scenarios may require specific authentication types
- Supporting multiple methods maximizes accessibility
Expand Down Expand Up @@ -112,43 +106,37 @@ We chose SimpleWebAuthn because:
### Positive:

1. Enhanced Security for Users:

- Phishing-resistant authentication adds protection against common attacks
- Hardware-backed security provides stronger guarantees than passwords alone
- Biometric authentication reduces risk of credential sharing

2. Improved User Experience Options:

- Users can choose between password, OAuth, or passkey based on their needs
- Native biometric flows provide fast and familiar authentication
- Password manager integration enables seamless cross-device access
- Multiple authentication methods increase accessibility

3. Future-Proofing Authentication:

- Adoption of web standard
- Gradual transition path as passkey support grows
- Meeting evolving security best practices

### Negative:

1. Implementation Complexity:

- WebAuthn is a complex specification
- Need to handle various device capabilities
- Must maintain backward compatibility
- Need to maintain password-based auth as fallback

2. User Education:

- New technology requires user education
- Some users may be hesitant to adopt
- Need clear documentation and UI guidance

### Neutral:

1. Data Storage:

- New database model for passkeys
- Additional storage requirements per user
- Migration path for existing users
Expand Down
3 changes: 0 additions & 3 deletions docs/decisions/043-pwnedpasswords.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,19 @@ However, we wanted to implement this in a way that:
We will integrate the HaveIBeenPwned Password API with the following approach:

1. **Progressive Enhancement**

- The password check is implemented as a non-blocking enhancement
- If the check fails or times out (>1s), we allow the password
- This ensures users can still set passwords even if the service is
unavailable

2. **Development Experience**

- The API calls are mocked during development and testing using MSW (Mock
Service Worker)
- This prevents unnecessary API calls during development
- Allows for consistent testing behavior
- Follows our pattern of mocking external services

3. **Error Handling**

- Timeout after 1 second to prevent blocking users
- Graceful fallback if the service is unavailable
- Warning logs for monitoring service health
Expand Down
68 changes: 33 additions & 35 deletions docs/decisions/044-rr-devtools.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,33 @@ Status: accepted

## Context

Epic Stack uses React Router for routing. React Router is a powerful
library, but it can be difficult to debug and visualize the routing
in your application. This is especially true when you have a complex
routing structure with nested routes, dynamic routes, and you rely
on data functions like loaders and actions, which the Epic Stack does.

It is also hard to know which routes are currently active
(which ones are rendered) and if any if the loaders are triggered
when you expect them to be. This can lead to confusion and frustration
and the use of console.log statements to debug the routing in your
application.

This is where the React Router DevTools come in. The React
Router DevTools are a set of tools that do all of these things for you.

React Router has a set of DevTools that help debug and visualize the
routing in your application. The DevTools allow you to see the
current route information, including the current location, the matched
routes, and the route hierarchy. This can be very helpful when debugging
your applications. The DevTools also hook into your server-side by
wrapping loaders and actions, allowing you to get extensive
information about the data being loaded and the actions being dispatched.
Epic Stack uses React Router for routing. React Router is a powerful library,
but it can be difficult to debug and visualize the routing in your application.
This is especially true when you have a complex routing structure with nested
routes, dynamic routes, and you rely on data functions like loaders and actions,
which the Epic Stack does.

It is also hard to know which routes are currently active (which ones are
rendered) and if any if the loaders are triggered when you expect them to be.
This can lead to confusion and frustration and the use of console.log statements
to debug the routing in your application.

This is where the React Router DevTools come in. The React Router DevTools are a
set of tools that do all of these things for you.

React Router has a set of DevTools that help debug and visualize the routing in
your application. The DevTools allow you to see the current route information,
including the current location, the matched routes, and the route hierarchy.
This can be very helpful when debugging your applications. The DevTools also
hook into your server-side by wrapping loaders and actions, allowing you to get
extensive information about the data being loaded and the actions being
dispatched.

## Decision

We will add the React Router DevTools to the Epic Stack. The DevTools
will be added to the project as a development dependency. The DevTools
will be used in development mode only.
We will add the React Router DevTools to the Epic Stack. The DevTools will be
added to the project as a development dependency. The DevTools will be used in
development mode only.

The DevTools will be used to enhance the following:

Expand All @@ -45,19 +44,18 @@ The DevTools will be used to enhance the following:
6. See cache information returned via headers from your loaders
7. See which loaders/actions are triggered when you navigate to a route
8. and a lot more!


## Consequences

With the addition of the React Router DevTools, you will not have to rely on
console.log statements to debug your routing. The DevTools will provide you
with the tools to ship your applications faster and with more confidence.
console.log statements to debug your routing. The DevTools will provide you with
the tools to ship your applications faster and with more confidence.

The DevTools will also help you visualize the routing in your application,
which can be very helpful in understanding routing in general, and figuring
out if your routes are set up correctly.
The DevTools will also help you visualize the routing in your application, which
can be very helpful in understanding routing in general, and figuring out if
your routes are set up correctly.

They are not included in the production build by default, so you will not
have to worry about them being included in your production bundle.
They are only included in development mode, so you can use them without
any negative performance impact in production.
They are not included in the production build by default, so you will not have
to worry about them being included in your production bundle. They are only
included in development mode, so you can use them without any negative
performance impact in production.
Loading
Loading