Tutorials
Learn about Remix, React, and more.
Subscribe to my tutorials using RSS.
- Build a Command-Driven Markdown Toolbar in React
- Handle Custom Invoker Commands in React
- Build a User Menu in React with Invoker Popover Commands
- Prevent a Modal Dialog from Closing with request-close in React
- Open a Modal Dialog in React with the Invoker Commands API
- Use an `iife` Helper for Inline Control Flow in TypeScript
- Cancel `useFetcher().load()` Requests on Unmount in React Router
- Access React Router Context with AsyncLocalStorage
- Create a Per-Request Database Instance with Middleware
- Create a Multi-Directory Route Organization in React Router
- Use Sec-Fetch Headers for CSRF Protection
- Dedupe Server Calls with Remix Utils Batcher
- Transform FormData Between UI and Database in React Router
- Build a Nested Master-Detail View with Redirects in React Router
- Stream Shared Promise Results in React Router
- Redirect Based on Screen Size in React Router
- Avoid Waterfalls in React Suspense
- Render Loader Promises with Suspense in React Router
- Create Reusable Action Routes in React Router
- Add a Cookie-Based Color Scheme Toggle in React Router
- Debounce Loaders and Actions in React Router
- Authenticate OAuth2 Clients with client_id and client_secret
- Use the OAuth2 Introspection Endpoint
- Revoke OAuth 2.0 Refresh Tokens via the Revocation Endpoint
- Protect OAuth 2.0 Authorization Code Flow with PKCE
- Add Custom Claims to JWT Access Tokens Safely
- Validate JWT Expiration, Issued-At, and Not-Before Claims
- Use OAuth 2.0 Scopes to Authorize API Actions
- Validate JWTs with JWKS
- Create a Per-Request Singleton with React Router Middleware
- Test React Router Middleware with Bun Test
- Enable and use middleware in React Router 7.3
- Show a 404 in React Router
- Trigger File Downloads from React Router Loaders and Actions
- Use Bullet to Detect N+1 Queries in Rails
- Convert Markdown to PDF and ePub with Pandoc
- Serve User-Specific Stylesheets in React Router
- Split a React Router Route Config across Multiple Files
- Configure the tracking branch in Git
- Reuse route modules in React Router
- Populate Your Rails Database with Fixtures
- Stub a method in a class with Minitest
- Show toast after a Remix action
- Simplify Component Imports with TypeScript Namespaces
- Validate a Form in Remix with clientAction
- Generate a Cloudflare Environment Type with wrangler
- Configure Scoped Private Packages in Bun
- Use package.json#bin to create a CLI
- Access location.state in Remix Client Loaders and Actions
- Add Internationalization with remix-i18next to a Remix Vite App
- Autoload the Correct Node.js Version with NVM
- Nest Routes with Dynamic Params in Remix
- Build Register, Login, and Logout Flows with Remix Sessions
- Access React Router's loader data from a route ErrorBoundary
- Access React Router's Loaders Data in entry.client
- Handle not found URLs with Remix
- Persist the User Locale Using Cookies with React Router and i18next
- Add dynamic canonical URL to Remix routes
- Add custom attributes to Markdoc code fences
- Enable Remix ~/ aliased imports in Vitest
- Add syntax highlight to Markdoc using Prism.js
- Create a CRUD with Remix
- Pass Cookies from a React Router Loader to an External API
- Call an action from a loader in Remix
- Use React Portal in Remix
- Prevent the React Router Loader to Run after Document Request
- Defer a Fetch response in Remix
- Use a CDN for your static assets in Remix
- Get the absolute URL in Remix's MetaFunction
- Build an app with Remix and Bun
- Find and remove unused code with Knip
- Create multiple top-level layouts in Remix
- Test meta tags using Playwright
- Prefetch data for Remix Fetcher usage
- Keep Your Loader Data Fresh in Remix
- Share Remix Route Logic between Web and API Routes
- Access the Search Params of a Request in React Router
- Upload Images in a Remix Application
- Redirect with Search Param in Remix
- Access the Loader Data in Remix
- Abort Async Calls Inside Remix Loaders and Actions
- Get Remix route params `entry.server`
- Test meta tags with Cypress
- Strongly type Remix route IDs
- Strongly type public assets in Remix
- Create a reusable Form component in Remix
- Sync text input with URLSearchParam in Remix
- Use TanStack Query to Share Data between React Router Loaders
- Logout from Auth0 with Remix Auth
- Send Node.js ReadStream objects from Remix loaders
- Reset a form on success in Remix
- Use `qs.parse` to use nested form fields in Remix
- Send JSON to a Remix action
- Set Multiple Cookies in the Same Response in React Router Loaders
- Close SSE connection from the server in Remix
- Measure performance with the Server-Timing header in React Router
- Automatically commit sessions on Remix
- Customize Remix AppLoadContext type
- Turn on Caps Lock on Cypress
- Delete a Cookie using Remix cookie helpers
- Add runtime SSG and ISR to Remix
- Improve SEO by not sending JS in Remix
- Use AMP with Remix
- Use Remix as a SPA only
- Downgrade to MPA if Users Prefer Reduced Data in React Router
- Add rolling sessions to Remix
- Use Server-Sent Events with Remix
- Progressively Enhance the useFetcher Hook in React Router
- Use `process.env` client-side with Remix
- Persist inputs after a form submit in Remix
- Lazy-load React components in Remix
- Destroy User Session and While Setting a Flash Message in React Router
- Add additional data before submitting on Remix
- Redirect to an external website with Remix
- Bubble up data on Remix routes
- Group related routes together in Remix
- Parse Markdown with Markdoc in Remix
- Optimize image loading with plain HTML
- Add returnTo behavior to Remix Auth
- Share session and cookies between Next and Remix
- Fix double data request when prefetching in Remix
- Run Tailwind and Remix in Parallel with PM2
- Use Remix with socket.io
- Generate a PDF in Remix with Resource Routes
- Avoid waterfalls of queries in Remix loaders
- Run Next and Remix on the same server
- Test Remix loaders and actions
- Use NProgress in a Remix app
- Use Fathom with Remix
- Fix `gyp: No Xcode or CLT version detected!` error
- Use Dependabot to keep Remix up-to-date
- Load only the data you need in Remix
- Use ETags in Remix
- Redirect to the original URL inside a Remix action
- Read search params with JS
- Use ActiveModel::Serializer with non ActiveRecord object
- Serialize list of items with ActiveModel::Serializer
- Use serializers with JSON.stringify and JSON.parse
- Force a locale in Rails I18n from the params
- Add missing `created_at` and `updated_at` columns in Rails
- Build your own RSS Reader
- Keep Heading Levels Consistent with React Context
- Use TailwindCSS Typography with Dark Mode Styles
- Use SWR with Geolocation
- Sync WebApp Session Status between Tabs with SWR
- Sync SWR cache with Web Storage
- Configure Google Suite MX records in Vercel
- Report Web Vitals in Next.js
- Use React.Suspense to wait for an image to load
- Purge unused CSS with TailwindCSS
- Setup a redirect inside a project deployed to Vercel
- Use a scoped registry with Yarn
- Automatically Publish to npm using GitHub Actions