{
  "schemaVersion": "1.0",
  "item": {
    "slug": "supabase-hakke",
    "name": "Supabase Hakke",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/studio-hakke/supabase-hakke",
    "canonicalUrl": "https://clawhub.ai/studio-hakke/supabase-hakke",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/supabase-hakke",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=supabase-hakke",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-05-07T17:22:31.273Z",
      "expiresAt": "2026-05-14T17:22:31.273Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=afrexai-annual-report",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=afrexai-annual-report",
        "contentDisposition": "attachment; filename=\"afrexai-annual-report-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/supabase-hakke"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/supabase-hakke",
    "agentPageUrl": "https://openagent3.xyz/skills/supabase-hakke/agent",
    "manifestUrl": "https://openagent3.xyz/skills/supabase-hakke/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/supabase-hakke/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Supabase for Hakke Studio",
        "body": "Supabase integration específica para proyectos de Hakke Studio."
      },
      {
        "title": "Proyectos Actuales",
        "body": "ProyectoSupabase URLUsohakke-apphttps://[project].supabase.coSaaS multi-tenant"
      },
      {
        "title": "CLI Installation",
        "body": "# Supabase CLI (ya instalado)\nsupabase --version\n\n# Si no está instalado\nnpm install -g supabase"
      },
      {
        "title": "Login to Supabase",
        "body": "supabase login\n\nThis opens browser for OAuth login with contacto@hakke.cl."
      },
      {
        "title": "Link Project",
        "body": "cd /home/bastianberrios/proyectos/HAKKE/hakke-app\nsupabase link --project-ref <project-id>"
      },
      {
        "title": "Generate Types",
        "body": "supabase gen types typescript --local > lib/supabase/database.types.ts"
      },
      {
        "title": "Create Migration",
        "body": "supabase migration new <migration_name>"
      },
      {
        "title": "Apply Migration",
        "body": "supabase db push"
      },
      {
        "title": "Reset Database (DEV ONLY)",
        "body": "supabase db reset"
      },
      {
        "title": "Get API Keys",
        "body": "supabase status\n\nReturns:\n\nanon key - Public key (client-side)\nservice_role key - Secret key (server-side ONLY)"
      },
      {
        "title": "Create User (Admin)",
        "body": "-- In Supabase Dashboard SQL Editor\nINSERT INTO auth.users (email, encrypted_password, email_confirmed_at)\nVALUES (\n  'user@example.com',\n  crypt('password123', gen_salt('bf')),\n  NOW()\n);"
      },
      {
        "title": "Enable RLS",
        "body": "ALTER TABLE users ENABLE ROW LEVEL SECURITY;"
      },
      {
        "title": "Create Policy",
        "body": "-- Users can only see their own data\nCREATE POLICY \"Users can view own data\"\nON users\nFOR SELECT\nUSING (auth.uid() = id);\n\n-- Users can update own data\nCREATE POLICY \"Users can update own data\"\nON users\nFOR UPDATE\nUSING (auth.uid() = id);"
      },
      {
        "title": "Create Bucket",
        "body": "-- In Supabase Dashboard SQL Editor\nINSERT INTO storage.buckets (id, name, public)\nVALUES ('avatars', 'avatars', false);"
      },
      {
        "title": "Storage Policy",
        "body": "-- Users can upload to own folder\nCREATE POLICY \"Users can upload avatars\"\nON storage.objects\nFOR INSERT\nWITH CHECK (\n  bucket_id = 'avatars'\n  AND auth.uid()::text = (storage.foldername(name))[1]\n);"
      },
      {
        "title": "Create Function",
        "body": "supabase functions new <function-name>"
      },
      {
        "title": "Deploy Function",
        "body": "supabase functions deploy <function-name>"
      },
      {
        "title": "Invoke Function",
        "body": "curl -i -L --request POST 'https://<project>.supabase.co/functions/v1/<function-name>' \\\n  --header 'Authorization: Bearer <anon-key>' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\"name\":\"Functions\"}'"
      },
      {
        "title": "Architecture",
        "body": "┌─────────────────────────────────────────┐\n│           hakke-app (SaaS)              │\n├─────────────────────────────────────────┤\n│  tenants table (multi-tenant)           │\n│  - id, slug, name, plan                 │\n│  - owner_id (FK → auth.users)           │\n│  - subscription_status                  │\n├─────────────────────────────────────────┤\n│  Row Level Security (RLS)               │\n│  - tenant_id = current_tenant()         │\n└─────────────────────────────────────────┘"
      },
      {
        "title": "Tenant Isolation",
        "body": "-- Function to get current tenant\nCREATE OR REPLACE FUNCTION current_tenant_id()\nRETURNS uuid AS $$\nBEGIN\n  RETURN (auth.jwt()->>'tenant_id')::uuid;\nEND;\n$$ LANGUAGE plpgsql SECURITY DEFINER;\n\n-- RLS Policy example\nCREATE POLICY \"Users can only see own tenant data\"\nON appointments\nFOR ALL\nUSING (tenant_id = current_tenant_id());"
      },
      {
        "title": "Subscription Management",
        "body": "-- Check subscription status\nCREATE OR REPLACE FUNCTION has_active_subscription()\nRETURNS boolean AS $$\nDECLARE\n  tenant_record tenants%ROWTYPE;\nBEGIN\n  SELECT * INTO tenant_record\n  FROM tenants\n  WHERE id = current_tenant_id();\n  \n  RETURN tenant_record.subscription_status = 'active';\nEND;\n$$ LANGUAGE plpgsql SECURITY DEFINER;"
      },
      {
        "title": "List Tables",
        "body": "SELECT table_name\nFROM information_schema.tables\nWHERE table_schema = 'public';"
      },
      {
        "title": "Describe Table",
        "body": "SELECT\n  column_name,\n  data_type,\n  is_nullable,\n  column_default\nFROM information_schema.columns\nWHERE table_name = 'users';"
      },
      {
        "title": "Check RLS",
        "body": "SELECT\n  schemaname,\n  tablename,\n  rowsecurity\nFROM pg_tables\nWHERE schemaname = 'public';"
      },
      {
        "title": ".env.local",
        "body": "NEXT_PUBLIC_SUPABASE_URL=https://<project>.supabase.co\nNEXT_PUBLIC_SUPABASE_ANON_KEY=<anon-key>\nSUPABASE_SERVICE_ROLE_KEY=<service-role-key>"
      },
      {
        "title": ".env.example (commit to git)",
        "body": "NEXT_PUBLIC_SUPABASE_URL=\nNEXT_PUBLIC_SUPABASE_ANON_KEY=\nSUPABASE_SERVICE_ROLE_KEY="
      },
      {
        "title": "Server Client (Next.js)",
        "body": "// lib/supabase/server.ts\nimport { createClient } from '@supabase/supabase-js';\nimport { cookies } from 'next/headers';\n\nexport function createServerClient() {\n  const cookieStore = cookies();\n  \n  return createClient(\n    process.env.NEXT_PUBLIC_SUPABASE_URL!,\n    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,\n    {\n      auth: {\n        persistSession: false,\n      },\n    }\n  );\n}"
      },
      {
        "title": "Browser Client (Next.js)",
        "body": "// lib/supabase/client.ts\nimport { createClient } from '@supabase/supabase-js';\n\nexport const supabase = createClient(\n  process.env.NEXT_PUBLIC_SUPABASE_URL!,\n  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!\n);"
      },
      {
        "title": "Connection Issues",
        "body": "# Check if Supabase is accessible\ncurl -I https://<project>.supabase.co/rest/v1/\n\n# Expected: 401 Unauthorized (means API is working, just need auth)"
      },
      {
        "title": "RLS Not Working",
        "body": "-- Check if RLS is enabled\nSELECT tablename, rowsecurity\nFROM pg_tables\nWHERE schemaname = 'public';\n\n-- Check policies\nSELECT\n  schemaname,\n  tablename,\n  policyname,\n  permissive,\n  roles,\n  cmd,\n  qual,\n  with_check\nFROM pg_policies\nWHERE schemaname = 'public';"
      },
      {
        "title": "Auth Issues",
        "body": "# Check if user exists\nsupabase auth list\n\n# Check logs\nsupabase logs auth"
      },
      {
        "title": "Deploy with Vercel",
        "body": "# In hakke-app directory\nvercel\n\n# Add env vars in Vercel Dashboard or CLI\nvercel env add NEXT_PUBLIC_SUPABASE_URL\nvercel env add NEXT_PUBLIC_SUPABASE_ANON_KEY\nvercel env add SUPABASE_SERVICE_ROLE_KEY"
      },
      {
        "title": "Best Practices",
        "body": "PracticeWhyRLS always onSecurity firstService key server-onlyNever expose to clientType generationType-safe queriesMigrations in gitReproducible DBSeparate anon/service keysPrinciple of least privilege"
      },
      {
        "title": "Resources",
        "body": "Docs: https://supabase.com/docs\nDashboard: https://supabase.com/dashboard\nCLI Reference: https://supabase.com/docs/reference/cli\nSQL Editor: Dashboard → SQL Editor\nLogs: Dashboard → Logs\n\nSupabase Hakke v1.1.0 - Production-ready for Hakke Studio"
      }
    ],
    "body": "Supabase for Hakke Studio\n\nSupabase integration específica para proyectos de Hakke Studio.\n\nProyectos Actuales\nProyecto\tSupabase URL\tUso\nhakke-app\thttps://[project].supabase.co\tSaaS multi-tenant\nCLI Installation\n# Supabase CLI (ya instalado)\nsupabase --version\n\n# Si no está instalado\nnpm install -g supabase\n\nAuthentication\nLogin to Supabase\nsupabase login\n\n\nThis opens browser for OAuth login with contacto@hakke.cl.\n\nLink Project\ncd /home/bastianberrios/proyectos/HAKKE/hakke-app\nsupabase link --project-ref <project-id>\n\nDatabase Operations\nGenerate Types\nsupabase gen types typescript --local > lib/supabase/database.types.ts\n\nCreate Migration\nsupabase migration new <migration_name>\n\nApply Migration\nsupabase db push\n\nReset Database (DEV ONLY)\nsupabase db reset\n\nAuth Operations\nGet API Keys\nsupabase status\n\n\nReturns:\n\nanon key - Public key (client-side)\nservice_role key - Secret key (server-side ONLY)\nCreate User (Admin)\n-- In Supabase Dashboard SQL Editor\nINSERT INTO auth.users (email, encrypted_password, email_confirmed_at)\nVALUES (\n  'user@example.com',\n  crypt('password123', gen_salt('bf')),\n  NOW()\n);\n\nRLS (Row Level Security)\nEnable RLS\nALTER TABLE users ENABLE ROW LEVEL SECURITY;\n\nCreate Policy\n-- Users can only see their own data\nCREATE POLICY \"Users can view own data\"\nON users\nFOR SELECT\nUSING (auth.uid() = id);\n\n-- Users can update own data\nCREATE POLICY \"Users can update own data\"\nON users\nFOR UPDATE\nUSING (auth.uid() = id);\n\nStorage Operations\nCreate Bucket\n-- In Supabase Dashboard SQL Editor\nINSERT INTO storage.buckets (id, name, public)\nVALUES ('avatars', 'avatars', false);\n\nStorage Policy\n-- Users can upload to own folder\nCREATE POLICY \"Users can upload avatars\"\nON storage.objects\nFOR INSERT\nWITH CHECK (\n  bucket_id = 'avatars'\n  AND auth.uid()::text = (storage.foldername(name))[1]\n);\n\nEdge Functions\nCreate Function\nsupabase functions new <function-name>\n\nDeploy Function\nsupabase functions deploy <function-name>\n\nInvoke Function\ncurl -i -L --request POST 'https://<project>.supabase.co/functions/v1/<function-name>' \\\n  --header 'Authorization: Bearer <anon-key>' \\\n  --header 'Content-Type: application/json' \\\n  --data '{\"name\":\"Functions\"}'\n\nMulti-Tenant SaaS (hakke-app)\nArchitecture\n┌─────────────────────────────────────────┐\n│           hakke-app (SaaS)              │\n├─────────────────────────────────────────┤\n│  tenants table (multi-tenant)           │\n│  - id, slug, name, plan                 │\n│  - owner_id (FK → auth.users)           │\n│  - subscription_status                  │\n├─────────────────────────────────────────┤\n│  Row Level Security (RLS)               │\n│  - tenant_id = current_tenant()         │\n└─────────────────────────────────────────┘\n\nTenant Isolation\n-- Function to get current tenant\nCREATE OR REPLACE FUNCTION current_tenant_id()\nRETURNS uuid AS $$\nBEGIN\n  RETURN (auth.jwt()->>'tenant_id')::uuid;\nEND;\n$$ LANGUAGE plpgsql SECURITY DEFINER;\n\n-- RLS Policy example\nCREATE POLICY \"Users can only see own tenant data\"\nON appointments\nFOR ALL\nUSING (tenant_id = current_tenant_id());\n\nSubscription Management\n-- Check subscription status\nCREATE OR REPLACE FUNCTION has_active_subscription()\nRETURNS boolean AS $$\nDECLARE\n  tenant_record tenants%ROWTYPE;\nBEGIN\n  SELECT * INTO tenant_record\n  FROM tenants\n  WHERE id = current_tenant_id();\n  \n  RETURN tenant_record.subscription_status = 'active';\nEND;\n$$ LANGUAGE plpgsql SECURITY DEFINER;\n\nCommon Queries\nList Tables\nSELECT table_name\nFROM information_schema.tables\nWHERE table_schema = 'public';\n\nDescribe Table\nSELECT\n  column_name,\n  data_type,\n  is_nullable,\n  column_default\nFROM information_schema.columns\nWHERE table_name = 'users';\n\nCheck RLS\nSELECT\n  schemaname,\n  tablename,\n  rowsecurity\nFROM pg_tables\nWHERE schemaname = 'public';\n\nEnvironment Variables\n.env.local\nNEXT_PUBLIC_SUPABASE_URL=https://<project>.supabase.co\nNEXT_PUBLIC_SUPABASE_ANON_KEY=<anon-key>\nSUPABASE_SERVICE_ROLE_KEY=<service-role-key>\n\n.env.example (commit to git)\nNEXT_PUBLIC_SUPABASE_URL=\nNEXT_PUBLIC_SUPABASE_ANON_KEY=\nSUPABASE_SERVICE_ROLE_KEY=\n\nClient Setup\nServer Client (Next.js)\n// lib/supabase/server.ts\nimport { createClient } from '@supabase/supabase-js';\nimport { cookies } from 'next/headers';\n\nexport function createServerClient() {\n  const cookieStore = cookies();\n  \n  return createClient(\n    process.env.NEXT_PUBLIC_SUPABASE_URL!,\n    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,\n    {\n      auth: {\n        persistSession: false,\n      },\n    }\n  );\n}\n\nBrowser Client (Next.js)\n// lib/supabase/client.ts\nimport { createClient } from '@supabase/supabase-js';\n\nexport const supabase = createClient(\n  process.env.NEXT_PUBLIC_SUPABASE_URL!,\n  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!\n);\n\nTroubleshooting\nConnection Issues\n# Check if Supabase is accessible\ncurl -I https://<project>.supabase.co/rest/v1/\n\n# Expected: 401 Unauthorized (means API is working, just need auth)\n\nRLS Not Working\n-- Check if RLS is enabled\nSELECT tablename, rowsecurity\nFROM pg_tables\nWHERE schemaname = 'public';\n\n-- Check policies\nSELECT\n  schemaname,\n  tablename,\n  policyname,\n  permissive,\n  roles,\n  cmd,\n  qual,\n  with_check\nFROM pg_policies\nWHERE schemaname = 'public';\n\nAuth Issues\n# Check if user exists\nsupabase auth list\n\n# Check logs\nsupabase logs auth\n\nIntegration with Vercel\nDeploy with Vercel\n# In hakke-app directory\nvercel\n\n# Add env vars in Vercel Dashboard or CLI\nvercel env add NEXT_PUBLIC_SUPABASE_URL\nvercel env add NEXT_PUBLIC_SUPABASE_ANON_KEY\nvercel env add SUPABASE_SERVICE_ROLE_KEY\n\nBest Practices\nPractice\tWhy\nRLS always on\tSecurity first\nService key server-only\tNever expose to client\nType generation\tType-safe queries\nMigrations in git\tReproducible DB\nSeparate anon/service keys\tPrinciple of least privilege\nResources\nDocs: https://supabase.com/docs\nDashboard: https://supabase.com/dashboard\nCLI Reference: https://supabase.com/docs/reference/cli\nSQL Editor: Dashboard → SQL Editor\nLogs: Dashboard → Logs\n\nSupabase Hakke v1.1.0 - Production-ready for Hakke Studio"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/studio-hakke/supabase-hakke",
    "publisherUrl": "https://clawhub.ai/studio-hakke/supabase-hakke",
    "owner": "studio-hakke",
    "version": "1.1.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/supabase-hakke",
    "downloadUrl": "https://openagent3.xyz/downloads/supabase-hakke",
    "agentUrl": "https://openagent3.xyz/skills/supabase-hakke/agent",
    "manifestUrl": "https://openagent3.xyz/skills/supabase-hakke/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/supabase-hakke/agent.md"
  }
}