尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗House brand + operator console for a modular family of small-business tools
("kits") for Singapore micro/small sellers. qkit (queue/orders), loopkit
(stamp-card loyalty), paykit (payments), and stockkit (inventory) are
live; shopkit and reachkit are upcoming (see src/lib/kits.ts).
This app is the public brand landing plus a role-gated operator console:
/dashboard — cross-product metrics overview (post-login home)/admin/vendors — grant/revoke kit access per vendor/admin/team — manage Merqo-team members/admin/products — per-kit health from the metrics API/admin/feedback — vendor NPS + comments per kit/admin/activity — the admin-audit trail (every real mutating admin action)/about — public "Why Merqo" page: the qkit origin story and a
founder/business-name line matching /legal/terms's phrasingEach kit runs its own app on its own schema in a shared Supabase project.
Merqo pulls per-kit metrics over an HTTP API (bearer secret) — it never
queries another kit's schema directly. Brand theme is "Harbour Control"
(harbour-navy primary, buoy-amber accent) as of 2026-08-19, replacing
"Control Room" (pine-green + marigold-gold) — see globals.css's own
header comment. src/lib/brand-icon.tsx's ImageResponse-generated
favicon/apple-touch-icon carries the same rebrand. Dark mode moved from a
pure OS-media-query to a .dark-class-based approach (@custom-variant dark), driven by next-themes' ThemeProvider wrapping the root layout,
so @merqo/ui's AccountMenu (v0.18.0, collapsed into a "Theme · {current}"
submenu as of v0.19.0) now exposes a manual Light/Dark/
System control on top of the existing OS-auto behavior. In production, every kit's auth
cookie is scoped to .merqo.io (NEXT_PUBLIC_AUTH_COOKIE_DOMAIN,
src/lib/supabase/), so signing in on one kit signs you in on the rest —
unset in dev/preview, where each kit still runs on its own *.vercel.app
host. Kit links (src/lib/kits.ts) default to each kit's
https://<kit>.merqo.io host; NEXT_PUBLIC_<KIT>_URL overrides one. The dashboard's onboarding tour (src/components/dashboard-tour.tsx)
stamps its "seen" state as soon as it auto-runs rather than when it
finishes, so a refresh mid-tour can't make it re-trigger on the next load —
and since that client-fired stamp is fire-and-forget and can be aborted by
a hard navigation (the tour's own steps spotlight @merqo/ui's
AccountMenu trigger, whose dropdown renders links as plain <a> tags),
/dashboard's own server render (src/app/dashboard/(app)/layout.tsx)
also stamps it synchronously, durably, as part of the request. The tour's
"your kits" step now spotlights the active-kit grid (data-tour="kit-cards")
with an inline example kit-card preview in its description, the same
example-card treatment every other Merqo kit's own onboarding tour carries
on its first step — that preview's plan-tier pill renders the real Badge
component instead of a hand-copied color, so it can't drift from what the
badge actually looks like — see
../docs/superpowers/specs/2026-08-25-tour-example-badge-drift-fix-design.md
(workspace root, cross-kit spec). The landing footer matches qkit's exactly
(single-row wordmark/tagline/credit-line/sign-in link, no CTA band above it).
Merqo uses @merqo/ui, the shared component package for the kit family (see
qkit/loopkit/paykit/stockkit for the same dependency). /about's own story
is now @merqo/ui's shared
AboutMerqo component (v0.25.0), the same content every kit's own
/about page renders. LegalDocument (every /legal/* page) gained a
"← Back" button in the same release. As of v0.24.0, TermsAcceptanceCheckbox no longer
collects a typed legal name — just the agree checkbox — since a plain
ToS/Privacy clickwrap doesn't need a signatory name for evidentiary
strength beyond the existing acceptance record (see /legal/accept's
own README). useAsyncAction, InfoTooltip, Section,
TwoColumnSections, ImageUploader, and DashboardTour are used directly
or through a thin per-app adapter (src/hooks/use-async-action.ts,
src/lib/image-upload-adapter.ts, src/components/dashboard-tour.tsx).
dashboard-nav.tsx composes @merqo/ui's DashboardNav for both the
vendor dashboard and admin-console headers (burger, inline links, account
menu, kit switcher on the dashboard), and both layouts end with the landing
Footer without its sign-in link. The profile and vendor-detail pages use
BackButton. The profile page composes shared Section, TwoColumnSections, ImageUploader and SocialLinksFields in route-local sections. Each section owns its save state and retains its distinct server-action or Supabase Auth contract.
@merqo/ui's AccountMenu hardcodes its Profile link to
/dashboard/profile; src/app/dashboard/profile/page.tsx redirects that
to Merqo's real, persona-shared /profile route. The landing nav
(src/components/landing/nav.tsx) is built on @merqo/ui's LandingNav
shell (wordmark/end slots), added in v0.9.0. v0.10.0 added an optional
LinkComponent prop to AccountMenu/DashboardNav so Next.js consumers can
opt their internal nav links out of a plain <a>'s full page reload;
dashboard-nav.tsx passes LinkComponent={Link} (next/link).
@merqo/ui bumped to v0.32.0 (2026-09-22), for currency. It adds
ImageUploader's deferUpload mode (upload on save instead of on pick);
this app doesn't need it, because its only uploader is the profile icon,
which saves the moment an image is picked.
@merqo/ui bumped to v0.31.4 (2026-09-22), for its new
storagePathFromPublicUrl. Replacing or removing a profile icon now deletes the
old image from storage (removeReplacedAvatar in
src/lib/image-upload-adapter.ts); before this, every avatar change orphaned one
file, because ImageUploader names each upload randomly.
@merqo/ui bumped to v0.31.3 (2026-09-22), which also stops resizeToWebp
mislabelling a PNG as WebP on browsers that cannot encode WebP; the public
vendor-avatars bucket now enforces 5 MB and JPEG/PNG/WebP itself (migration
0030). Before that, v0.31.2 (2026-09-19), from v0.29.3. v0.31.0 replaced
the package-wide "use client" banner with per-module directives, so a
plain-data export is a real value inside a Server Component rather than an
opaque client-reference stub — the root cause of the 2026-09-18 RSC crashes
across the kits. It also promoted four modules merqo had its own copy of:
safeRedirectPath, resizeToWebp, BackToTop and GoogleMark. The
landing Footer is now a thin adapter over the shared one, passing
copyright and signInLabel overrides so the hub keeps saying
the current-year Merqo copyright and "Sign in →" rather than a kit's "a Merqo kit" /
"Vendor sign in →"; rendered output is unchanged. v0.31.1 fixes a latent
resizeToWebp bug where a dotless filename yielded the whole name as its
extension. Which repo uses which shared export is tracked in
../merqo-ui/docs/usage-matrix.md.
Next.js 16 · App Router · Turbopack · TypeScript strict · Tailwind v4 ·
shadcn/ui (new-york) · Zod · Supabase (@supabase/ssr) · Vitest ·
Playwright · pnpm 11 · Node ≥24 · deploy target: Vercel
pnpm dev # dev server — http://localhost:3000
pnpm build # production build
pnpm test # run test suite (vitest)
pnpm test:e2e # playwright public smoke
pnpm check # prettier --check + eslint + tsc --noEmit
pnpm format # prettier --write
pnpm check:legal-versions # compare actual legal versions at each product's locked UI commit
pnpm-workspace.yaml's overrides block pins transitive deps (postcss,
nanoid, undici, fast-uri, js-yaml, brace-expansion, sharp) past known CVE
thresholds — pnpm audit --prod --audit-level=high (CI's security.yml
audit job) hard-gates on these. When a new advisory lands on a transitive
dep, bump its floor here rather than waiting on the upstream package to
update; a floor set too low silently stops helping once a newer vulnerable
release ships within the allowed range.
src/app/ — app router (landing, dashboard, admin console, server actions)
src/app/page.tsx — public brand landing with session-aware CTAs
src/app/dashboard/ — vendor dashboard: (app)/ (overview + kit discovery,
open to every signed-in user)
src/app/admin/ — Merqo-team console: overview (page.tsx) + vendors/, team/,
products/, feedback/, activity/ (all auth-gated)
src/app/profile/ — shared account page (signed-in gate only — reachable from
both the vendor dashboard and the admin console)
src/app/login/ — email/password sign-in
src/app/api/telegram/webhook/ — merqo's own Telegram bot's webhook (customer connect)
src/app/api/merqo/ — bearer-secret endpoints qkit/loopkit call INTO merqo
src/proxy.ts — Supabase session refresh + route guard (Next 16)
src/components/landing/ — landing sections (nav, hero, kit-stacker, …)
src/components/dashboard/ — dashboard widgets (stat cards, kit discovery/preview cards)
src/components/brand/ — shared Merqo wordmark
src/hooks/use-async-action.ts — shared pending/error state for server-action buttons
src/lib/kits.ts — kit family config (landing roadmap source of truth)
src/lib/metrics-client.ts — fetch of a kit's HTTP metrics endpoint
src/lib/vendor-activity-client.ts — fetch of a single vendor's per-kit triage status/metrics
(admin/vendors/[email]'s Activity cards)
src/lib/schemas.ts — Zod schemas for the profile page's forms
src/lib/merqo-vendor-profile.ts — typed wrapper over the shared vendor_profile RPCs
src/lib/supabase/ — browser / server (schema=merqo) / service-role clients
supabase/migrations/ — SQL schema (merqo.* tables) + RLS + grants
supabase/seed/staging-registry.sql: one-time staging registry wiring (docs/STAGING.md)
scripts/staging-migrate.sh: applies migrations to the staging project with psql
scripts/check-legal-version-skew.mjs — asserts merqo + all 5 kit repos pin
matching terms/privacy/pilot versions from exact locked UI commits
One shared Supabase project, schema per kit. Merqo owns merqo.*:
merqo_team (team membership), products (kit registry + per-product
metrics_secret), vendor_links (vendor↔kit access, email-keyed),
billing_settings (cross-kit pricing levers — currently just the
bundle-discount toggle, public-read, service-role-only write),
customers (cross-kit customer identity — phone-keyed OR Telegram-chat-keyed
per vendor since the 2026-08-16 widening, the shared counterpart to
vendor_profile, reachable only through upsert_customer and three
Telegram-identity SECURITY DEFINER functions, called by qkit/loopkit),
telegram_link_tokens (short-lived deep-link tokens for merqo's own
customer-facing Telegram bot, service-role only), admin_audit (every real
mutating admin action — kit-access grant/revoke, team add/remove, the
bundle-discount toggle, support-message resolution — recorded via
recordAudit(); immutable at the grant level, no update/delete grant
to any role; surfaced on /admin/activity). Merqo also hosts that
bot's webhook plus two bearer-secret endpoints qkit/loopkit call into —
the first kit → merqo HTTP direction in this codebase (see
docs/superpowers/specs/2026-08-16-customer-telegram-connect-design.md).
RLS defaults to deny. Vendors can read their own vendor_links; registry
secrets and administrative writes use server-only service clients, so
metrics_secret never reaches a browser.
CHANGELOG.md (includes the new admin-audit trail, plus a fix
restoring card/background contrast in both modes after the Harbour
Control rebrand had accidentally collapsed them to the same color and a
follow-up dark-mode brightness bump, a fix routing every signed-in
landing CTA through /post-login instead of straight to /admin,
founder Telegram alerts on any kit's help/feedback submission, a
fix to that alert's own setup runbook (it was missing the step where
you message the bot first), and security bumps of next to 16.3.4,
browserslist to 4.28.9, and vitest to 4.1.11, and a vitest.config.ts
testTimeout bump from 10s to 30s fixing a real test-isolation leak where a
timed-out test skipped its cleanup and bled a stale render into the next test)docs/DEPLOY.mddocs/STAGING.md. .gitattributes
keeps *.sh on LF line endings so the staging script runs in a Linux
container from a Windows checkout.docs/superpowers/.claude/README.mdSee AGENTS.md for full engineering rules, harness details, and skills.
Vendor grants, product options, team memberships and open support messages read all API pages in stable order. Incomplete reads fail rather than showing partial administrative data. Email resolution queries only referenced auth user IDs in batches of eight; adding a team member by email retains full directory pagination. Recent audit entries remain intentionally limited by the requested history size. These offset-based lists are operational views, not transactionally consistent accounting snapshots.
The legal rollout check reads each product's lockfile and uses the sibling
merqo-ui Git checkout to inspect its exact committed legal constants. Fetch
any missing locked commit before running the check. Different UI releases are
allowed when the legal document versions match. Git uses its standard installed
path (Windows: C:/Program Files/Git/cmd/git.exe; Unix: /usr/bin/git).
The shared UI dependency is pinned to immutable commit 7b386558af36a1cbf008a9b4c4073c07ffc105ba, tagged v0.34.2, carrying the reviewed upload lifecycle, storage URL validation and safe money parsing fixes. Since v0.32.1, Section title tooltips and default-mode InfoTooltips open on a tap as well as on hover and keyboard focus. Since v0.32.2 every info icon also takes taps through a 44px touch area on touch devices. Since v0.32.3 a long tooltip wraps inside the viewport. Since v0.34.2 a server action that ends in redirect() counts as navigation, not an error. pnpm 11.10 permits preparation only for that exact locked source URL; update the dependency and its build allowlist together.
The AI harness follows templateCentral 6.0.4: hook commands are anchored on the project directory, and the guard against committing to main reads the branch of the directory a command runs in. The dated entry in AGENTS.md lists what was adopted.
src/proxy.ts sets the CSP (nonce on per-request routes) and X-Robots-Tag on non-production deployments. The operator console requires TOTP MFA; see src/app/mfa/README.md and docs/security/.
eslint.config.mjs consumes the shared @merqo/ui/eslint preset (comment and directive hygiene, size and complexity limits, no colour literals or em dashes in src). eslint.config.test.ts asserts the key rules stay at error. Colour literals are allowed only in src/lib/brand-icon.tsx and src/app/global-error.tsx.