CleanFrame
A personal home screen for Samsung The Frame. A starting point to fork and adapt.
Donde los dominicanos que llegan encuentran a su gente: vivienda revisada, guías de trámites en español y verificación real.
Translation pending
LifestyleTypeScript · PLpgSQLGitHub @developers-insightsOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗Red social white-label multi-tenant para comunidades latinas en EE. UU. Cada tenant es un dominio propio con su marca (logo, color, módulos), sobre una única base de código y una única base de datos con aislamiento por RLS. Tenant piloto: dominicanos (Queens, NY).
El corazón del producto es el wedge de vivienda verificada anti-estafa: avisos de alquiler con Trust Score, Escudo Anti-Estafa (verificador + reportes comunitarios), mensajería con contacto protegido y guías SEO para recién llegados.
| Capa | Tecnología |
|---|---|
| Framework | Next.js 16 (App Router, src/, TypeScript estricto) |
| Estilos | Tailwind CSS v4 (tokens en globals.css vía @theme) |
| DB / Auth / Storage / Realtime | Supabase (Postgres 17, RLS FORCE en 23+ tablas) |
| Pagos | Stripe (Checkout + Identity + webhooks) |
| Resend | |
| IA | OpenAI (moderación omni-moderation + RAG con embeddings) |
| Observabilidad | Sentry |
| PWA | Serwist (service worker, offline) |
| Tests | Vitest + Testing Library |
Documentos rectores: docs/ARQUITECTURA.md (contrato técnico), docs/PLAN_MAESTRO.md (estrategia), docs/PROGRESS.md (estado), docs/investigacion/13-diseno-ux-premium.md (design system — rige tal cual).
npm install
cp .env.example .env.local # completar BLOQUE A como mínimo (ver docs/SETUP-ENV.md)
npm run dev # http://localhost:3000 (?t=<slug> para cambiar de tenant)
| Script | Qué hace |
|---|---|
npm run dev | Servidor de desarrollo (Turbopack; service worker deshabilitado en dev) |
npm run build | Build de producción — next build --webpack (Serwist necesita webpack para emitir public/sw.js) |
npm run start | Sirve el build de producción |
npm run test | Tests con Vitest |
npm run lint / npm run typecheck | ESLint / tsc --noEmit |
npm run check:rls | Enumerador RLS: verifica que ninguna tabla quede sin políticas (correr tras cada migración) |
npm run db:migrate | Aplica migraciones de supabase/migrations/ |
npm run db:seed | Siembra tenants demo + contenido de ejemplo |
npm run rag:embed | Genera embeddings del contenido para el asistente RAG (requiere OPENAI_API_KEY; lo agrega el módulo de IA) |
src/
├─ middleware.ts # Resolución de tenant por dominio + refresh de sesión Supabase
├─ app/
│ ├─ (marketing)/ # Landing pública + guías SEO
│ ├─ (auth)/ # Entrar, registro, onboarding
│ ├─ (app)/ # App autenticada: feed, propiedades, escudo, mensajes, perfil…
│ ├─ admin/ # Paneles global / dominio / moderación
│ └─ api/ # Webhooks (Stripe) + crons (protegidos con CRON_SECRET)
├─ components/ # ui/ (design system), trust/, listings/, feed/, shell/…
├─ lib/ # supabase/, tenant/, config/services.ts (degradación), rate-limit/, i18n/…
supabase/migrations/ # SQL versionado (RLS FORCE, triggers, RPCs)
scripts/ # rls-enumerator, seed, apply-migrations, generate-icons
Todo está documentado en .env.example (por bloques: A = imprescindible, B = antes del primer usuario real, C = puede esperar) y en docs/SETUP-ENV.md con el paso a paso de cada servicio.
Reglas de oro:
NEXT_PUBLIC_* se expone al navegador → jamás un secreto ahí.SUPABASE_SERVICE_ROLE_KEY, STRIPE_SECRET_KEY, OPENAI_API_KEY viven solo en el servidor.src/lib/config/services.ts): la feature muestra un estado premium "muy pronto", nunca un error crudo.tenant_id del JWT es la frontera real de aislamiento. npm run check:rls lo verifica.src/lib/rate-limit/, in-memory; migrar a Upstash con multi-instancia).next.config.ts: HSTS, X-Frame-Options: DENY, CSP (hoy en Report-Only; pasa a enforcing tras validar en staging).Según Plan Maestro §5.2 / §14.4 — el repo llega "listo para este gate", pero el gate lo cruza un humano:
package.json → next build --webpack, no lo pises)..env.example (Production + Preview).dominicanos.com) al proyecto — el middleware resuelve el tenant por Host.https://<dominio>/api/webhooks/stripe y cargar STRIPE_WEBHOOK_SECRET.api/cron/* exigen Authorization: Bearer ${CRON_SECRET}.| Slug | Dominio prod | Uso |
|---|---|---|
dominicanos | dominicanos.com | Tenant piloto (default en dev) |
comunidadlatina | comunidadlatina.com | Segundo tenant para probar white-label |
En dev: http://localhost:3000?t=comunidadlatina (queda en cookie cl-tenant).