Readme Español • English Readme
Aplicación web fullstack para gestión de tareas con autenticación de usuarios. Permite crear, editar, completar y eliminar tareas personales.
Este proyecto es parte de mi portafolio personal y está diseñado para demostrar mis habilidades en desarrollo web fullstack, incluyendo la creación de APIs REST con Django y el desarrollo de interfaces de usuario con React.
- Autenticación segura Registro e inicio de sesión con JWT (access + refresh tokens)
- Gestión completa de tareas Crear, editar, completar y eliminar en tiempo real
(CRUD) - Control de estado Marcar tareas como completadas o no completadas
- Grupos de tareas Organizar tareas en pestañas personalizadas con colores
- Asistente IA Sugerencias de tareas con IA integrada (OpenRouter / LLM)
- Rutas protegidas Acceso exclusivo para usuarios autenticados
- Validación robusta Formularios validados con esquemas
Zod - Diseño responsive Interfaz adaptable con
Tailwind CSSen todos los dispositivos - Estado global Manejo eficiente con
Zustand - Documentación API Swagger UI y ReDoc auto-generados con
drf-spectacular
FullStack-TodoList/
├── Makefile # Automatización de tareas (make help)
├── backend/ # API REST con Django
│ ├── config/ # Configuración principal
│ │ └── settings/ # Settings por entorno (development / production)
│ ├── apps/
│ │ ├── accounts/ # Autenticación y usuarios
│ │ ├── assistant/ # Asistente IA
│ │ ├── core/ # Utilidades compartidas
│ │ └── tasks/ # App de tareas (models, views, serializers)
│ └── scripts/ # Scripts de build y utilidades
├── frontend/ # App React
│ └── src/
│ ├── api/ # Cliente HTTP (Axios)
│ ├── components/ # Componentes reutilizables
│ ├── layouts/ # Layouts de página
│ ├── pages/ # Páginas principales
│ ├── store/ # Zustand store
│ └── utils/ # Esquemas Zod
└── scripts/ # Scripts de setup del entorno
| Tecnología | Uso |
|---|---|
| React 19 | Interfaz de usuario |
| Vite | Build tool y dev server |
| Tailwind CSS 4 | Estilos |
| Zustand | Estado global |
| React Router 7 | Navegación |
| React Hook Form + Zod | Validación de formularios |
| Axios | Cliente HTTP |
| Tecnología | Uso |
|---|---|
| Django 6 | Framework backend |
| Django REST Framework | API REST |
| SQLite / PostgreSQL | Base de datos |
make build-venv # Crear entorno virtual e instalar dependencias
make migrate # Aplicar migraciones
make runserver # Iniciar backend en http://localhost:8000
make frontend-install # Instalar dependencias del frontend
make frontend-dev # Iniciar frontend en http://localhost:5173Ejecuta
make helppara ver todos los comandos disponibles.
Backend
1 - Entrar al directorio y crear/activar el entorno virtual
cd backend
python -m venv .venv
source .venv/bin/activate # Linux/macOS
.venv\Scripts\Activate.ps1 # Windows2 - Instala las dependencias
pip install -e "../[dev]"3 - Aplicar las migraciones
python manage.py migrate4 - Iniciar el servidor
python manage.py runserverEl servidor estará disponible en http://localhost:8000
Frontend
1 - Entrar al directorio e instalar dependencias
cd frontend
npm install2 - Inicia el servidor de desarrollo
npm run devLa aplicación estará disponible en http://localhost:5173
Por defecto se usa development. Para cambiar a producción:
# Vía Makefile
make runserver DJANGO_ENV=production
# Manual (Linux/macOS)
export DJANGO_SETTINGS_MODULE=config.settings.production
# Manual (Windows PowerShell)
$env:DJANGO_SETTINGS_MODULE = "config.settings.production"Backend en Render
| Propiedad | Valor |
|---|---|
| Root | backend/ |
| Build command | ./scripts/build_backend.sh |
| Start command | gunicorn config.wsgi:application --bind 0.0.0.0:$PORT |
| Variable | Valor |
|---|---|
DJANGO_SETTINGS_MODULE |
config.settings.production |
SECRET_KEY |
tu-clave-secreta-muy-larga |
DEBUG |
False |
DATABASE_URL |
postgresql://usuario:contraseña@db.supabase.co:5432/postgres |
ALLOWED_HOSTS |
tu-backend.onrender.com |
CORS_ALLOWED_ORIGINS |
https://tu-frontend.pages.dev |
CSRF_TRUSTED_ORIGINS |
https://tu-backend.onrender.com |
Tip: Puedes usar
render.yamlen la raíz del proyecto para automatizar la configuración
Base de datos en Supabase
Para la base de datos, utilizaremos Supabase, que ofrece una solución PostgreSQL gestionada y fácil de integrar con Render.
- Crea un nuevo proyecto en Supabase
- Obtén la URL de conexión PostgreSQL desde Settings > Database
- Copia la URL en la variable
DATABASE_URLde tu servicio Render - Las migraciones se ejecutan automáticamente en
build.sh
python manage.py migrate # Se ejecuta en el buildFrontend en Cloudflare Pages
| Propiedad | Valor |
|---|---|
| Project root | frontend/ |
| Build command | npm run build |
| Output directory | dist |
| Variable | Valor |
|---|---|
VITE_API_URL |
https://tu-backend.onrender.com/api/ |
El archivo frontend/public/_redirects está configurado para redirigir todas las rutas a index.html, permitiendo que React Router maneje la navegación.
/* /index.html 200Backend Testing
El backend usa pytest y pytest-django para pruebas unitarias e integración.
# Ejecutar todas las pruebas del backend
source .venv/bin/activate
pytest backend/apps/tasks/tests/ -v
# Ejecutar pruebas con cobertura
pytest backend/apps/tasks/tests/ --cov=backend/apps/tasks --cov-report=html
# Ejecutar pruebas de un archivo específico
pytest backend/apps/tasks/tests/test_models.py -v
# Ejecutar tests que coincidan con un patrón
pytest backend/apps/tasks/tests/ -k "test_creation" -vbackend/apps/tasks/
├── tests/
│ ├── __init__.py
│ ├── test_models.py # Pruebas del modelo Task (11 tests)
│ ├── test_serializers.py # Pruebas de serializers (11 tests)
│ └── test_views.py # Pruebas de endpoints API (15 tests)
├── models.py
├── serializers.py
└── views.py
| Componente | Cobertura | Tests | Estado |
|---|---|---|---|
| Tasks Models | 100% | 11 | ✅ Completo |
| Tasks Serializers | 100% | 11 | ✅ Completo |
| Tasks Views | 100% | 15 | ✅ Completo |
| Total Tasks App | 100% | 37 | ✅ Completo |
Informe de cobertura completo: /htmlcov/index.html
from django.test import TestCase
from django.contrib.auth.models import User
from apps.tasks.models import Task
class TaskModelTests(TestCase):
def setUp(self):
self.user = User.objects.create_user(
username="testuser",
email="test@example.com",
password="testpass123"
)
def test_task_creation(self):
"""Verifica que se puede crear una tarea correctamente"""
task = Task.objects.create(
title="Test Task",
description="Test Description",
user=self.user
)
self.assertEqual(task.title, "Test Task")
self.assertFalse(task.completed)Frontend Testing
El frontend usa Vitest para pruebas unitarias de componentes React.
cd frontend
# Ejecutar todas las pruebas
npm run test:run
# Ejecutar pruebas en modo watch (re-ejecuta al cambiar archivos)
npm run test
# Ejecutar con cobertura
npm run test:run
# Ejecutar tests que coincidan con un patrón
npm run test:run -- -t "TaskCard"frontend/src/
├── components/
│ └── __tests__/
│ ├── TaskCard.test.jsx # Pruebas del componente TaskCard (9 tests)
│ └── Spinner.test.jsx # Pruebas del componente Spinner (6 tests)
└── utils/
└── __tests__/
└── schema.test.js # Pruebas de validación Zod (15 tests)
| Componente | Cobertura | Tests | Estado |
|---|---|---|---|
| TaskCard | 100% | 9 | ✅ Completo |
| Spinner | 100% | 6 | ✅ Completo |
| Validation Schemas | 95% | 15 | ✅ Completo |
| Total Frontend | 97.61% | 30 | ✅ Completo |
Informe de cobertura: /frontend/coverage/index.html
import { describe, it, expect } from 'vitest'
import { render, screen } from '@testing-library/react'
import { TaskCard } from '../TaskCard'
describe('TaskCard Component', () => {
it('renders task title correctly', () => {
const task = {
id: 1,
title: 'Test Task',
completed: false
}
render(<TaskCard task={task} />)
expect(screen.getByText('Test Task')).toBeInTheDocument()
})
it('shows completed state', () => {
const task = {
id: 1,
title: 'Completed Task',
completed: true
}
render(<TaskCard task={task} />)
const checkbox = screen.getByRole('checkbox')
expect(checkbox).toBeChecked()
})
})El archivo frontend/vitest.config.ts incluye:
export default defineConfig({
test: {
globals: true,
environment: 'happy-dom',
setupFiles: ['./src/test/setup.ts'],
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html', 'lcov'],
},
},
})| Stack | Framework | Pruebas | Cobertura | Status |
|---|---|---|---|---|
| Backend | pytest | 37 | 100% | ✅ |
| Frontend | Vitest | 30 | 97.61% | ✅ |
| Total | - | 67 | 97% | ✅ |
Todos los tests pasan correctamente en cada ejecución.
Documentación interactiva disponible en
/api/docs/(Swagger) y/api/redoc/(ReDoc)
| Método | Endpoint | Descripción |
|---|---|---|
| POST | /api/users/ |
Registro de usuario |
| GET | /api/users/me/ |
Datos del usuario actual |
| POST | /api/token/ |
Obtener tokens JWT (login) |
| POST | /api/token/refresh/ |
Refrescar access token |
| GET | /api/tasks/ |
Listar tareas |
| POST | /api/tasks/ |
Crear tarea |
| PUT | /api/tasks/{id}/ |
Actualizar tarea |
| DELETE | /api/tasks/{id}/ |
Eliminar tarea |
| GET | /api/groups/ |
Listar grupos |
| POST | /api/groups/ |
Crear grupo |
| PATCH | /api/groups/{id}/ |
Actualizar grupo |
| DELETE | /api/groups/{id}/ |
Eliminar grupo |
| PATCH | /api/groups/reorder/ |
Reordenar grupos |
| POST | /api/ai/suggest-task/ |
Sugerencia de tarea con IA |
| GET | /api/schema/ |
Esquema OpenAPI |
| GET | /api/docs/ |
Swagger UI |
| GET | /api/redoc/ |
ReDoc |
Este proyecto está bajo la Licencia MIT. Consulta el archivo LICENSE para más detalles.
En colaboración con @DMsuDev
