Cartas digitales con onda. Escribí algo que realmente querés decir.
Web app que genera cartas digitales como links compartibles. La data vive en el token de la URL (Base64 URL-safe), sin backend.
Deploy: Vercel (auto-deploy en cada push a main).
App en producción: ver el último deploy en el dashboard de Vercel.
Autor: Rodrigo Peralta
- Framework: Next.js 15 (App Router) + React 19
- Lenguaje: TypeScript
- Estilos: Tailwind CSS v4 + shadcn/ui (Radix UI)
- Animaciones: Motion (sucesor de Framer Motion)
- Build: Turbopack
- Deploy target: Vercel
- Node.js 20+
- npm 10+ (o pnpm/yarn)
npm install
npm run devLa app corre en http://localhost:3000.
| Script | Descripción |
|---|---|
npm run dev |
Dev server con Turbopack y HMR. |
npm run build |
Build de producción de Next.js (type-check durante el proceso). |
npm run start |
Sirve el build de producción. |
npm run lint |
Solo ESLint. |
npm run version:patch |
Bumpea 0.1.0 → 0.1.1 y crea tag anotado. |
npm run version:minor |
Bumpea 0.1.0 → 0.2.0 y crea tag anotado. |
npm run version:major |
Bumpea 0.1.0 → 1.0.0 y crea tag anotado. |
⚠️ Hay un pre-push hook configurado que correnpm run buildantes de cada push. Si falla, aborta.
src/
├── app/
│ ├── page.tsx # Composición de carta (formulario)
│ ├── layout.tsx # Root layout
│ ├── carta/[token]/
│ │ ├── page.tsx # Vista de carta recibida
│ │ ├── layout.tsx
│ │ └── opengraph-image.tsx # OG image dinámica por carta
│ ├── api/
│ │ └── version/
│ │ └── route.ts # GET /api/version (build metadata)
│ └── icon.svg # Favicon
├── components/
│ ├── CozyField.tsx # Input con label y error
│ ├── Envelope.tsx # Sobre animado
│ ├── Footer.tsx # Footer con autor + versión
│ ├── LetterPaper.tsx # Hoja de carta
│ └── SealButton.tsx # Botón con animación "sello"
└── lib/
├── letter.ts # encode/decode del token
├── utils.ts # cn() + helpers
└── version.ts # Lee APP_VERSION / APP_SHA / BUILD_TIME
- Usuario completa
Para,De,Mensaje,P.D.opcional. - Al sellar, la carta se encodea en Base64 URL-safe y se genera un link del tipo
/{dominio}/carta/{token}. - Al abrir el link, se decodifica el token, se anima el sobre y se muestra la carta.
- El botón Responder pre-rellena el formulario con
Para/Deinvertidos.
- Conventional Commits (sin Co-Authored-By).
- Sin
any. Si el tipo de Motion es conflictivo, se usaHTMLMotionPropsconOmit<..., "children">. - Sin backend por ahora — todo client-side.
- Semantic Versioning — bumpear con
npm run version:patch|minor|major. - CHANGELOG.md sigue Keep a Changelog — agregar entrada en cada release.
- Backlog MVP — features completadas.
- Backlog futuras — features pendientes + INFRA.
- Tasks originales — fases del proyecto.
- CHANGELOG.md — historial de releases.