Skip to content

Remix Cookies — Direct Cookie Management

DodaTech Updated 2026-06-28 3 min read

In this tutorial, you will learn about Remix Cookies. We cover key concepts, practical examples, and best practices to help you master this topic.

Learn Remix cookies: create and manage cookies directly, set cookie attributes, read cookies in loaders and actions, and sign cookies for security.

In this lesson, you'll use Remix's cookie API to create, read, and write cookies directly without the session abstraction layer.

What You'll Learn

How to create cookies, read them in loaders, set them in actions, configure cookie attributes, and sign cookies for integrity.

Why It Matters

Cookies are useful for simple state like theme preferences, language settings, or A/B test assignments. Direct cookie access is simpler than sessions for single-value storage.

Real-World Use

DodaZIP stores user theme preference (light/dark), language choice, and dismissed announcements in cookies for instant access.

flowchart LR
    A[Create Cookie] --> B[Loader: Read]
    A --> C[Action: Write]
    B --> D[Component: Use Value]
    C --> E[Set-Cookie Header]
    style A fill:#121212,color:#fff
// app/cookies.server.ts
import { createCookie } from "@remix-run/node";

export const themeCookie = createCookie("theme", {
  maxAge: 60 * 60 * 24 * 365, // 1 year
  httpOnly: true,
  sameSite: "lax",
  secure: process.env.NODE_ENV === "production",
});

export const languageCookie = createCookie("lang", {
  maxAge: 60 * 60 * 24 * 30, // 30 days
});

Reading Cookies in Loaders

import { json } from "@remix-run/node";
import { themeCookie } from "~/cookies.server";

export const loader = async ({ request }) => {
  const theme = (await themeCookie.parse(request.headers.get("Cookie"))) || "light";
  return json({ theme });
};

Setting Cookies in Actions

import { redirect, json } from "@remix-run/node";
import { themeCookie } from "~/cookies.server";

export const action = async ({ request }) => {
  const formData = await request.formData();
  const theme = formData.get("theme");
  
  return json({ success: true }, {
    headers: {
      "Set-Cookie": await themeCookie.serialize(theme),
    },
  });
};
import { createCookie } from "@remix-run/node";

export const preferencesCookie = createCookie("prefs", {
  secrets: [process.env.COOKIE_SECRET],
  maxAge: 60 * 60 * 24 * 30,
});

Remix signs cookie values when a secrets array is provided, preventing tampering.

Multiple Cookies in One Response

export const action = async ({ request }) => {
  const theme = "dark";
  const lang = "es";
  
  const headers = new Headers();
  headers.append("Set-Cookie", await themeCookie.serialize(theme));
  headers.append("Set-Cookie", await languageCookie.serialize(lang));
  
  return json({ success: true }, { headers });
};

Common Mistakes

  1. Not using httpOnly for sensitive cookies: Without httpOnly, JavaScript can read the cookie, making it vulnerable to XSS Attacks.
  2. Omitting secure in production: Set secure: true to ensure cookies are only sent over HTTPS.
  3. Forgetting to parse cookies: cookie.parse() returns the value. Without Parsing, you get the raw cookie string.
  4. Setting cookies without sameSite: Default is lax, which is secure. Set sameSite: "none" only if cross-site requests need the cookie.
  5. Using cookies for large data: Cookies are included in every request. Keep values under 4KB.

Practice Questions

  1. How do you create a cookie in Remix? Answer: Use createCookie("name", options) from @remix-run/node. Options include maxAge, httpOnly, secure, and sameSite.

  2. How do you read a cookie in a loader? Answer: Parse it from the request header: await cookie.parse(request.headers.get("Cookie")).

  3. How do you set a cookie in a response? Answer: Call await cookie.serialize(value) and set it as a Set-Cookie header on the response.

  4. What happens if a cookie doesn't have a secrets array? Answer: The value is stored as-is, without signing. Users can modify it. Use secrets for values that affect application behavior.

Challenge

Build a theme switcher that stores the preference in a cookie, reads it in the root loader, and applies the theme class to the HTML element. The preference should persist across sessions.

Mini Project

Create a cookie consent system: store consent in a signed cookie, show the banner only for new visitors, and allow users to update preferences later. The cookie should expire after 6 months.

FAQ

What's the difference between cookies and sessions?

: Sessions use cookies as a storage key but keep data server-side. Cookies store data directly. Sessions are better for larger or sensitive data.

Can I delete a cookie?

: Set maxAge: 0 when serializing the cookie. The browser deletes it immediately.

How do I handle multiple cookie secrets?

: Pass an array. The first secret signs new cookies. Older secrets validate existing cookies for smooth rotation.

Can I use cookies for authentication?

: Yes, but sessions or HTTP-only cookie tokens are more secure for auth. Use signed cookies with httpOnly: true.

What's Next

Learn about Remix Authentication for implementing complete authentication systems.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro