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
828,292
Web platform β TypeScript, React, Prisma, CSS
iOS
78,204
Swift + SwiftUI lines
Android
3,117
Kotlin + Jetpack Compose lines
All platforms
909,613
Web + iOS + Android combined (44.5Γ the King James Bible)
Characters written
35.04M
35,041,420 total characters
Updates pushed
1,893
exact commit count on main
Current version
v1.18.93
build 1893 Β· 1c76417
Database models
392
across 47 schema files β most SaaS platforms have 20β50
API endpoints
955
individually routed β Stripe's public API has ~400
Translated strings
82,512
every string, in 24 languages
System permutations
10^287
2^955 endpoint combinations β more than atoms in the observable universe (10^80)
Project age
6mo 15d
since Dec 14, 2025
Pre-AI dev hours
30.3K hrs
909,613 lines Γ· 30 LOC/hr β equivalent to 14.6 years (senior engineer, no AI)
With-AI dev hours
7.6K hrs
4Γ AI productivity multiplier (2024β2026 studies) β equivalent to 948 days
Equivalent firm cost
$7,859,636
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
1,893 updates pushed Showing page 20 of 40 Β· 951β1,000 of 2,000 fetched
Wednesday, March 4, 2026 16 updates pushed
Docs 9:49 PM Β· ZRosserMcIntosh
Update schema refactor plan + session plan β all phases complete 9:47 PM Β· ZRosserMcIntosh
Phase 6b: Migrate 137 public API routes to tenantPrisma() 137 files migrated to tenantPrisma() 37 files keep both imports (use $queryRaw/$executeRaw/$transaction) 52 files correctly skipped (no tenant-scoped models) 0 build errors Feature 8:58 PM Β· ZRosserMcIntosh
Phase 6 β migrate 152 admin API routes to tenantPrisma() Replaced raw prisma.model.xxx with db.model.xxx (tenant-scoped) in 152 files const db = tenantPrisma(TENANT_ZERO_ID) injected at top of each handler Kept raw prisma import only where $queryRaw/$transaction/non-scoped models needed Removed ~50 redundant tenantId: TENANT_ZERO_ID from where/data objects Migration script: scripts/infra/migrate-to-tenant-prisma.ts Manual cleanup of 8 inline tenantId references Build passes (exit 0), zero TypeScript errors in src/ Feature 6:47 PM Β· ZRosserMcIntosh
legacy Shopify 301 redirects + robots.txt cleanup for GSC indexing /blogs/news/:slug β /jewel-vox/:slug (old Shopify blog) /collections/earrings β /creations/earrings /collections/pearl-bracelets β /creations/bracelets /collections/pearl-rings β /creations/rings /collections/all β /creations /pages/store β /contact /pages/:slug β / (catch-all for old Shopify pages) /platform/docs/:path* β / (leaked SaaS docs) /creations/south-seas-starfish-live-on-the-coral-reef β starfish collection Block /services/ (Shopify login_with_shop auth URLs) Block /collections/*.atom (Shopify atom feeds) Block /pages/ and /blogs/ (old Shopify paths) Block /platform/ (internal SaaS docs) Added missing /education/4cs page Bumped education pages priority from 0.5 β 0.6 Update 6:19 PM Β· ZRosserMcIntosh
remove <video:player_loc> from video sitemap β was duplicating <loc> page URL player_loc must point to an embeddable SWF/player, not the HTML landing page We don't have an embeddable player, so remove it entirely content_loc already correctly points to raw Supabase .MP4 video files Fixes all 33 instances flagged by Google Update 6:10 PM Β· ZRosserMcIntosh
comment out stray tenantId in task route commented blocks, add tenantId to task create tenantId: TENANT_ZERO_ID was placed outside comments in both tasks/route.ts and tasks/[id]/route.ts Properly commented the lines in the TODO notification blocks Added tenantId to the actual prisma.task.create data object Feature 6:00 PM Β· ZRosserMcIntosh
add video sitemap for Google Video indexing (33 product videos) New /video-sitemap.xml route with Google video sitemap spec (xmlns:video) Includes thumbnail_loc, content_loc, player_loc, publication_date per video Queries all active Katura products with videoUrl from database Rich auto-generated descriptions with product name, metal type, jewelry type Added video-sitemap.xml to robots.txt alongside main sitemap Addresses Google Search Console '28 videos could not be indexed' issue Caches for 1 hour with stale-while-revalidate Update 5:45 PM Β· ZRosserMcIntosh
broken wholesale import, VideoObject SEO, ring image swap, footer press link Fix broken import in wholesale stores routes (import inside import β build failure) Add VideoObject JSON-LD to product detail pages (35 products with video get rich results) Replace fictional design-ring image with Stella's 777 Lucky Numbers rose gold ring Add 'In the Press' link to footer navigation under Company (all 24 locales) Add generateVideoObjectSchema to structured-data.ts Feature 5:12 PM Β· ZRosserMcIntosh
backfill scripts for product image alt text (175 images upgraded in DB) backfill-image-alt-text.ts: fills null alt fields with '{Name} β {Metal} {Type} by Katura' upgrade-image-alt-text.ts: upgrades slug-based alt text (e.g. 'pearl-studs-3') to SEO-friendly format Ran on production DB: 175 images upgraded from slugs/filenames to descriptive alt text Eliminates 'ChatGPT Image Dec 23...' alt texts from product images Feature 4:53 PM Β· ZRosserMcIntosh
add 'In the Press' page β JCK Magazine & Garden & Gun features New /in-the-press page with 3 press articles (JCK Vermeer pearls, Garden & Gun river pearls, JCK Raw Sugar diamonds) Full NewsArticle + CollectionPage JSON-LD structured data for Google rich results sameAs signals linking Katura to authoritative press URLs BreadcrumbList schema on press page 'As Featured In' trust banner on homepage (between recommendations and education) 'As Featured In' section on About page with link to press page Press page added to sitemap (priority 0.7) Press page added to footer navigation under Company Designer bio section with internal links to /about and /creations Press inquiry CTA with link to /contact page Feature seo 4:29 PM Β· ZRosserMcIntosh
comprehensive SEO overhaul β structured data, breadcrumbs, canonical URLs, social profiles Fix double 'Katura' in home page title (use title.absolute) Fix social profiles: instagram/katura1999, facebook/katura1999jewelry, add tiktok + pinterest Add LocalBusiness (JewelryStore) JSON-LD to every page via locale layout Add ItemList JSON-LD on shop page (/creations) with top 50 products Add ItemList JSON-LD on all 6 category pages (earrings, rings, necklaces, bracelets, engagement-rings, wedding-bands) Add CollectionPage JSON-LD on collection detail pages with canonical + hreflang alternates Add ItemList JSON-LD on collections listing page Add Blog JSON-LD on blog listing page (/jewel-vox) with BlogPosting entries Add BreadcrumbList JSON-LD on shop, categories, collections, and blog pages New structured-data generators: generateLocalBusinessSchema, generateItemListSchema, generateBlogSchema Feature 4:09 PM Β· ZRosserMcIntosh
legal policies, compliance gate, onboarding, brevo events, builder icons, stripe scripts, smoke tests Update 4:11 AM Β· ZRosserMcIntosh
guard against undefined session.user.id in hero pin create Update 4:06 AM Β· ZRosserMcIntosh
add tenantId to all admin API route create calls (46 files, 60+ models) Systematic sweep of every admin API route that creates tenant-scoped models using the raw prisma client. These all need explicit tenantId since the auto-injection only works with the tenant-scoped client. Models fixed: Collection, ProductCategory, ProductTag, ProductVariantGroup, ProductVariantGroupMember, Shipment, Promotion, SalesGoal, Achievement, CommissionRecord, TeamMemberPay, ServiceRequest, ServiceStatusHistory, WholesaleStore, WholesaleStoreActivity, WholesaleSetting, BusinessExpense, TimeEntry, Project, TaskColumn, Idea, TaskActivity, TaskAttachment, Notification, WiseIntegration, WiseRecipient, WiseTransfer, WiseRateAlert, JobPosting, CrmDeal, CrmActivity, CrmTask, CrmNote, CrmContact, CrmPipelineStage, HeroPinRule, StrategicObjective, KeyResult, Initiative, AnalyticsExportLog Also fixed: WiseIntegration queries were using tenantId: null (broken since tenantId became NOT NULL) β changed to TENANT_ZERO_ID. Zero TypeScript errors (tsc --noEmit clean). Update 3:32 AM Β· ZRosserMcIntosh
add tenantId to product admin API routes (create, duplicate, update images) route.ts POST: add tenantId to product.create [id]/duplicate/route.ts POST: add tenantId to product.create, productImage.create, inventoryItem.create, productVariant.create [id]/route.ts PUT: add tenantId to two productImage.create calls (fallback create on P2025 and new image create) Chore 1:08 AM Β· ZRosserMcIntosh
add translation utility scripts (fix, verify, docs-sidebar) Tuesday, March 3, 2026 5 updates pushed
Update 8:33 PM Β· ZRosserMcIntosh
complete translation audit β 0 missing keys across all 24 locales Added footer.loveEngagement.weddingSites to 21 locales Added product.handcraftedUnique to 21 locales Added full weddingSites namespace (31 keys) to 21 locales Added employeeLogin namespace (15 keys) to 21 locales Added developer namespace to 21 locales Added docs.sidebar.home and docs.sidebar.fullSearch to 21 locales Fixed NL footer.newsletter from string to proper object Removed temporary audit/fix scripts All 2,778 translation keys now at 100% parity with English Feature 7:38 PM Β· ZRosserMcIntosh
tenant email marketing system + fix admin email builder + i18n Add emailOveragePerEmail & stripeEmailOveragePriceId to SaasPlan schema Update PlanDetails/TenantEntitlements interfaces with emailPerEmail Update all plan mapping functions and DEFAULT_LIMITS SQL migration: Starter /bin/zsh.01, Professional /bin/zsh.008, Enterprise /bin/zsh.005 Replace TODO stubs in handleSave/handleSend with real API calls Save creates campaign + template, Send creates campaign + sends via Brevo campaigns, templates, segments, settings: add TENANT_ZERO_ID to GET/POST Monday, March 2, 2026 6 updates pushed
Chore 8:53 PM Β· ZRosserMcIntosh
update luxury brand strategy doc + misc scripts Chore 8:43 PM Β· ZRosserMcIntosh
update investor page styling to navy theme Feature 3:45 PM Β· ZRosserMcIntosh
legitimate multi-method valuation calculator for cap table Operating valuation fixed at 7Γ TTM revenue as the company benchmark Three valuation tabs: Comparable Multiples, DCF Analysis, Valuation Summary DCF model with configurable growth rate, FCF margin, discount rate, terminal multiple Projection table showing revenue, FCF, and PV for each forecast year Valuation Summary tab consolidates all methods (operating, comps bear/base/bull, DCF, last round, SAFE cap) Sunday, March 1, 2026 23 updates pushed
Feature 11:26 PM Β· ZRosserMcIntosh
cap table valuation estimator + fix initialization + debug sales rep Industry-comparable multiplier presets (Luxury Jewelry/DTC, E-Commerce, SaaS, Small Business, Manufacturing, Custom) AI-assisted notes explaining each industry's valuation dynamics Revenue or Earnings based (auto-switches per industry) Interactive slider for multiplier with bear/base/bull scenario table Per-share price based on fully diluted count Reference points from last funding round and SAFE caps Legal disclaimer about non-409A nature Copied SQL migration files to migrations/cap-table/ where the initialize handler expects them Added outputFileTracingIncludes in next.config.ts so Vercel bundles the SQL files in the serverless function Better console output for team members fetch to diagnose why the dropdown only shows 'Unassigned' Handles both array and wrapped response formats Update 11:00 PM Β· ZRosserMcIntosh
order detail page β mark-paid for DELIVERED orders, tenantId on all creates Allow DELIVERED orders to be marked as paid (keeps DELIVERED status, just updates payment to SUCCEEDED) Added tenantId to auditLog.create Added tenantId to OrderItem creates (when editing items)
Brevo webhook: resolve tenantId from campaign for events + stats
service.ts: add tenantId to MarketingCampaignStat creates
Rewrite marketing hub with real DB queries (stats, campaigns, templates)
Email usage bar with overage warnings
New campaign creation flow (3-step: details β design β review)
Platform marketing API routes (campaigns CRUD + send-now)
Platform API helpers (getPlatformTenantId, getPlatformApiContext)
Add /api/saas/blog/categories route (GET/POST)
Add employeeLogin + developer namespaces to all 24 locales
Add weddingSites namespace translations for all 23 non-EN locales
Add footer.loveEngagement.weddingSites + product.handcraftedUnique
Fix NL footer.newsletter structure (string β object)
Internationalize employee-login-form.tsx Feature 5:48 PM Β· ZRosserMcIntosh
add Katura High Jewelry page and footer link with all 24 translations Add /high-jewelry page with invitation-only high jewelry content Add highJewelry link at top of footer shop column Add full highJewelry namespace translations in all 24 locale files Copy citrine necklace image to public/images with clean filename Update 5:44 PM Β· ZRosserMcIntosh
complete tenant data isolation audit β all 8 issues resolved Restructured where clause to use AND for combining tenant scope with search OR Scoped trailing 12-month revenue query to tenant_katura orders Issue #7: createAuditLog() now writes tenantId (defaults to TENANT_ZERO_ID) All 14 inline prisma.auditLog.create() calls now pass tenantId explicitly createAuditLogger() accepts tenantId param or reads x-tenant-id header logFileUpload/logFileDownload/logDataExport accept tenantId Issue #8: SQL backfill script for User.tenantId (staff + customers) Feature 12:12 AM Β· ZRosserMcIntosh
redesign investor page β light/elegant aesthetic matching /platform, rose gold typography Replaced dark navy (#030712) theme with clean white/stone-50 light backgrounds Switched all headings to font-serif for refined luxury feel Applied rose gold gradient text (from-stone-800 via-amber-700 to-stone-700) matching /platform Cards: white bg + stone-200 borders with hover shadows instead of frosted glass Buttons: solid stone-900 with elegant hover states Section labels: rose gold gradient uppercase tracking Removed 'Founder' from Rosser's title β now just 'Chief Technology Officer' Promoted Stella to 'Chief Marketing Officer' (from Director of Marketing) Updated all docs: LUXURY_BRAND_STRATEGY, BUILD-STATUS, KATURA_SAAS_PLATFORM_PLAN
Rich financial summary: gross/net revenue, COGS, gross profit, gross margin, AOV, refunds
API now queries COGS via OrderItem Γ Product.costPrice and refunded order totals
RevenuePeriod type with full P&L metrics per period (TTM, current year, prior year)
Operating valuation prominently displayed in card header with per-share price
All figures derived from actual settled order data Feature 3:11 PM Β· ZRosserMcIntosh
revenue-based valuation estimator β auto-populates from actual order data Cap table API now queries TTM, current year, and prior year settled order revenue Uses same SETTLED_STATUSES + Shopify import filter as analytics overview ValuationEstimator auto-populates revenue from real orders on load Users can toggle between TTM / YTD / Prior Year revenue sources Editable for simulation β shows 'Actual' vs 'Simulated' badge Reset button to snap back to actual revenue after editing YoY growth badge when prior year data available Added RevenueData type to cap table types Disclaimer updates when using actual revenue data Refactor 2:13 PM Β· ZRosserMcIntosh
remove all `any` types from tenant-prisma.ts Created AllModelsQueryArgs interface for $allModels extension callbacks Replaced 18 `: any` destructured params with typed AllModelsQueryArgs Added explicit `as Record<string, unknown>` casts for result/data access Zero `any` remaining in tenant-prisma.ts (core tenant isolation layer) All 39 existing tests pass unchanged Update 12:16 AM Β· ZRosserMcIntosh
cap table β run migrations directly, remove fs.readFileSync from Vercel Ran all 5 cap table SQL migrations against Supabase directly 15 cap_* tables created with seeded data (October Skies Benediction LLC) Rewrote handleInitializeTables to check for existing tables instead of reading files Removed fs/path imports and outputFileTracingIncludes from next.config.ts handleReseed returns 501 with instructions for local execution
Added tenantId to AuditLog create (was causing 500 on source update)
Added tenantId to CommissionRecord create
Added tenantId to DELETE audit log
Improved error response with details
Show 'Mark as Paid' button for DELIVERED orders when payment hasn't been collected (checks payment status, not order status)
Removed DELIVERED from the status blocker list Update 10:48 PM Β· ZRosserMcIntosh
disable Command built-in filtering for server-side search The shadcn Command component has its own client-side filter that was racing with our server-side search. When results came back from the API, Command's internal filter couldn't match them because they weren't present when the filter string was first evaluated. Added shouldFilter={false} to both customer and product Command components so only our useEffect debounced API search controls what's shown. Feature 10:07 PM Β· ZRosserMcIntosh
update rexandkate wedding site hero text Changed the top line from 'Request the Pleasure of Your Company' to 'We Request the Pleasure of Your Company' Update 10:04 PM Β· ZRosserMcIntosh
align order and payment status enums with schema CONFIRMED β PAID (schema uses PAID, not CONFIRMED) Added REFUNDED option PAID β SUCCEEDED (schema uses SUCCEEDED, not PAID) Added PROCESSING and PARTIALLY_REFUNDED options Update 7:30 PM Β· ZRosserMcIntosh
correct import path for TENANT_ZERO_ID 7:15 PM Β· ZRosserMcIntosh
add detailed logging to order creation flow Update 6:37 PM Β· ZRosserMcIntosh
add missing tenantId to Order, OrderItem, Payment, and AuditLog creates prisma.order.create() nested items.create (OrderItem) nested payments.create (Payment) prisma.auditLog.create() Feature 6:13 PM Β· ZRosserMcIntosh
replace Create Order dialog with full page at /admin/orders/new Sticky header with back arrow, cancel, and create buttons 2-column layout: main content (2/3) + sticky sidebar (1/3) Left column: Customer, Products, Shipping/Billing Address, Notes Right sidebar: Order Summary with live totals, Status & Payment, Date Extracted reusable AddressForm component Mobile-responsive: single column with bottom submit button Expanded country list (30 countries) Added Cash payment method option 'Billing same as shipping' defaults to checked Old dialog component preserved for reference but no longer imported Update 5:34 PM Β· ZRosserMcIntosh
include tenantId in ProductImage.create() during upload ProductImage.tenantId is required (NOT NULL). The upload route was omitting it, causing Prisma to reject the scalar productId and demand a relation connect instead. Now fetches tenantId from the parent Product and passes it through. Update 5:30 PM Β· ZRosserMcIntosh
upload UX β show detailed errors, detect video files in image uploader Upload route: detect video MIME types and hint to use 'Product Video' section Client: show each server-reported error detail as a toast notification Remove diagnostic endpoint (upload-test) and debug script (check-product) Expanded allowed MIME types on client (avif, heic, heif, tiff, svg+xml) Update 5:22 PM Β· ZRosserMcIntosh
upload route β trim productId, add raw SQL fallback, return details on 404 5:15 PM Β· ZRosserMcIntosh
add productId logging to upload route 5:12 PM Β· ZRosserMcIntosh
add upload diagnostic endpoint Chore 4:56 PM Β· ZRosserMcIntosh
remove test script Update 4:56 PM Β· ZRosserMcIntosh
expand image upload to accept AVIF/HEIC + add maxDuration for Vercel Client-side allowlist expanded: AVIF, HEIC, HEIF, TIFF, SVG Added fallback: any image/* type accepted if not in explicit list HTML accept attribute updated to include new formats Added maxDuration=60 to upload route for Vercel serverless Better error messages include file type for diagnosis Update 4:38 PM Β· ZRosserMcIntosh
product image upload β expand Supabase MIME types + better logging Updated Supabase bucket to also allow: image/avif, image/heic, image/heif, image/tiff, image/svg+xml Added file name, MIME type, and size logging on every upload attempt Error messages now include the MIME type for easier diagnosis Update 4:11 PM Β· ZRosserMcIntosh
exclude 'Custom Rings' category from homepage and search Added EXCLUDE_CUSTOM_RINGS_CATEGORY and CUSTOM_RINGS_CATEGORY_SLUG constants to product-visibility.ts Applied category filter in getDynamicCollections (home-cache.ts) Applied to search API (categories + products) Custom rings category remains visible in admin Update 3:41 PM Β· ZRosserMcIntosh
exclude custom ring orders from all public product listings Homepage dynamic collections (home-cache getDynamicCollections) Homepage new arrivals (home-cache getNewArrivals) Hero product collage (/api/products/collage) Collections listing page (/collections) Collection detail page (/collections/[id]) Collection API (/api/collections/[slug]) Creations/shop page (/creations) Category pages (category-page.tsx) Products API (/api/products) 3:07 PM Β· ZRosserMcIntosh
Phase 5: Build tenantPrisma() client extension for 184 tenant-scoped models Rewrote src/lib/saas/tenant-prisma.ts from Phase 0 (4 SaaS models, manual per-model hooks) to Phase 5 (184 models, $allModels extension with runtime Set lookup) TENANT_SCOPED_MODELS: Set of 184 PascalCase model names covering all models with NOT NULL tenantId (156 core + 27 SaaS + 1 DesignFile) Covers all 16 Prisma operations: findMany, findFirst, findFirstOrThrow, findUnique, findUniqueOrThrow, create, createMany, createManyAndReturn, update, updateMany, upsert, delete, deleteMany, count, aggregate, groupBy findUnique/findUniqueOrThrow use post-fetch verification (can't inject tenantId into unique where clause) create/createMany strip tenant relation field to avoid Prisma conflicts upsert handles where + create + update sections, prevents tenantId mutation Throws on empty tenantId to prevent accidental global queries withTenant() preserved as deprecated alias for backward compatibility Exported: tenantPrisma, withTenant, isTenantScoped, TENANT_SCOPED_MODELS, TenantPrismaClient type checkLimit() now uses tenantPrisma for product counts (was TODO in Phase 0) Updated barrel export in src/lib/saas/index.ts 39 unit tests passing (registry correctness, hook behavior, cross-tenant guards) npx tsc --noEmit: zero source errors npx prisma validate: schemas valid 2:15 PM Β· ZRosserMcIntosh
Phase 4: Make tenantId NOT NULL on 156 tenant-scoped models Updated 31 .prisma schema files: tenantId String? β String, SaasTenant? β SaasTenant Applied ALTER COLUMN SET NOT NULL to all 156 tables in production DB Used race-condition-safe strategy: SET DEFAULT β backfill NULLs β SET NOT NULL β DROP DEFAULT Caught and backfilled 2 straggler rows in ShipStationSyncLog during transaction 20 hybrid models intentionally left nullable (User, Article, GiftCard, etc.) Zero TypeScript compilation errors Prisma validate β
| Prisma generate β
Feature 12:59 PM Β· ZRosserMcIntosh
Phase 3 complete β backfill 13,000 NULL tenantIds β tenant_katura Dry-run mode by default (--execute flag to run) Verifies tenant_katura exists before touching data Counts NULLs per table before executing Single SERIALIZABLE transaction β all-or-nothing Post-execution validation confirms zero NULLs remain 39 of 155 tables had NULL tenantIds 13,000 rows backfilled to 'tenant_katura' 117 tables were already clean (empty or pre-populated) Post-run validation: 0 NULLs remaining across all 155 tables Docs 12:35 PM Β· ZRosserMcIntosh
Phase 2 complete β classify all 252 models for tenant isolation 155 models β tenantId String (make required) 21 models β tenantId String? (keep nullable β hybrid/shared) 9 join tables β no tenantId (inherit from parents) 22 global models β no tenantId (platform/reference data) 11 user-scoped β no tenantId (scoped by userId/siteId) 34 SaaS models β already correctly configured Backfill SQL generated for all 155 tables (using tenant_katura)