Dyrected
Examples & RecipesRecipe Library

Scope content to the current workspace

Stamp a workspace identifier onto new records and filter reads and writes to that tenant boundary.

This generated recipe is review-ready source material. Use it from the runtime where it appears in the sidebar and search results.

Stamp a workspace identifier onto new records and filter reads and writes to that tenant boundary.

Use this when

  • add multi-tenant access control
  • scope records to a workspace
  • keep organizations isolated
  • limit data by tenant

Dyrected concepts

access, beforeChange, tenant isolation

Additional packages: No additional packages.

Decisions and cautions

Use this recipe only when its runtime matches the project you are documenting or building. Cloud recipes must stay inside the managed content backend boundary. Self-hosted recipes may use the server runtime, database, hooks, and infrastructure you control.

Complete recipe

This is the canonical source compiled and behavior-tested by @dyrected/knowledge.

import { defineCollection, defineTextField } from "@dyrected/core";

const getWorkspaceId = (user?: unknown) => {
  if (!user || typeof user !== "object") return undefined;
  const workspaceId = (user as Record<string, unknown>).workspaceId;
  return typeof workspaceId === "string" && workspaceId.length > 0
    ? workspaceId
    : undefined;
};

export const Projects = defineCollection({
  slug: "projects",
  access: {
    read: ({ user }) =>
      getWorkspaceId(user)
        ? { workspaceId: { equals: getWorkspaceId(user) } }
        : false,
    create: ({ user }) => Boolean(getWorkspaceId(user)),
    update: ({ user }) =>
      getWorkspaceId(user)
        ? { workspaceId: { equals: getWorkspaceId(user) } }
        : false,
    delete: ({ user }) =>
      user?.roles?.includes("admin")
        ? true
        : getWorkspaceId(user)
          ? { workspaceId: { equals: getWorkspaceId(user) } }
          : false,
  },
  hooks: {
    beforeChange: [
      ({ data, operation, user }) => {
        if (operation !== "create") return data;
        const workspaceId = getWorkspaceId(user);
        if (!workspaceId) {
          throw new Error("A workspace is required to create a project.");
        }
        return { ...data, workspaceId };
      },
    ],
  },
  fields: [
    defineTextField({ name: "name", label: "Project name", required: true }),
    defineTextField({
      name: "workspaceId",
      label: "Workspace ID",
      required: true,
      admin: { readOnly: true },
    }),
  ],
});

On this page

Dyrected| Cloud

Get your backend ready in minutes

Use a managed database, storage, APIs, and admin dashboard without setting up the infrastructure yourself.

Set Up My Backend