Concepts, value, and typical clone scenarios — less code.
Concepts, value, and typical clone scenarios — less code.
Підготовка контенту платформи Ring
Підготовка контенту платформи Ring
Підготовка контенту платформи Ring
Ring Platform optimizes at four layers: Server Component request dedup, Next 16 'use cache' catalog reads, client bootstrap single-flight, and DatabaseService EntityCache. All patterns below trace to real files — no fabricated KPIs or invented utilities.
Use Founder / Developer tabs in the docs sidebar to filter this page.
Most Ring pages are React Server Components — HTML arrives pre-rendered with minimal client JavaScript. Performance wins come from architecture, not bolt-on CDN tricks:
| Layer | Benefit for operators |
|---|---|
| Server-first rendering | Marketing and catalog pages ship without heavy JS bundles |
| Request-level dedup | One database read per page render, not one per component |
| Batched analytics | Web Vitals sent as one POST per page load, not five |
| Provider SSOT | No duplicate credit-balance or notification polls draining API quota |
| Build-time Firebase mock | Static generation does not require live Firebase credentials |
Ring Platform optimizes at four layers: Server Component request dedup, Next 16 'use cache' catalog reads, client bootstrap single-flight, and DatabaseService EntityCache. All patterns below trace to real files — no fabricated KPIs or invented utilities.
Use Founder / Developer tabs in the docs sidebar to filter this page.
Most Ring pages are React Server Components — HTML arrives pre-rendered with minimal client JavaScript. Performance wins come from architecture, not bolt-on CDN tricks:
| Layer | Benefit for operators |
|---|---|
| Server-first rendering | Marketing and catalog pages ship without heavy JS bundles |
| Request-level dedup | One database read per page render, not one per component |
| Batched analytics | Web Vitals sent as one POST per page load, not five |
| Provider SSOT | No duplicate credit-balance or notification polls draining API quota |
| Build-time Firebase mock | Static generation does not require live Firebase credentials |
Ring Platform optimizes at four layers: Server Component request dedup, Next 16 'use cache' catalog reads, client bootstrap single-flight, and DatabaseService EntityCache. All patterns below trace to real files — no fabricated KPIs or invented utilities.
Use Founder / Developer tabs in the docs sidebar to filter this page.
Most Ring pages are React Server Components — HTML arrives pre-rendered with minimal client JavaScript. Performance wins come from architecture, not bolt-on CDN tricks:
| Layer | Benefit for operators |
|---|---|
| Server-first rendering | Marketing and catalog pages ship without heavy JS bundles |
| Request-level dedup | One database read per page render, not one per component |
| Batched analytics | Web Vitals sent as one POST per page load, not five |
| Provider SSOT | No duplicate credit-balance or notification polls draining API quota |
| Build-time Firebase mock | Static generation does not require live Firebase credentials |
userIdhooks/use-vendor-status.ts (30s), hooks/use-credit-balance.ts (5s bootstrap) |
| Session refetch tuning | Per-tab (client) | 15min interval, no focus/offline refetch | features/auth/components/session-provider.tsx |
| Web Vitals batching | Per-tab (client) | Buffer + 1.5s debounce → single POST | components/providers/web-vitals-provider.tsx |
Not used: sessionStorage server caches, custom RingApiClient, per-metric Web Vitals POST loops, or performance budget enforcement in next.config.mjs.
cache() — request dedupMultiple imports of the same document during one Server Component render resolve to one Firestore read.
'use cache' SSOTShared by app/api/store/products/route.ts and getStoreProducts server action. Invalidate with updateTag('store:products') after product mutations.
30-second TTL on entities collection for read-after-write consistency. Writes invalidate affected keys automatically.
Use findDocById for single-document lookups — not queryDocs filtered by id.
WebVitalsProvider buffers useReportWebVitals callbacks and flushes one POST /api/analytics/web-vitals per debounce window (1.5s), shaped to webVitalsPayloadSchema in features/analytics/lib/analytics-db.ts. Metrics also flush on visibilitychange / pagehide.
useReportWebVitals fires once per Core Web Vital (CLS, FCP, LCP, TTFB, INP). Without batching that would be up to five POSTs per page load. The provider collapses them into one request.
Documented in hooks/HOOKS-README.md § P4:
useVendorStatus — dedupes GET /api/vendor/status across sidebar layout remounts.useCreditBalance — bootstrap fetch dedupes across Strict Mode / Suspense remounts; live updates still flow through CreditBalanceProvider + tunnel.Enforce with ./scripts/validate-provider-ssot.sh (seven gates — see Best practices).
During next build, lib/firebase/build-mock.server.ts returns mock Firestore/Auth instances so static generation does not require live Firebase credentials. SWC minification and CSS optimization are handled by Next.js 16 automatically — there is no swcMinify or experimental.optimizeCss flag.
getCacheMetrics() in firebase-service-manager.ts logs hit rate when FIREBASE_DEBUG_LOGS=true. This is a dev console tool, not production monitoring.
All connection pooling lives in lib/database/. Domain code uses db(); PostGIS-only raw SQL uses getSharedPgPool(). Never instantiate new Pool( outside lib/database/ — gate 7 of the SSOT script.
userIdhooks/use-vendor-status.ts (30s), hooks/use-credit-balance.ts (5s bootstrap) |
| Session refetch tuning | Per-tab (client) | 15min interval, no focus/offline refetch | features/auth/components/session-provider.tsx |
| Web Vitals batching | Per-tab (client) | Buffer + 1.5s debounce → single POST | components/providers/web-vitals-provider.tsx |
Not used: sessionStorage server caches, custom RingApiClient, per-metric Web Vitals POST loops, or performance budget enforcement in next.config.mjs.
cache() — request dedupMultiple imports of the same document during one Server Component render resolve to one Firestore read.
'use cache' SSOTShared by app/api/store/products/route.ts and getStoreProducts server action. Invalidate with updateTag('store:products') after product mutations.
30-second TTL on entities collection for read-after-write consistency. Writes invalidate affected keys automatically.
Use findDocById for single-document lookups — not queryDocs filtered by id.
WebVitalsProvider buffers useReportWebVitals callbacks and flushes one POST /api/analytics/web-vitals per debounce window (1.5s), shaped to webVitalsPayloadSchema in features/analytics/lib/analytics-db.ts. Metrics also flush on visibilitychange / pagehide.
useReportWebVitals fires once per Core Web Vital (CLS, FCP, LCP, TTFB, INP). Without batching that would be up to five POSTs per page load. The provider collapses them into one request.
Documented in hooks/HOOKS-README.md § P4:
useVendorStatus — dedupes GET /api/vendor/status across sidebar layout remounts.useCreditBalance — bootstrap fetch dedupes across Strict Mode / Suspense remounts; live updates still flow through CreditBalanceProvider + tunnel.Enforce with ./scripts/validate-provider-ssot.sh (seven gates — see Best practices).
During next build, lib/firebase/build-mock.server.ts returns mock Firestore/Auth instances so static generation does not require live Firebase credentials. SWC minification and CSS optimization are handled by Next.js 16 automatically — there is no swcMinify or experimental.optimizeCss flag.
getCacheMetrics() in firebase-service-manager.ts logs hit rate when FIREBASE_DEBUG_LOGS=true. This is a dev console tool, not production monitoring.
All connection pooling lives in lib/database/. Domain code uses db(); PostGIS-only raw SQL uses getSharedPgPool(). Never instantiate new Pool( outside lib/database/ — gate 7 of the SSOT script.
userIdhooks/use-vendor-status.ts (30s), hooks/use-credit-balance.ts (5s bootstrap) |
| Session refetch tuning | Per-tab (client) | 15min interval, no focus/offline refetch | features/auth/components/session-provider.tsx |
| Web Vitals batching | Per-tab (client) | Buffer + 1.5s debounce → single POST | components/providers/web-vitals-provider.tsx |
Not used: sessionStorage server caches, custom RingApiClient, per-metric Web Vitals POST loops, or performance budget enforcement in next.config.mjs.
cache() — request dedupMultiple imports of the same document during one Server Component render resolve to one Firestore read.
'use cache' SSOTShared by app/api/store/products/route.ts and getStoreProducts server action. Invalidate with updateTag('store:products') after product mutations.
30-second TTL on entities collection for read-after-write consistency. Writes invalidate affected keys automatically.
Use findDocById for single-document lookups — not queryDocs filtered by id.
WebVitalsProvider buffers useReportWebVitals callbacks and flushes one POST /api/analytics/web-vitals per debounce window (1.5s), shaped to webVitalsPayloadSchema in features/analytics/lib/analytics-db.ts. Metrics also flush on visibilitychange / pagehide.
useReportWebVitals fires once per Core Web Vital (CLS, FCP, LCP, TTFB, INP). Without batching that would be up to five POSTs per page load. The provider collapses them into one request.
Documented in hooks/HOOKS-README.md § P4:
useVendorStatus — dedupes GET /api/vendor/status across sidebar layout remounts.useCreditBalance — bootstrap fetch dedupes across Strict Mode / Suspense remounts; live updates still flow through CreditBalanceProvider + tunnel.Enforce with ./scripts/validate-provider-ssot.sh (seven gates — see Best practices).
During next build, lib/firebase/build-mock.server.ts returns mock Firestore/Auth instances so static generation does not require live Firebase credentials. SWC minification and CSS optimization are handled by Next.js 16 automatically — there is no swcMinify or experimental.optimizeCss flag.
getCacheMetrics() in firebase-service-manager.ts logs hit rate when FIREBASE_DEBUG_LOGS=true. This is a dev console tool, not production monitoring.
All connection pooling lives in lib/database/. Domain code uses db(); PostGIS-only raw SQL uses getSharedPgPool(). Never instantiate new Pool( outside lib/database/ — gate 7 of the SSOT script.
// lib/services/firebase-service-manager.ts (firebase-full mode)
import { cache } from 'react'
export const getCachedDocument = cache(async (collection: string, docId: string) => {
const db = getAdminDb()
const doc = await db.collection(collection).doc(docId).get()
return doc.exists ? doc : null
})
// features/store/config.ts
export async function getCachedProductCatalog(): Promise<StoreProduct[]> {
'use cache'
cacheTag('store:products')
cacheLife('minutes')
const adapter = await getStoreAdapter()
return adapter.listProducts()
}
const result = await db().queryDocs({
collection: 'entities',
filters: [{ field: 'status', operator: 'eq', value: 'active' }],
orderBy: [{ field: 'createdAt', direction: 'desc' }],
pagination: { limit: 20, offset: 0 },
})
if (!result.success) throw result.error
// next.config.mjs (excerpt)
const nextConfig = {
reactStrictMode: true,
cacheComponents: true,
}
// lib/services/firebase-service-manager.ts (firebase-full mode)
import { cache } from 'react'
export const getCachedDocument = cache(async (collection: string, docId: string) => {
const db = getAdminDb()
const doc = await db.collection(collection).doc(docId).get()
return doc.exists ? doc : null
})
// features/store/config.ts
export async function getCachedProductCatalog(): Promise<StoreProduct[]> {
'use cache'
cacheTag('store:products')
cacheLife('minutes')
const adapter = await getStoreAdapter()
return adapter.listProducts()
}
const result = await db().queryDocs({
collection: 'entities',
filters: [{ field: 'status', operator: 'eq', value: 'active' }],
orderBy: [{ field: 'createdAt', direction: 'desc' }],
pagination: { limit: 20, offset: 0 },
})
if (!result.success) throw result.error
// next.config.mjs (excerpt)
const nextConfig = {
reactStrictMode: true,
cacheComponents: true,
}
// lib/services/firebase-service-manager.ts (firebase-full mode)
import { cache } from 'react'
export const getCachedDocument = cache(async (collection: string, docId: string) => {
const db = getAdminDb()
const doc = await db.collection(collection).doc(docId).get()
return doc.exists ? doc : null
})
// features/store/config.ts
export async function getCachedProductCatalog(): Promise<StoreProduct[]> {
'use cache'
cacheTag('store:products')
cacheLife('minutes')
const adapter = await getStoreAdapter()
return adapter.listProducts()
}
const result = await db().queryDocs({
collection: 'entities',
filters: [{ field: 'status', operator: 'eq', value: 'active' }],
orderBy: [{ field: 'createdAt', direction: 'desc' }],
pagination: { limit: 20, offset: 0 },
})
if (!result.success) throw result.error
// next.config.mjs (excerpt)
const nextConfig = {
reactStrictMode: true,
cacheComponents: true,
}