Skip to content

Instantly share code, notes, and snippets.

View sergiodxa's full-sized avatar

Sergio Xalambrí sergiodxa

View GitHub Profile
import Auth0 from "@auth/core/providers/auth0";
import { RemixAuth } from "~/services/auth"
import { sessionStorage } from "~/services/session.server";
export let { loader, action } = RemixAuth({
sessionStorage: sessionStorage, // this does nothing yet
secret: process.env.AUTH_SECRET ?? "s3cr3t",
providers: [
Auth0({
@sergiodxa
sergiodxa / persist-inputs-remix-gh-copilot.md
Created October 20, 2022 21:47
An article completely generated by GitHub Copilot based on a title, with just a few minor errors

Persist user inputs after form submit in Remix

This tutorial will show you how to persist user inputs after form submit in Remix.

Prerequisites

Steps

@sergiodxa
sergiodxa / tailwind.config.js
Created June 22, 2022 18:07
Example Tailwind config for max and range screen sizes.
module.exports = {
theme: {
screens: {
"-2xl": { max: "1536px" },
"-xl": { max: "1280px" },
"-lg": { max: "1024px" },
"-md": { max: "768px" },
"-sm": { max: "640px" },
"sm~md": { min: "640px", max: "768px" },
"md~lg": { min: "768px", max: "1024px" },
@sergiodxa
sergiodxa / articles.test.ts
Last active May 15, 2022 22:34
An E2E helper for Vitest and Puppeteer to test Remix app
import { test, expect, describe, beforeAll, afterAll } from "vitest";
import "pptr-testing-library/extend";
import { type App, start } from "test/helpers/app";
import { loader } from "./articles";
import { logger } from "~/services/logger.server";
import type { PrismaClient } from "@prisma/client";
import { createDatabaseClient } from "test/helpers/db";
describe("E2E", () => {
let app: App;
@sergiodxa
sergiodxa / entry.server.tsx
Last active May 7, 2024 12:30
Dynamically generate a PDF with Remix
import { renderToStream } from "@react-pdf/renderer";
import ReactDOMServer from "react-dom/server";
import { EntryContext, Headers, RemixServer, Request, Response } from "remix";
import PDF, { loader } from "./pdfs/my-pdf.server";
async function handlePDFRequest(request: Request, headers: Headers) {
// get the data for the PDF
let response = await loader({ request, context: {}, params: {} });
// if it's a response return it, this means we redirected
if (response instanceof Response) return response;
@sergiodxa
sergiodxa / .eslintrc.js
Created July 30, 2021 22:45
My favorite ESLint configuration
/* eslint-disable unicorn/prefer-module */
module.exports = {
root: true,
parser: "@typescript-eslint/parser",
plugins: [
"@typescript-eslint",
"unicorn",
"import",
"react",
"prettier",
@sergiodxa
sergiodxa / remix-auth.ts
Created July 21, 2021 23:25
Remix authentication library usage example
// create a session storage instance
let sessionStorage = createCookieSessionStorage();
// create authenticator instance
let authenticator = new Authenticator<User>(
sessionStorage
);
// configure the authenticator to use the Auth0 strategy for sign-in
authenticator.use(
@sergiodxa
sergiodxa / csrf.tsx
Last active September 9, 2022 18:03
A module with the implementation for CSRF protection in Remix
import { randomBytes } from 'crypto';
import * as React from 'react';
import { Request, Session } from 'remix';
import { parseBody, parseParams } from './parse-body';
/**
* An error that is thrown when a CSRF token is missing or invalid.
* @example
* throw new InvalidAuthenticityToken("Can't verify CSRF token authenticity.");
* @example
@sergiodxa
sergiodxa / serializer.ts
Last active May 26, 2021 01:50
Serializer in TS similar to ActiveModel::Serializer
abstract class Serializer {
abstract attributes: string[];
[customAttribute: string]: unknown; // this allow this[attribute] to work so we can use getters to add extra attributes
constructor(protected input: Record<string, unknown>) {}
private filterAttributes() {
return Object.fromEntries(
this.attributes.map((attribute) => {
@sergiodxa
sergiodxa / use-translations.tsx
Last active May 11, 2021 00:11
A custom Hook built on top of React Query to use translations from a backend
import ms from "ms";
import * as React from "react";
import { useQuery } from "react-query";
import { hasOwn } from "../utils";
let isProduction = process.env.NODE_ENV === "production";
export interface Translations {
[key: string]: string;
}