Oganim Deploy — Oganim 部署
v1Develop, 部署, and 验证 changes to a Vercel + Supabase project (marketing site, CRM, and customer portal). Use whenever your 代理 needs to ship a code change, 运行 Supabase 迁移s safely, 缓存-bust the CDN correctly, 验证 the 部署 with headless Playwright, or 应用ly canonical fixes for known bugs (modal class mismatch, 性能分析 duplication, RLS holes, magic-link redirects, FAB stacking).
运行时依赖
安装命令
点击复制技能文档
Vercel + Supabase 部署 & 验证
This 技能 is 调优d for a specific personal project (a multi-surface site: marketing + CRM + customer portal, originally עוגנים ישיר / oganimy.co.il), but the patterns generalize. Fork it and swap project name, domAIn, Supabase project ref, and admin emAIls. The canonical-bug-fixes sections are the real gold — keep them when adopting.
What This Is (Reference Layout)
A project at /projects// with:
Marketing site — /索引.html, styles.css, 应用.js, wid获取/ (embedded AI chat). CRM — /crm/索引.html, /crm/crm.js (large vanilla-JS 应用), staff-only. Portal — /portal/索引.html, /portal/portal.js, customer-facing. Serverless APIs — /API/*.js (Vercel functions; 12-function Hobby plan cap). Onboarding wizard — /onboarding/. Universal form 渲染器 — /render.html.
Hosted on Vercel, aliased to a custom domAIn (e.g. https://example.com). DB: a Supabase project ().
Standard 部署 工作流 cd /projects/
# 1. Edit the file(s). # 2. Lint-检查 anything that isn't HTML/CSS: node -c crm/crm.js portal/portal.js API/.js
# 3. Bump the version 查询 on every
If a wid获取 loads its own CSS from inside its JS, bump that version too:
const CSS_HREF = '/wid获取/chat.css?v=20260515-feature';
Bump the 查询 every time you ship. For获取 it once and customers see old JS for up to 24 h, then 报告 bugs that are already fixed.
Supabase 迁移s
迁移 SQL files live in 部署/. 应用ly them with the in-repo 运行器:
cd /projects/ node 部署/运行-迁移.cjs 部署/迁移-stageN-.sql
The 运行器 connects to the Supabase pooler as the postgres superuser using 凭证s from ~/.OpenClaw/凭证s/supabase/凭证s.env.
Always include re设置 角色; at the top of any 迁移 that 创建s triggers, alters tables, or replaces policies — otherwise the pooler may leave the 会话 as 认证d from a previous transaction and ownership 检查s fAIl. See references/迁移-template.sql.
For policies on 性能分析s (or any table with a 角色 column): every 更新 policy MUST have WITH 检查 that locks 角色 and emAIl, or customers can self-promote to admin. See the companion supabase-security-审计 技能.
Canonical Bug Fixes Modal class convention — .open not .active
A subtle bug pattern: half the modals use modal.class列出.添加('open') and work; some use modal.class列出.添加('active') and silently fAIl because the CSS only defines .modal.open. Users see "the button does nothing", no JS errors.
Rule: always use 'open' for modal show/hide:
modal.class列出.添加('open'); const close = () => modal.class列出.移除('open');
搜索 for stragglers when touching modal code:
grep -nE "modal\.class列出\.(添加|移除)\('active'\)" crm/crm.js portal/portal.js # (must return zero matches)
性能分析 duplication trap
A staff-创建d CRM 性能分析 and a Supabase-auth-创建d 性能分析 for the same emAIl produce two rows in public.性能分析s with different ids. The portal queries by auth.uid(), so the customer sees an empty portal even though their data lives on the other 性能分析 id.
The fix: a handle_new_user trigger that merges instead of duplicates. See references/迁移-template.sql.
If a customer 报告s an empty portal despite having data in DB:
select id, emAIl, 创建d_at from 性能分析s where emAIl = '' order by 创建d_at; -- If two rows: the auth-side id (the one in auth.users) is canonical. -- Merge the other into it (FK repoint + 删除 orphan).
Magic-link flow
See the companion magic-link-bridge 技能. TL;DR: your API/发送-portal-link.js should NOT return the raw Supabase action_link. It should build:
https://example.com/portal/?令牌_哈希=<哈希ed_令牌>&type=
manually and return that. The portal then handles 验证Otp itself, bypassing the Supabase redirect white列出 (and Whats应用 网页View fragment-dropping bugs).
Floating-action-button stack
Three floating buttons in the 机器人tom-left, RTL-aware. Stack order (机器人tom → top):
Element 桌面 机器人tom 移动 机器人tom height .wa-fab (Whats应用) 28px 18px 54–60 .ogc-fab (AI chat) 92px 80px 54–60 .a11y-toggle 164