{"id":18493111,"url":"https://github.com/tomascuevas/evlun","last_synced_at":"2026-04-06T21:32:54.310Z","repository":{"id":56871354,"uuid":"526750860","full_name":"TomasCuevas/Evlun","owner":"TomasCuevas","description":"Evlun | Clon de twitter creado desde 0 por Tomás Cuevas","archived":false,"fork":false,"pushed_at":"2025-02-28T11:52:52.000Z","size":477,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-13T20:54:02.613Z","etag":null,"topics":["cloudinary","docker","express","mongodb","nextjs","nodejs","reactquery","responsive-design","social-media","tailwindcss","typescript"],"latest_commit_sha":null,"homepage":"https://evlun.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TomasCuevas.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-08-19T21:03:00.000Z","updated_at":"2025-02-28T11:53:15.000Z","dependencies_parsed_at":"2025-08-13T20:38:56.642Z","dependency_job_id":null,"html_url":"https://github.com/TomasCuevas/Evlun","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/TomasCuevas/Evlun","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasCuevas%2FEvlun","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasCuevas%2FEvlun/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasCuevas%2FEvlun/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasCuevas%2FEvlun/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TomasCuevas","download_url":"https://codeload.github.com/TomasCuevas/Evlun/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasCuevas%2FEvlun/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31491097,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-06T17:22:55.647Z","status":"ssl_error","status_checked_at":"2026-04-06T17:22:54.741Z","response_time":112,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cloudinary","docker","express","mongodb","nextjs","nodejs","reactquery","responsive-design","social-media","tailwindcss","typescript"],"created_at":"2024-11-06T13:12:45.643Z","updated_at":"2026-04-06T21:32:54.298Z","avatar_url":"https://github.com/TomasCuevas.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Evlun\n\nUna aplicación de red social tipo microblogging construida con un monorepo (cliente y servidor) que permite autenticación, publicación de posts, likes, guardados, seguidores/seguidos y configuración de perfil.\n\n---\n\n## ✨ Características\n\n- Autenticación con JWT (registro, login, verificación, reactivación/desactivación)\n- Feed de posts (global, seguidos, respuestas)\n- Likes y guardados\n- Búsqueda de usuarios y perfiles\n- Seguidores/seguidos\n- Configuración de cuenta (usuario, email, teléfono, país, género, contraseña, avatar/banner vía Cloudinary)\n- Subida de archivos con `express-fileupload`\n\n---\n\n## 🧱 Arquitectura del proyecto\n\nMonorepo con workspaces para cliente (Next.js) y servidor (Node/Express).\n\n```\nEvlun/\n  packages/\n    client/   # Next.js + React + Tailwind + React Query + Zustand\n    server/   # Express + TypeScript + Mongoose + JWT + Cloudinary\n```\n\n---\n\n## 🛠️ Stack técnico\n\n- Cliente: Next.js 12, React 18, TailwindCSS, React Query, Zustand, Formik, Yup, React Quill, Axios\n- Servidor: Node.js, Express, TypeScript, Mongoose (MongoDB), JWT, CORS, express-fileupload, Cloudinary\n- Base de datos: MongoDB (Docker)\n- Despliegue: Vercel (config para server incluida)\n\n---\n\n## 📦 Requisitos previos\n\n- Node.js 16+\n- Yarn (recomendado, los scripts del root usan `yarn --cwd`)\n- Docker (para MongoDB local)\n\n---\n\n## 🔐 Variables de entorno\n\nConfigura entornos por paquete.\n\n### Servidor (`packages/server/.env`)\n\n```\nPORT=4000\nMONGODB_URI=mongodb://localhost:27017/evlundb\nPRIVATE_SECRET_KEY_JWT=tu_clave_secreta\nCLOUDINARY_URL=cloudinary://\u003ckey\u003e:\u003csecret\u003e@\u003ccloud_name\u003e\n# Orígenes permitidos separados por espacios\nORIGINS=http://localhost:3000 http://localhost:4000\n```\n\n- `PORT`: puerto del servidor (por defecto 4000)\n- `MONGODB_URI`: cadena de conexión de MongoDB\n- `PRIVATE_SECRET_KEY_JWT`: clave para firmar JWT\n- `CLOUDINARY_URL`: credenciales de Cloudinary en formato de conexión\n- `ORIGINS`: dominios permitidos por CORS, separados por espacio\n\n### Cliente (`packages/client/.env.local`)\n\n```\nNEXT_PUBLIC_API_URI=http://localhost:4000/api\n```\n\n- El cliente usa `NEXT_PUBLIC_API_URI` para formar `baseURL` de Axios:\n  - `/auth`, `/post`, `/settings`, `/user`\n\n---\n\n## 🗄️ Base de datos local (Docker)\n\nEl `docker-compose.yaml` se encuentra en `packages/server/`.\n\n```bash\ncd packages/server\ndocker compose up -d\n```\n\nMongoDB quedará disponible en `mongodb://localhost:27017` y el proyecto usa la BD `evlundb`.\n\n---\n\n## 🚀 Instalación\n\nInstala dependencias desde la raíz usando Yarn (workspaces):\n\n```bash\nyarn install\n```\n\n---\n\n## 🧪 Scripts disponibles\n\nDesde la raíz del proyecto:\n\n```bash\n# Desarrollar\nnpm run dev:server    # Levanta el API (usa yarn internamente)\nnpm run dev:client    # Levanta el cliente Next.js\n\n# Cliente\nnpm run build:client  # Construye el cliente\nnpm run start:client  # Inicia cliente en modo producción\n```\n\nEn cada paquete:\n\n- Cliente (`packages/client`): `yarn dev | build | start | lint`\n- Servidor (`packages/server`): `yarn dev | build | start`\n\n---\n\n## ▶️ Ejecución en desarrollo\n\n1. Levanta MongoDB con Docker\n\n```bash\ncd packages/server\ndocker compose up -d\n```\n\n2. Configura variables de entorno en `packages/server/.env` y `packages/client/.env.local`\n\n3. Arranca servidor y cliente (en dos terminales):\n\n```bash\nnpm run dev:server\nnpm run dev:client\n```\n\n- API: `http://localhost:4000`\n- Web: `http://localhost:3000`\n\nAsegúrate de incluir ambos orígenes en `ORIGINS` del servidor.\n\n---\n\n## 🌐 Endpoints (overview)\n\nBase API: `http://localhost:4000/api`\n\n- Auth (`/auth`)\n\n  - POST `/create` – Registro\n  - POST `/login` – Login\n  - GET `/check` – Renovación de JWT (requiere header `evluntoken` y middleware `JWTValidation`)\n  - PUT `/deactivate` – Desactivar usuario (JWT)\n  - PUT `/reactivate` – Reactivar usuario\n\n- Post (`/post`)\n\n  - POST `/create` – Crear post (JWT)\n  - GET `/id/:id` – Obtener post por id\n  - GET `/user/:id` – Posts de un usuario\n  - GET `/answers/:postId` – Respuestas de un post\n  - GET `/all` – Feed global (JWT)\n  - GET `/following` – Feed seguidos (JWT)\n  - GET `/saved` – Guardados (JWT)\n  - GET `/saved/list` – IDs de posts guardados (JWT)\n  - PUT `/like/:postId` – Like/Unlike (JWT)\n  - PUT `/save/:postId` – Guardar/Quitar guardado (JWT)\n  - PUT `/report/:postId` – Reportar post (JWT)\n  - PUT `/delete/:postId` – Eliminar (soft delete) (JWT)\n\n- User (`/user`)\n\n  - GET `/username/:username` – Datos de usuario\n  - GET `/search?search=...\u0026skip=...` – Buscar usuarios\n  - PUT `/follow/:userId` – Seguir (JWT)\n  - PUT `/unfollow/:userId` – Dejar de seguir (JWT)\n  - GET `/following/:userId` – Listado de seguidos (JWT)\n  - GET `/followers/:userId` – Listado de seguidores (JWT)\n\n- Settings (`/settings`)\n  - PUT `/profile` – Actualizar perfil (JWT)\n  - PUT `/username` – Cambiar username (JWT)\n  - PUT `/phone` – Cambiar teléfono (JWT)\n  - PUT `/email` – Cambiar email (JWT)\n  - PUT `/country` – Cambiar país (JWT)\n  - PUT `/gender` – Cambiar género (JWT)\n  - PUT `/password` – Cambiar contraseña (JWT)\n\n### Autenticación\n\n- Header esperado por el backend: `evluntoken: \u003cJWT\u003e`\n- El cliente inyecta automáticamente este header desde la cookie `evluntoken` usando interceptores de Axios.\n- Tiempo de expiración del token: 2h.\n\n---\n\n## 🖼️ Media y uploads\n\n- Se utiliza Cloudinary (SDK v2). Configuración vía `CLOUDINARY_URL`.\n- Subidas gestionadas con `express-fileupload`.\n\n---\n\n## 🎨 UI/UX\n\n- TailwindCSS con tokens de color y breakpoint custom (`xs: 500px`).\n- Carga diferida e infinite scrolling mediante React Intersection Observer.\n- Editor enriquecido con React Quill.\n\n---\n\n## 🧰 Utilidades destacadas del cliente\n\n- Estado global con Zustand (`packages/client/store`)\n- React Query para fetching y cache de datos\n- Validación de formularios con Formik + Yup\n- Helpers de fechas y validaciones (`packages/client/helpers` y `packages/server/src/helpers`)\n\n---\n\n## ☁️ Despliegue\n\n- El servidor incluye `packages/server/vercel.json` para despliegue en Vercel (`@vercel/node`).\n- Variables a configurar en el provider: `MONGODB_URI`, `PRIVATE_SECRET_KEY_JWT`, `CLOUDINARY_URL`, `ORIGINS`.\n- El cliente (Next.js) puede desplegarse en Vercel, configurando `NEXT_PUBLIC_API_URI` apuntando al dominio del backend.\n\n---\n\n## 📜 Licencia\n\nISC © Tomas Cuevas\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomascuevas%2Fevlun","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftomascuevas%2Fevlun","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomascuevas%2Fevlun/lists"}