smithery/ntq78

frontend-supabase-sdk

Use when making direct Supabase SDK calls in TypeScript files (hooks, components, routes, utilities)

Installation

$ npx skills add smithery/ntq78 --skill frontend-supabase-sdk

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery/ntq78.

npx skills add smithery/ntq78

Browse all from smithery/ntq78

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Skill metadata

Parsed from SKILL.md frontmatter.

Declared agents claude-code

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 6,333 B
  • docs SUMMARY.md 129 B

History

  1. First recorded snapshot · 0 installs

SKILL.md

Frontend Supabase SDK Usage

Naming Convention for SDK Responses

Pattern

const sb_Service[StringParam]_Operation = await supabase.service.method()

Components:

  • sb_ - Prefix for all Supabase SDK responses
  • Service - The Supabase service: Auth, From, Functions, Storage
  • [StringParam] - String parameters converted to PascalCase and concatenated directly (no underscore)
  • Operation - The primary operation: Select, Insert, Update, Delete, Invoke, etc.

String Parameter Conversion

snake_case → PascalCase

"organization_members" → OrganizationMembers
"rel_files_tags" → RelFilesTags

kebab-case → PascalCase

"generate-upload-url" → GenerateUploadUrl
"delete-file" → DeleteFile

Concatenation: String parameters are concatenated directly with the service/method name (no underscore between them)

Primary Operation Only

Use only the main operation, ignore modifiers like .single(), .eq(), .maybeSingle(), etc.

// ✅ Correct - primary operation only
const sb_FromProjects_Select = await supabase.from("projects").select().eq("id", id).single();

// ❌ Wrong - don't include modifiers
const sb_FromProjects_SelectEqSingle = await supabase
    .from("projects")
    .select()
    .eq("id", id)
    .single();

Core Examples

Database Operations (from)

// Insert
const sb_FromProjects_Insert = await supabase.from("projects").insert(body).select().single();

// Select
const sb_FromOrganizationMembers_Select = await supabase
    .from("organization_members")
    .select("*, organizations(*)")
    .eq("user_id", userId);

// Update
const sb_FromProjects_Update = await supabase
    .from("projects")
    .update(body)
    .eq("id", id)
    .select()
    .single();

// Delete
const sb_FromRelFilesTags_Delete = await supabase
    .from("rel_files_tags")
    .delete()
    .eq("file_id", fileId);

Auth Operations

const sb_Auth_GetUser = await supabase.auth.getUser();
const user = sb_Auth_GetUser.data.user;

const sb_Auth_GetSession = await supabase.auth.getSession();
const session = sb_Auth_GetSession.data.session;

const sb_Auth_SignOut = await supabase.auth.signOut();

Functions (Edge Functions)

const sb_Functions_InvokeGenerateUploadUrl = await supabase.functions.invoke(
    "generate-upload-url",
    { body: { fileName, projectId } }
);

Storage Operations

const sb_StorageProjectFiles_Upload = await supabase.storage
    .from("project-files")
    .upload(path, file);

const sb_StorageProjectFiles_Download = await supabase.storage.from("project-files").download(path);

Accessing Data and Errors

const sb_FromProjects_Select = await supabase.from("projects").select();
if (sb_FromProjects_Select.error) {
    console.error(sb_FromProjects_Select.error);
    throw sb_FromProjects_Select.error;
}
const projects = sb_FromProjects_Select.data;

Why This Convention?

❌ Problems with Destructuring

Naming Conflicts:

const { data, error } = await supabase.from("projects").insert();
const { data, error } = await supabase.from("files").select(); // ❌ Conflict!

Ugly Inline Renaming:

const { data: uploadData, error: urlError } =
    await supabase.functions.invoke("generate-upload-url");
const {
    data: { user },
    error: userError,
} = await supabase.auth.getUser();
const { data: metadata, error: metadataError } = await supabase.from("files").insert();

Inconsistent Patterns:

const { data: projects, error: projectsError }; // One dev's choice
const { data: projectData, error: projectErr }; // Another dev's choice

✅ Benefits of sb\_\* Pattern

  • No Conflicts: Each variable has unique, descriptive name
  • Explicit and Verbose: Immediately clear what each variable represents
  • Consistent Convention: Always follows same pattern - no guessing
  • Better for AI/LLM: Systematic and reliably followed
  • Self-Documenting: Variable name describes the operation

Common Patterns

Error Handling

const sb_FromProjects_Insert = await supabase.from("projects").insert(body);
if (sb_FromProjects_Insert.error) {
    console.error("Failed to create project:", sb_FromProjects_Insert.error);
    throw sb_FromProjects_Insert.error;
}
return sb_FromProjects_Insert.data;

Early Return

const sb_Auth_GetUser = await supabase.auth.getUser();
if (sb_Auth_GetUser.error || !sb_Auth_GetUser.data.user) {
    return null;
}
const user = sb_Auth_GetUser.data.user;

Nested Data

const sb_Auth_GetSession = await supabase.auth.getSession();
const session = sb_Auth_GetSession.data.session;

Usage in Different Contexts

**In Query Hooks (useQ\_\*):**

const queryFn = async (projectId: string) => {
    const sb_FromFiles_Select = await supabase
        .from("files")
        .select("*, rel_files_tags(file_tags(*))")
        .eq("project_id", projectId);

    if (sb_FromFiles_Select.error) throw sb_FromFiles_Select.error;
    return sb_FromFiles_Select.data;
};

**In Mutation Hooks (useM\_\*):**

const mutationFn = async (body: CreateProjectBody) => {
    const sb_FromProjects_Insert = await supabase.from("projects").insert(body).select().single();

    if (sb_FromProjects_Insert.error) throw sb_FromProjects_Insert.error;
    return sb_FromProjects_Insert.data;
};

In Route Guards:

export const loader = async () => {
    const sb_Auth_GetSession = await supabase.auth.getSession();
    const session = sb_Auth_GetSession.data.session;

    if (!session) {
        throw redirect({ to: "/login" });
    }

    return { session };
};

Related Skills

  • frontend-query-hooks - Query hooks using this convention
  • frontend-mutation-hooks - Mutation hooks using this convention
  • frontend-supabase-auth - Auth-specific patterns

For additional examples: .claude/skills/frontend-supabase-sdk/examples.md

<!-- Last compacted: 2025-11-16 -->