made by fixter.org
Antes de iniciar el proyecto asegurate de ejecutar:
npx prisma generate
Inicia el proyecto ejecutando:
npm dev
EasyBits soporta la publicación de tres tipos de curso:
- Pre-grabado
- En vivo y
- Por correo
Cada uno de estos modos tendrá un comportamiento y un set de features diferente.
enum AssetType {
VOD_COURSE
EMAIL_COURSE
WEBINAR
EBOOK
DOWNLOADABLE
}
model Asset {
id String @id @default(auto()) @map("_id") @db.ObjectId
type AssetType @default(DOWNLOADABLE)
// ...
}Constantes definidas. El tipo WEBINAR puede aún mutar en el transcurso del desarrollo.
- Ahora la subida de archivos a S3 es concurrente y en segundo plano usando Effect y react-hook-multipart.
- El estado y progreso de todas las subidas se maneja globalmente con un contexto React (
UploadsContext). - Puedes ver y controlar el progreso desde cualquier parte de la app, incluso si navegas entre rutas.
- Hay un stacker flotante en /dash/assets que muestra el progreso de subidas activas.
- Beneficios: mejor UX, control total, reusabilidad y robustez.
- Usa el custom hook
useUploads()para acceder al estado y acciones de subidas desde cualquier componente. - El provider
UploadsProviderenvuelve la app y mantiene el estado global de subidas. - Effect se usa para manejar la lógica asíncrona y la concurrencia de las subidas, permitiendo lanzar, cancelar y controlar tareas de subida de forma declarativa y robusta.
// En tu root/layout
<UploadsProvider>
<App />
</UploadsProvider>;
// En cualquier componente
import { useUploads } from "~/context";
const { uploads, uploadFile } = useUploads();
// Subir un archivo (por ejemplo, desde un input)
<input
type="file"
onChange={(e) => {
const file = e.target.files?.[0];
if (file) uploadFile(file, "assetId");
}}
/>;
// Mostrar progreso
uploads.map((u) => (
<div key={u.id}>
{u.file.name}: {u.progress}%
</div>
));El blog usa archivos MDX como rutas directas para evitar duplicación de datos y problemas en producción.
- Crear archivo MDX en
app/content/blog/YYYY-MM-DD-nombre-post.mdx - Actualizar 3 lugares:
app/routes/blog.tsx(lista)app/routes/blog.$slug.tsx(post individual)react-router.config.ts(prerendering)
- ✅ Sin duplicación de datos
- ✅ Funciona en producción (Fly.io)
- ✅ Prerendering eficiente
- ✅ SEO optimizado con meta tags automáticos
Ahora todas las operaciones críticas con Stripe usan la librería Effect (ts) para controlar los errores de forma funcional y predecible. Las funciones que interactúan con Stripe devuelven un resultado estructurado: { ok: true, data } en caso de éxito, o { ok: false, error } en caso de error. Así, el backend nunca lanza errores inesperados y el código que consume estas funciones solo revisa la propiedad ok para saber si todo salió bien.
Esto permite que el frontend reciba mensajes de error claros y controlados, sin stacktraces ni detalles internos, facilitando la experiencia de usuario y el debugging. Además, los logs de Stripe quedan centralizados y es fácil extender este patrón a otros servicios de terceros en el futuro.