KATURA
Your browser is not supported. Please update your iPad to the latest iOS version, or visit us on a newer device.
How to update your iPad Skip to main content JOIN THE WORLD OF KATURA Be the first to discover new collections, exclusive events, and the stories behind our legendary creations.
KaturaβCrafting timeless treasures since 1999.
The technology behind Katura is built in-house. K99 is our jewelry business platform β available to other jewelers.
Β© 2026 KATURA. All rights reserved.
πΊπΈ English EN πΊπΈ United States $
Software Updates Β· KATURA | KATURA
Live from GitHub Β· Refreshed continuously
Software Updates Every change we ship to katura1999.com β features, fixes, security patches, the lot. Pulled straight from our private GitHub repository so you can see exactly what was built and when.
By the numbers Lines of code
850,259
Web platform β TypeScript, React, Prisma, CSS
iOS
79,607
Swift + SwiftUI lines
Android
3,117
Kotlin + Jetpack Compose lines
All platforms
932,983
Web + iOS + Android combined (45.8Γ the King James Bible)
Characters written
36.05M
36,053,358 total characters
Updates pushed
2,087
exact commit count on main
Current version
v1.20.87
build 2087 Β· 40f34e0
Database models
411
across 47 schema files β most SaaS platforms have 20β50
API endpoints
988
individually routed β Stripe's public API has ~400
Translated strings
82,512
every string, in 24 languages
System permutations
10^297
2^988 endpoint combinations β more than atoms in the observable universe (10^80)
Project age
8mo 1d
since Dec 14, 2025
Pre-AI dev hours
31.1K hrs
932,983 lines Γ· 30 LOC/hr β equivalent to 15.0 years (senior engineer, no AI)
With-AI dev hours
7.8K hrs
4Γ AI productivity multiplier (2024β2026 studies) β equivalent to 972 days
Equivalent firm cost
$8,119,550
live ticker Β· Katura rate: $60 USD/hr
Hours estimated from source line count at 30 LOC/hr (industry benchmark for production-quality TypeScript/React without AI assistance), with a 4Γ multiplier for AI-assisted development per published 2024β2026 enterprise studies. Equivalent Firm Cost uses a $250/hr loaded billable rate reflecting a premium engineering firm building enterprise-grade SaaS β and ticks up live, because the project is still being actively built.
Commit history
2,087 updates pushed Showing page 8 of 40 Β· 351β400 of 2,000 fetched
Saturday, May 16, 2026 30 updates pushed
Feature 11:52 PM Β· ZRosserMcIntosh
wire real Stripe off-session overage charging Add src/lib/saas/overage-billing.ts: chargeOverage(): off-session PaymentIntent against tenant's saved card (idempotency key: overage:{id}:{cents}:{hourBucket}) createOverageInvoice(): for monthly_invoice tenants β creates InvoiceItem, finalizes and sends Invoice ensureTenantStripeCustomer(): upserts Stripe Customer, saves ID back to DB getDefaultPaymentMethod(): checks invoice_settings then falls back to card list Replace overage-charge cron stub with real implementation: Calls chargeOverage() for all eligible auto_recharge tenants Handles success / requires_action / failure outcomes On MAX_CHARGE_FAILURES: moves pendingOverageUsd β unpaidOverageUsd, sets billingStatus=past_due Locks tenant (billingLock=true) when unpaid >= LOCK_THRESHOLD_USD Feature 11:35 PM Β· ZRosserMcIntosh
wire enforcement into all live expensive routes + 25 passing tests enforceEmailSend() called after credit check, before sendBrevoEmail() Returns 402/429/403 with structured error {code, message, decision} Recipient count forwarded so bulk sends are metered correctly enforceMessengerSend() called after membership check, before INSERT IP address forwarded for rate-limit / abuse detection Returns {error, decision} with correct HTTP status enforceLiveKitJoin() called before ensureRoom() + createParticipantToken() If livekit kill switch is active, room is never created enforceLiveKitJoin() called before createParticipantToken() Covers both start and join actions enforceLiveKitJoin() called after invite validation, before token issuance Even unauthenticated guests are metered against TENANT_ZERO_ID Kill switch on livekit blocks guest joins immediately enforceLiveKitJoin() called before createParticipantToken() Public endpoint β metered against TENANT_ZERO_ID enforceDataImport() called at job creation time (not processing time) Estimated row count from config.totalRows / config.rowCount Throws 'Import blocked: ...' to surface to the API caller Feature 11:28 PM Β· ZRosserMcIntosh
wire usage gateway integration, add cron jobs, comprehensive docs src/lib/saas/usage-hooks.ts: Higher-level enforcement hooks with UsageBlockedError enforceLLMUsageBefore/After, enforceEmailSend, enforceMessengerSend enforceLiveKitJoin, enforceWebhookDelivery, enforceDataImport enforceSTT, enforceTTS (Deepgram speech services) UsageBlockedError class with HTTP status code mapping src/lib/saas/metered-llm.ts: Drop-in metered LLM adapter wrappers callLLMMetered, callLLMWithFailoverMetered streamLLMMetered, streamLLMWithFailoverMetered Pre-flight enforcement β provider call β post-flight recording /api/cron/usage-rollup: Hourly/daily/monthly event aggregation Upsert-based (idempotent, safe to re-run) Auto-cleans hourly rollups older than 90 days Schedule: every hour at :05 /api/cron/billing-period-reset: Monthly billing cycle management Resets aiCurrentSpendUsd/infraCurrentSpendUsd to 0 Escalates pending β unpaid overages Locks tenants with > unpaid overage Schedule: midnight on 1st of month /api/cron/overage-charge: Auto-recharge processing Finds tenants with pending overage above threshold Attempts Stripe charge (placeholder until Connect wired) Locks tenant after 3 consecutive failures Schedule: every 2 hours Added usage-rollup, billing-period-reset, overage-charge schedules docs/saas-build/METERING-BILLING-ENFORCEMENT.md: 500+ line comprehensive build log Architecture diagrams, all 7 tables documented Complete rate card with verified May 2026 pricing Markup & margin strategy with examples 5 spend modes explained 14 kill switches listed All 6 admin pages described Wiring guide for every integration point Operational playbook (outage, abuse, billing, pricing updates) Feature 11:18 PM Β· ZRosserMcIntosh
complete metering, billing enforcement & rate limiting infrastructure SaasUsageEvent: immutable event ledger for all billable/abusable actions SaasUsageRollup: hourly/daily/monthly aggregates for dashboards & billing SaasProviderRateCard: unified provider pricing table (never hardcode prices) SaasTenantLimitPolicy: per-plan & per-tenant limits with enforcement levels SaasTenantBillingControl: spend modes, AI/infra caps, overage tracking, feature locks SaasRateLimitViolation: rate limit violation audit log SaasPlatformSwitch: emergency kill switches (disable_openai, disable_livekit, etc.) src/lib/saas/usage-gateway.ts: central enforcement gateway enforceAndRecordUsage() β single choke-point for all expensive actions Pipeline: raw_usage β provider_cost β billable_cost β quota_check β decision Returns: ALLOW | ALLOW_WITH_WARNING | THROTTLE | REQUIRE_PAYMENT | BLOCK_* Convenience wrappers: enforceAI, enforceEmail, enforceMessenger, enforceLiveKit, etc. Kill switch checks, feature locks, rate limits, quota limits, spend tracking /admin/saas/usage/metering: global metering dashboard (by provider, feature, tenant) /admin/saas/usage/rate-limits: rate limit config, kill switches, violation monitoring /admin/saas/usage/rate-card: provider pricing table with markup & margin visibility /admin/saas/billing/overages: pending/charged/failed overages, threshold warnings /admin/saas/security/abuse: violation detection, suspicious tenants, IP abuse, AI anomalies /admin/saas/tenants/[id]/limits: per-tenant limits, overrides, feature locks, current usage OpenAI: GPT-5.5 (/ per 1M tok), GPT-5.4 (.50/), GPT-5.4m (/bin/zsh.75/.50) Realtime (/ per 1M audio tok), Translate (/bin/zsh.034/min), Whisper (/bin/zsh.017/min) Web Search (/1k calls), Image-2 (/ per 1M tok) Anthropic: Opus 4.7 (/ MTok), Sonnet 4.6 (/), Haiku 4.5 (/) Cache writes (1.25x), cache reads (0.1x), web search (/1k) xAI: Grok 4.3 & 4.20 (.25/.50 per 1M tok) Deepgram: Nova-3 STT (/bin/zsh.0058/min stream), Aura-2 TTS (/bin/zsh.030/1k chars) Voice Agent (/bin/zsh.075/min), add-ons (redaction/diarization /bin/zsh.002/min) LiveKit: WebRTC (/bin/zsh.0005/min Ship), Agent (/bin/zsh.01/min), Recording (/bin/zsh.005/min) Data transfer (/bin/zsh.12/GB Ship), SIP (/bin/zsh.004/min) Update 10:48 PM Β· ZRosserMcIntosh
resolve TS errors across 6 SaaS admin pages contracts/page.tsx: replace non-existent prisma.saasSubscription with saasTenant query entitlements/page.tsx: fix plan query (monthlyPrice, _count.tenants), fix brace alignment data-quality/page.tsx: replace customDomain with domains relation, stripeAccountId β stripeConnectAccountId, fix images relation query blueprints/page.tsx: subscriptions β tenants count, price β monthlyPrice ordering tenants/[id]/config-snapshots/page.tsx: replace subscription/featureFlags with plan/enabledFeatures/domains, fix unknown type in JSX tenants/segments/page.tsx: replace subscription relation with direct plan relation Feature saas 10:32 PM Β· ZRosserMcIntosh
Shopify-level operator control plane β Phases 1-6 + Virgil additions SaasAuditEvent β universal audit log for all staff actions SaasFailedPayment β cached Stripe payment failures with retry tracking SaasDispute β Stripe chargebacks with evidence deadline tracking SaasOnboardingChecklist β per-tenant activation checklist (9 steps) SaasTenantNote β internal staff-only notes (categorized, pinnable) SaasTenantRiskFlag β risk/trust flags (VIP, fraud, abuse, strategic) Command Center, System Health, Incidents, Activity Feed, Dashboard updates Tenant 360 (tabbed: Overview/Billing/Domains/Usage/Support/Integrations/ Audit/Notes/Risk), Health Scores, Lifecycle Funnel, Segments, At Risk, Revenue Rescue, Config Snapshots, Impersonate button w/ reason modal Failed Payments war room, Disputes/Chargebacks, Credits/Coupons scaffold Feature Flags, Entitlements Engine, Contracts Registry, Runbooks, Blueprints, Translations, AI Credits & Spend Webhook Deliveries forensics, OAuth Connections, Vendor Status Failed Records, Migration Packages, Data Imports Escalations, SLA Monitor, B2B Messenger Platform Users, Roles & Permissions, Login Activity, Audit Logs, Data Export/Deletion Requests Background Jobs, Queues, Cron Jobs, Email Deliverability, Error Logs, Deployments, Database Marketing Engagements, Service Invoices, Engineering/Design Churn, Trial Conversion, Feature Adoption, Expansion, Benchmarks, Data Quality Score, Sandbox Mode Broadcast center with segment targeting (MVP read-only) Server components with direct Prisma reads (try/catch β empty arrays) Client-side interactivity in *-client.tsx siblings Shared operator primitives: OperatorPageHeader, OperatorMetric, EmptyOperatorPanel All writes through operator-actions.ts (role check + audit log) Webhook handler enhanced for invoice.payment_failed + charge.dispute.* docs/active/SAAS_BACKEND_SHOPIFY_LEVEL.md β full plan with checkboxes 9:44 PM Β· ZRosserMcIntosh
gitignore logs/, tmp/, .vercel-rebuild, tsconfig artifacts 9:31 PM Β· ZRosserMcIntosh
Parity infrastructure: /api/mobile/features endpoint, parity audit script Refactor 9:21 PM Β· ZRosserMcIntosh
extract MessageThread from Messenger.tsx β final split complete New file: src/components/admin/messenger/MessageThread.tsx (~966 lines) Owns all local compose state: newMessage, isSending, translateMode, translateTargetLang, showTranslatePopover, isRecording, recordingDuration, isUploadingVoice, mentionQuery, mentionIndex, isSummarizing, summaryText, savedReplies, showSavedReplies, savedRepliesLoaded Owns local refs: messagesEndRef, inputRef, fileInputRef, mediaRecorderRef, audioChunksRef, recordingTimerRef Owns all compose handlers: handleSendMessage, handleInputChange, handleInputKeyDown, insertMention, getUserHandle, mentionCandidates Owns voice/file/summarize/savedReply handlers Moves two effects from Messenger.tsx: translateMode restore, scroll-to-bottom Reads shared state via useMessenger() (no props) Messenger.tsx: 2410 lines (original) β 633 lines (74% reduction) Pure state/effects/context-provider orchestrator Removed ~950 lines of compose + thread JSX/state/functions Removed unused imports: 20+ lucide icons, Avatar, Input, ScrollArea, DropdownMenu*, Badge, ScheduleMeetingDialog, MessageBubble, getBubbleColor, getInitials, MessageMetadata Refactor 9:03 PM Β· ZRosserMcIntosh
extract ChannelList from Messenger.tsx New file: src/components/admin/messenger/ChannelList.tsx No props β reads everything via useMessenger() context hook Renders: search bar, New Message button, Direct Messages section, Channels (group) section, empty state fallbacks Uses ChannelItem for each row (entrance stagger via delayMs) Messenger.tsx: replaced ~85-line inline sidebar with <ChannelList /> Messenger.tsx: removed unused imports Search, ChannelItem Messenger.tsx: ~1678 β ~1593 lines Refactor 9:01 PM Β· ZRosserMcIntosh
add MessengerContext β shared state layer for ChannelList + MessageThread New file: src/components/admin/messenger/MessengerContext.tsx Defines MessengerContextValue interface (channels, messages, users, currentUser, typing state, call state, notifications, refs, layout props) Exports MessengerContext (createContext) and useMessenger() hook useMessenger() throws if called outside a provider (fail-fast) Messenger.tsx: imports MessengerContext + MessengerContextValue Builds typed contextValue object from all existing state/refs/handlers Wraps return JSX in <MessengerContext.Provider value={contextValue}> Zero behaviour changes β all state stays in Messenger.tsx as before Enables ChannelList.tsx and MessageThread.tsx to be extracted next Refactor 8:57 PM Β· ZRosserMcIntosh
extract ChannelItem from Messenger.tsx New file: src/components/admin/messenger/ChannelItem.tsx Props: channel, isSelected, currentUserId, locale, onClick, delayMs Handles DM avatar vs group/hash icon rendering Carries entrance-animation stagger (animationDelay via delayMs prop) Exports ChannelItem + ChannelItemProps Messenger.tsx: removed inline ChannelItem function (~73 lines) Messenger.tsx: removed now-unused Users icon import Messenger.tsx: 1718 β 1645 lines Refactor 8:55 PM Β· ZRosserMcIntosh
extract NewChannelDialog from Messenger.tsx New file: src/components/admin/messenger/NewChannelDialog.tsx Self-contained state (channelType, channelName, selectedMembers, memberSearch, isCreating) Props: open, onOpenChange, users, currentUserId, locale, onCreated isCreating guard prevents double-submit Calls onCreated(channel) after successful API response Messenger.tsx: removed ~170 lines of inline dialog JSX + handleCreateChannel Messenger.tsx: removed 4 state vars (newChannelType, newChannelName, selectedMembers, memberSearch) Messenger.tsx: removed unused imports Dialog/DialogContent/Description/Footer/Header/Title/Checkbox/Label Messenger.tsx: 1942 β 1727 lines Refactor 8:51 PM Β· ZRosserMcIntosh
extract MessageBubble + types + utils from Messenger.tsx User, ChannelMember, Channel, Message, MessageMetadata interfaces Single source of truth for all messenger types tr(), getBubbleColor(), getInitials(), formatMessageDate() buildHandleMap(), renderWithMentions() β pure, tree-shakeable Full MessageBubble component (plain text, meeting card, voice, file) MeetingCard (private sub-component) All translation state (translateBubble, auto-translate, show original toggle) Read receipts, edited marker Imports types from ./messenger/types Imports MessageBubble from ./messenger/MessageBubble Imports utilities from ./messenger/utils Removes ~250 lines of now-redundant code Removes unused imports: ExternalLink, format, isToday, isYesterday, formatDistanceToNow File: 2410 β ~1947 lines (-463 lines) Feature 8:45 PM Β· ZRosserMcIntosh
storage category tabs, server-side channel bootstrap, messenger split foundation Photos / Videos / CAD & 3D / Documents / All tabs above file grid Client-side filter via matchesCategory() β no extra API calls CAD_EXTS set covers obj,stl,step,fbx,glb,gltf,3dm,blend,skp etc. Tab shows file count; section header updates to reflect active category Empty-category state with 'Show all files' link Category resets to 'all' when navigating folders or switching views useMemo'd displayFiles derived from files + category New src/lib/messenger/get-channels.ts β shared function returning the same shape as the channels API route messages/page.tsx converted to async server component β prefetches channels via getChannelsForUser() before first paint messages-client.tsx updated to accept + thread initialChannels prop Messenger.tsx: initialChannels prop seeds channels state immediately; isLoading starts false when data is provided; background refresh still runs for freshness β eliminating the initial channel-list spinner entirely Feature 8:35 PM Β· ZRosserMcIntosh
top-10 animations + messenger typing indicator, read receipts, bubble entrance Typing indicator: Supabase broadcast per channel, auto-clears after 4s, cleared on send Read receipts: 'Seen by Name, Name' instead of bare ββ typingUsers state + typingChannelRef + typingTimeoutRef + isTypingRef mountedAtRef: only animate messages newer than component mount time Update 8:25 PM Β· ZRosserMcIntosh
resolve Turbopack build errors β duplicate products route + missing shared module Delete analytics/(marketing)/products/page.tsx (conflicted with analytics/products/) Create analytics/_components/shared.ts barrel re-exporting from (marketing)/_components/shared Fix analytics/layout.tsx import to resolve via analytics/_components/shared Feature 8:19 PM Β· ZRosserMcIntosh
messenger @yen, summarize, saved replies, stella cleanup, per-user yen limits Messenger: @yen mentions auto-trigger AI reply (GPT-4o-mini) Messenger: β¦ Summarize button β inline thread summary banner Messenger: β‘ Saved Replies in + menu β quick template picker API: POST channels/[id]/yen-reply, POST channels/[id]/summarize API: GET/POST/DELETE /api/admin/messenger/saved-replies Schema: ChatSavedReply model (Prisma + SQL migration) Migration: performance indexes for ChatMessage, ChatChannelMember, YenTokenSpend Phase 4: delete src/app/admin/stella/, add catch-all redirects in next.config.ts Analytics: copy product detail page to analytics/(marketing)/products/[productId] Yen cost-guard: respect yenLimitOverride JSONB per user (unlimited flag + per-window overrides) Usage dashboard: PerUserLimitsPanel to view/edit per-user token limit overrides API: GET/PATCH /api/admin/usage/limits Feature messenger 8:02 PM Β· ZRosserMcIntosh
layout lock, translation mode, voice messages, + attachment menu Globe icon button in channel header opens an inline popover with: Toggle switch (on/off) Language picker: English / Portuguese / Spanish / French When mode is ON, every inbound message auto-translates on render (useEffect in MessageBubble β fires once per message ID per session). Cache-first via existing /api/admin/translate (chat_message entity type). First user to translate a message pays the AI cost; every subsequent user in any channel that shares that messageId gets the cached result instantly. 'Show original (Portuguese)' / 'β English' toggle per bubble. Translation mode preference persisted per channel in localStorage so it survives navigation and page refresh. When mode is off, translate button shows on hover (existing behaviour). handleStartRecording β getUserMedia, MediaRecorder.start(250ms chunks) handleStopRecording(cancel) β stops recorder, sends or discards handleSendVoiceMessage β uploads + sends message with metadata.kind='voice' Recording UI: pulsing red dot, MM:SS timer, cancel (X) and send (β) buttons 'Processingβ¦' spinner while Whisper transcribes Voice MessageBubble: Native <audio controls> player Transcript shown below player in italic (auto-translatable just like text) Duration badge Client-side message cache: messageCacheRef (Map<channelId, {messages, fetchedAt}>) 60s TTL β switching between channels feels instant after first visit. Realtime INSERT handler invalidates cache and triggers a fresh fetch. Avatar AvatarImage given width/height={32} to prevent layout shift. MessageBubble auto-translate useEffect skips temp 'tmp_*' IDs to prevent spurious API calls for optimistic messages. Docs 7:45 PM Β· ZRosserMcIntosh
messenger translation + performance + business tools roadmap (May 16) Update email 7:42 PM Β· ZRosserMcIntosh
signature HTML preserved, on by default, image attachments wired end-to-end Add separate signatureHtml state (never touches the textarea, so HTML tags survive). Add signatureEnabled boolean state (default true β on by default). New useEffect: rebuilds signatureHtml whenever the compose dialog opens or the fromAccountId changes, so the correct per-account signature is always loaded automatically. insertSignature() now toggles signatureEnabled instead of appending raw HTML to the body. Signature rendered as a read-only HTML preview below the textarea with a small β dismiss button; the βοΈ Sig toolbar button shows strikethrough when disabled. At send time, bodyWithSignature = body + signatureHtml (when enabled) is assembled server-side-safe before translation / dispatch, so the full HTML β including the logo <img> β is sent. Fix attachment upload: formData field renamed 'file' β 'files' to match the route's formData.getAll('files'). Fix response parsing: data.attachment β data.attachments?.[0]. Send payload changed from attachmentIds (just IDs) to attachments (full objects with storageUrl / fileName / mimeType / fileSize) so the send route has everything it needs to fetch and encode files. Add attachments field to sendEmailSchema (array of storageUrl / fileName / mimeType / fileSize objects). Before the Brevo call, iterate attachments: download each file from Supabase Storage, base64-encode it, create the EmailAttachment DB record, and push to brevoAttachments[]. Pass brevoAttachments to sendBrevoEmail({ attachment: [...] }) so files actually arrive in the recipient's inbox. Docs 7:15 PM Β· ZRosserMcIntosh
add May 16 session summary with next steps 6:22 PM Β· ZRosserMcIntosh
Phase 3: Promote Storage + CAD to sidebar, move stella/media β /admin/media Moved /admin/stella/media β /admin/media (canonical URL) Moved /admin/stella/media/videos β /admin/media/videos (canonical URL) Fixed internal links: media page links to /admin/media/videos, videos page links back to /admin/media stella/media and stella/media/videos now redirect (server-side components) Added next.config.ts 301 redirects for both stella/media routes Promoted /admin/storage from commandPaletteOnlyItems β Business Tools sidebar (after tasks) Promoted /admin/design (CAD for Antar) from commandPaletteOnlyItems β Business Tools sidebar (after storage) Updated nav.stellaMedia href β /admin/media, nav.stellaVideos href β /admin/media/videos Restored nav.agents to commandPaletteOnlyItems (was lost in edit) Refactor 5:27 PM Β· ZRosserMcIntosh
Phase 2 β move Smart Links + QR Codes to /admin/marketing /admin/marketing/links β moved from stella/marketing/links (standalone, no context dep) /admin/marketing/qr β moved from stella/marketing/qr (standalone) marketing-layout.tsx: added Smart Links + QR Codes to sidebar nav admin-navigation.ts: sidebar entries for smartLinks + qrCodes admin-i18n-provider.tsx: added smartLinks/qrCodes type + EN/PT translations next.config.ts: permanent redirects for old stella URLs 3:01 AM Β· ZRosserMcIntosh
lead time label β add resizing to Atelier Creation Time Update build 1:29 AM Β· ZRosserMcIntosh
unterminated string in consultation page placeholder Escaped single quote inside single-quoted JSX attribute caused Turbopack parse error. Converted to template literal to allow both quote types. Update seo 1:20 AM Β· ZRosserMcIntosh
add missing fb:app_id meta tag for Facebook domain insights Add fb:app_id to root layout and product detail page metadata Configure via NEXT_PUBLIC_FACEBOOK_APP_ID environment variable Required by Meta for proper domain insights and social sharing validation Update .env.example with Facebook App ID configuration Update seo 1:11 AM Β· ZRosserMcIntosh
product OG image β primary photo first, square dimensions for WhatsApp Order product images by isPrimary desc, sortOrder asc so the primary/featured image is always images[0] used for og:image Change OG image dimensions from 1200x630 to 1200x1200 (square) β WhatsApp, iMessage, and most social crawlers prefer square for product photos Feature products 1:08 AM Β· ZRosserMcIntosh
3 product page improvements Fix gap above Edit Product sticky bar (negate main padding with -m classes) Add Duplicate button to product edit form top bar + products list table uses existing POST /api/admin/products/[id]/duplicate route High-value purchase modal (>= $50k): intercepts Add to Bag, shows personal-assistance form (name, email, phone, message) β sends to /api/contact Adds HighValuePurchaseModal component + DuplicateProductButton component Feature meetings 12:53 AM Β· ZRosserMcIntosh
4 meeting upgrades Captions default ON for staff (was off) CAD viewer renders as participant tile in video grid (not floating overlay) tileMode prop added to MeetingCadViewer Updated admin and guest room clients Yen diamond search: search_diamonds tool in yen-chat backend calls Nivoda client directly, returns structured JSON diamond cards rendered in YenChatPanel with Share with client button Yen Intelligence button (Target icon) in control bar auto-opens Yen chat with structured consultation extraction prompt Friday, May 15, 2026 20 updates pushed
Feature 11:44 PM Β· ZRosserMcIntosh
Loupe360 fallback client + NivodaβLoupe360 cascade in diamond intel Diamond intel route now falls back to Loupe360 retail portal Loupe360 uses same credentials (NIVODA_API_USERNAME/PASSWORD) + Webshare proxy Returns v360 3D video share URL, image, measurements, crown angle Exact specs (cert number, carats, color, clarity, dimensions) feed competitor cert-number search URLs for undercutting Rare Carat / Blue Nile / Brilliant Earth Both Nivoda and Loupe360 responses go through shared buildIntelResponse() for consistent pricing intelligence output to Yen Update 10:53 PM Β· ZRosserMcIntosh
escape + in consultation redirect sources (Next.js path modifier) Refactor
Supabase: Storage (/bin/zsh.021/GB), Egress (/bin/zsh.09/GB), DB disk (/bin/zsh.125/GB) Image transforms (/1k), Edge functions (/1M)
DeepL: ~/1M characters (API Pro)
K99 internal: email (/bin/zsh.001/send), messenger, webhooks, support
Low-cost AI (Haiku): 2x provider cost
Standard AI (Sonnet/GPT-5.4): 3x provider cost
Premium/realtime AI: 4-5x provider cost
Infrastructure (LiveKit/storage): 3-4x
Internal services (email/webhooks): 5-10x
Locked: no overages, feature pauses at limit (default for new tenants)
Auto-Recharge: charge card at threshold ( increments)
Monthly Invoice: accumulate and bill at month-end (trusted tenants)
Enterprise Contract: custom terms, PO, wire
Internal: track everything, bill nothing (Katura-owned tenants)
Added Metering, Rate Limits, Rate Card, Overages, Abuse Detection links 10:30 PM Β· ZRosserMcIntosh
Phase 1 β consolidate marketing analytics under /admin/analytics New route group (marketing) under analytics with shared KPI layout /admin/analytics/conversions β funnel, engagement, journeys, Meta events /admin/analytics/traffic β channels, geo, hourly, UTM campaigns /admin/analytics/orders β cart activity, wishlist, revenue by source Existing analytics pages (overview, customers, team, etc.) untouched Sidebar nav: stella/marketing β analytics/conversions Redirects: all /admin/stella/marketing/* β /admin/analytics/* /admin/stella now redirects to /admin/analytics/conversions Docs 9:24 PM Β· ZRosserMcIntosh
meeting minutes β CAD viewer & Yen AI testing session (May 15) Feature 9:23 PM Β· ZRosserMcIntosh
consultation offer pages + smart link attribution layer Create 3 paid-traffic offer pages (upgrade-credit, diamond-studs, bridal-bundle) Shared offer component with 10-section conversion layout + sticky mobile CTA Attribution hook: URL params β localStorage β cookie β hidden form fields Extend API route, booking pipeline, and Prisma schema with 12 attribution fields Add +URL alias redirects in next.config.ts Remove ,000 promo from base consultation page (now clean evergreen) Smart link seed script: 24 links across 4 groups (EN men, EN women, retarget, PT-BR) Full plan doc: docs/active/CONSULTATION-OFFER-PAGES-PLAN.md Update 8:04 PM Β· ZRosserMcIntosh
marketing crash separate kpisPartial from data context Update 7:42 PM Β· ZRosserMcIntosh
marketing page crash β funnelRates undefined during KPI fast-load The KPI partial payload (from /api/admin/analytics/kpis) doesn't include funnelRates. The page was accessing data.funnelRates.cartToCheckout before the full conversions response landed, crashing with 'can't access property'. Fix: destructure funnelRates into 'fr' with a safe N/A fallback so the funnel section renders gracefully during the partial-data window. Feature 7:20 PM Β· ZRosserMcIntosh
email β default mailbox redirect, alias management, Translate & Send email-shell: client-side fallback redirect to personal mailbox when landing on /admin/email with no slug (prevents blank inbox on nav) email-settings-dialog: full alias add/remove UI β '+ Add alias' button with email input, removes via Γ badge, calls POST/DELETE accounts API email-settings-dialog: '+ Add mailbox' tab β create Personal or Shared mailboxes directly from settings without touching the API accounts/[accountId]/route.ts: new DELETE endpoint for alias + empty shared mailbox removal (blocks deletion of PERSONAL or non-empty accounts) compose-dialog: 'Translate & Send' button in footer with language picker dropdown (8 languages), tooltip explaining saved original + translated send compose-dialog: translateToLanguage local state β works for new threads (not just prefilled replies); unified with prefill.translateToLanguage path supabase: add_yen_limit_overrides migration applied via supabase db push Feature 6:05 PM Β· ZRosserMcIntosh
dedicated OPENAI_IMAGE_API_KEY for gpt-image-1 transformations enhance/route.ts: use OPENAI_IMAGE_API_KEY (falls back to OPENAI_API_KEY) enhance/route.ts: update config check to reflect new key name .env.example: document OPENAI_IMAGE_API_KEY + K99_OPENAI_IMAGE_API_KEY Feature 5:53 PM Β· ZRosserMcIntosh
ai-photo-studio demo β fix slider orientation, square frame, earring metal-change demo before-after-slider: fix image order so Original is on left, AI Enhanced reveals from left as you drag right (was inverted) before-after-slider: default aspect ratio now 1/1 (square frame) ai-photo-studio-client: pass aspectRatio='1/1' to BeforeAfterSlider preset-data: add featured 'Rose Gold β Yellow Gold' preset at top with real earring before/after images preset-data: update 'rose-gold' and 'yellow-gold' presets to use earring images (EARRING_ROSE / EARRING_YELLOW) and mark isAvailable=true assets: earrings-rose-gold.png + earrings-yellow-gold.png β /public/demo/ Update 5:36 PM Β· ZRosserMcIntosh
email expand sync, Yen logo + cursive text thread-view: lift expand state to ThreadView with shared expandedIds Set β clicking either column card now syncs expand/collapse across both sides thread-view: add onToggle/expanded controlled props to MessageCard and TranslatedMessageCard; remove independent useState from both components thread-view: old untranslated outbound on English column shows a clear placeholder instead of the Portuguese body yen-bubble: replace yen-logo.png β yen-avatar.png, remove invert filter on all 4 logo circles (FAB, panel header, welcome, message avatar) yen/page.tsx: same logo swap + remove invert/mixBlendMode on all 4 instances; 'Yen' title text now rendered in Dancing Script cursive layout.tsx: add Dancing Script font (CSS var --font-dancing-script) Feature 5:11 PM Β· ZRosserMcIntosh
AI Product Photo Studio demo + Antar 404 fix /admin/ai-photo-studio/demo β polished interactive demo page Before/after drag slider with touch + mouse support, pulse handle 10 transformation presets (Professional Photo, White BG, Square Crop, Instagram Story, Rose Gold, Yellow Gold, Transparent PNG, Luxury Hero, Moss Background, Custom Prompt) DEMO_MODE=true β no API calls, no tokens spent, preloaded images Cost/Spend Controls panel with per-preset estimates Thumbs up/down feedback with chips + comment (local state) Custom Prompt demo with animated processing timeline Product Preservation Rules card (allowed vs requires review) Floating ambient orb background, framer-motion animations 7 reusable components under src/components/admin/ai-photo-studio/ Add before/after demo images for Professional Photography preset /public/demo/ai-photo-studio/necklace-before-blue-velvet.jpg /public/demo/ai-photo-studio/necklace-after-white-background.png under-development: new 'Media & AI Imaging' section with Studio link Fix Antar 404 (T-HZMN7): middleware was rewriting antar.katura1999.com/login β /antar/login (404). Added /login + /auth to exclusion list so NextAuth sign-in resolves at root level on the antar subdomain. Feature 4:57 PM Β· ZRosserMcIntosh
AI image enhancement in product photos + media/enhance API Add ImageEnhancementJob Prisma model + SQL migration POST /api/admin/media/enhance β OpenAI gpt-image-1 transformations Presets: enhance, white_bg, square_crop, luxury_hero, variant Uploads result to Supabase, tracks job with status/cost/audit trail ProductPhotoUpload: per-image AI enhance buttons with before/after preview modal + approve (adds as new image) / discard flow Email translation fixes: GET /api/admin/email/[messageId]/translate β cache-only check (no AI) useTranslation: loadCachedOnMount option (shows saved translations on open without calling AI; Translate button still triggers AI) thread-view: autoTranslate=false, loadCachedOnMount=true Outbound translated replies stored with originalHtmlBody in textBody + translated-outbound tag β right panel shows English, not Portuguese Fix appraisal PDF import path (../../pdf-template) Under-development page: add Media Studio link Feature 3:44 PM Β· ZRosserMcIntosh
route Nivoda API through Webshare static proxy for IP whitelisting Install https-proxy-agent NivodaClient fetchGraphQL now passes dispatcher=HttpsProxyAgent when WEBSHARE_PROXY_URL env var is set Primary proxy: 45.38.107.97:6014 (London, UK) Fallback proxy: 142.111.48.253:7030 (Los Angeles, US) Feature 3:41 PM Β· ZRosserMcIntosh
insurance appraisal certificate generator at /admin/appraisals /admin/appraisals β full CRUD list with search, preview, download /api/admin/appraisals β existing GET/POST (enhanced with text search) /api/admin/appraisals/[id] β GET / PATCH / DELETE /api/admin/appraisals/[id]/pdf β streams a polished PDF certificate /api/admin/appraisals/pdf-template.tsx β @react-pdf/renderer document Double gold border frame Katura header logo centered at top QR code (top-left) linking to /appraisal/[id] for verification Certificate number (top-right), e.g. KATURA-APR-2026-XXXXXX Owner info, item details, metal/stones, condition columns Highlighted valuation box (replacement, fair market, liquidation) Scope & methodology legal text block Signature line + appraiser name + circular KATURA seal Katura footer with domain + cert number Typeahead search for customer and product Metal type, karat, weight fields Stones description (free text) Three value fields (replacement is primary) Issued + expiry dates (defaults to today / +2 years) Internal notes field Inline PDF preview via iframe dialog + download button 3:17 PM Β· ZRosserMcIntosh
add outbound IP debug route for Nivoda whitelisting Update 3:16 PM Β· ZRosserMcIntosh
CAD viewer HDR NetworkError + auto-select first file Environment preset='studio' was fetching studio_small_03_1k.hdr from an external CDN (vazxmixjsiawhamofees.supabase.co) which fails in production due to CORS/CSP. Changed to local file: Environment files='/hdri/studio_small_03_1k.hdr' File already exists at public/hdri/studio_small_03_1k.hdr β just wasn't being used. Auto-select first CAD file when picking a project in the meeting tray. Removes the redundant 'Choose file' click when a project has only one file (most common case). Multiple files still shown for switching, and first is pre-selected so the Share button is always ready immediately. Update 8:38 AM Β· ZRosserMcIntosh
CAD viewer now sources files from /admin/design storage links display-assets API now queries BOTH sources: 1. JewelryProjectCadFile (direct project uploads) 2. CadFileLink where linkType=JEWELRY_PROJECT (design page links) Builds Supabase public URLs from storageKey for source 2 files Merges and deduplicates across both sources Still filters to STL-only for the 3D viewer Update 8:09 AM Β· ZRosserMcIntosh
CC button text, feedback light theme, Yen logo, diamond intel Nivoda fallback, ShipEngine key Feature 7:08 AM Β· ZRosserMcIntosh
certificate verification (GIA/IGI/WISE) on authenticate page