Skip to content

Instantly share code, notes, and snippets.

View sergiodxa's full-sized avatar

Sergio Xalambrí sergiodxa

View GitHub Profile
@sergiodxa
sergiodxa / remix-v3-queue-task.tsx
Created October 15, 2025 06:21
An example on how to use `this.queueTask` to run something on every render or on mount
import type { Remix } from "@remix-run/dom";
import { press } from "@remix-run/events/press";
function Component(this: Remix.Handle) {
let isMounted = false;
let renderCount = 0;
// Runs once after first render (setup phase)
this.queueTask(() => {
isMounted = true;
@sergiodxa
sergiodxa / remix-v3-x-tanstack-query.tsx
Created October 12, 2025 04:40
An example on how to use Remix v3 along TanStack Query
import { hydrated, type Remix } from "@remix-run/dom";
import { press } from "@remix-run/events/press";
import {
QueryClient,
QueriesObserver,
type QueryObserverOptions,
} from "@tanstack/query-core";
type Todo = {
userId: number;
@sergiodxa
sergiodxa / counter.tsx
Last active October 12, 2025 00:26
A state helper that simulates useState for Remix v3
import type { Remix } from "@remix-run/dom";
import { press } from "@remix-run/events/press";
import { state } from "./state";
export function Counter(this: Remix.Handle, { initial }: { initial?: number }) {
let [count, setCount] = state(this, initial ?? 0);
return () => (
<button type="button" on={[press(() => setCount((c) => c + 1))]}>
@sergiodxa
sergiodxa / crud.ts
Last active April 21, 2025 04:56
A crud helper for RRv7 routes.ts file
import { index, prefix, route } from "@react-router/dev/routes";
import { camelize, pluralize, singularize } from "inflected";
function createCrud(base = "./views") {
/**
* Create a CRUD route configuration.
* @param name The name of the resource. It will be pluralized for the path.
* @param options The options for the crud.
* @param options.member Extra routes to add to each member.
* @param options.collection Extra routes to add to the collection.
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 December 5, 2024 08:05
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",