Tip
Quick Setup Note: This project includes enviroment variables and configures instructions into .env.example file for development and testing environments, (remember all enviroment values is with your credentials). This facilitates rapid deployment and ensures the test suite runs out-of-the-box without extra security overhead.
A professional fullstack application built with React, Redux, Express, Sequelize, and PostgreSQL.
This project features a robust CI/CD pipeline and a comprehensive testing suite, demonstrating scalable API design, cinematic UI, and production-ready architecture.
🔗 https://gallerymovies.netlify.app
🔗 https://moviesapp-lc0z.onrender.com
🔗 https://documenter.getpostman.com/view/48309056/2sB3dLUX82
What does the "passing" badge at the beginning of this project mean? This project implements Continuous Integration (CI/CD). This means that every time a code change is made, an automated system executes 19+ security and functional tests.
- Green Badge (Passing): The code is stable, secure, and production-ready.
- Red Badge (Failing): Indicates an error was detected before it could affect the end user.
This ensures that GalleryMovies consistently maintains professional quality standards.
erDiagram
MOVIE ||--o{ GENRE_MOVIES : "belongs to"
GENRE ||--o{ GENRE_MOVIES : "has"
MOVIE ||--o{ ACTOR_MOVIES : "features"
ACTOR ||--o{ ACTOR_MOVIES : "stars in"
MOVIE ||--o{ DIRECTOR_MOVIES : "directed by"
DIRECTOR ||--o{ DIRECTOR_MOVIES : "directs"
MOVIE {
string name
string image
text synopsis
int release_year
}
ACTOR {
string first_name
string last_name
string nationality
}
DIRECTOR {
string first_name
string last_name
string nationality
}
GENRE {
string name
}
- Complex Modeling: Implement many-to-many relationships using Sequelize ORM.
- Advanced Logic: Dynamic calculation of movie associations and cinematic data filtering.
- Quality Assurance: Achieve 100% core business logic coverage through automated integration tests.
- Seamless Integration: Connect a React + Redux frontend with a secure Express backend.
- Cinematic UI: Interface inspired by top-tier streaming platforms.
- Smart Relationships: Assign multiple Actors, Directors, and Genres to any Movie.
- Security First: Implementation of Helmet, CORS, and environment variable management.
- Developer Friendly: Reproducible test scripts and detailed bilingual documentation.
The reliability of GalleryMovies is backed by an automated testing workflow. Using Jest and Supertest, the project implements 19+ strategic tests covering:
- Full CRUD Operations: Actors, Genres, Directors, and Movies.
- Relationship Integrity: Validating many-to-many assignments (Actors-to-Movie, Genres-to-Movie).
- Automated Workflow: Every
pushorpull requesttriggers the GitHub Actions pipeline, ensuring code stability before deployment.
To run the tests locally:
npm test| Frontend | Backend | Testing & CI/CD | Database | Security & Middleware |
|---|---|---|---|---|
| React 18 | Node.js | Jest | PostgreSQL | Helmet |
| Redux Toolkit | Express | Supertest | Render (Deployment) | CORS |
| React Router | Sequelize ORM | GitHub Actions | Netlify (Frontend) | |
| Vite | Morgan | NeonDB | ||
| Bootstrap | Postman | |||
| Bootswatch |
| Method | Endpoint | Function |
|---|---|---|
| GET | /movies |
Returns all movies with all genres, actors, and directors |
| POST | /movies |
Create a new movie |
| GET | /movies/:id |
Return a movie by id searched |
| PUT | /movies/:id |
Update a movie by id |
| DELETE | /movies/:id |
Remove a movie by id |
Note: Standard CRUD enpoints for all models equally applicable for genres, actors and directors.
| Model | Fields |
|---|---|
| Genres | id, name |
| Actors | id, first_name, last_name, nationality, image, birthday |
| Directors | id, first_name, last_name, nationality, image, birthday |
| Movies | id, name, image, synopsis, release_year |
The following endpoints are tested:
GET /actors– Retrieve all actorsPOST /actors– Create a new actorDELETE /actors/:id– Delete an actor by IDPUT /actors/:id– Update an actor by ID
GET /genres– Retrieve all genresPOST /genres– Create a new genreDELETE /genres/:id– Delete a genre by IDPUT /genres/:id– Update a genre by ID
GET /directors– Retrieve all directorsPOST /directors– Create a new directorDELETE /directors/:id– Delete a director by IDPUT /directors/:id– Update a director by ID
GET /movies– Retrieve all moviesPOST /movies– Create a new movieDELETE /movies/:id– Delete a movie by IDPUT /movies/:id– Update a movie by IDPOST /movies/:id/actors– Assign actors to a moviePOST /movies/:id/directors– Assign directors to a moviePOST /movies/:id/genres– Assign genres to a movie
"scripts": {
"dev": "node --watch --env-file=.env src/server.js",
"start": "node src/server.js",
"test": "node --env-file=.env ./node_modules/jest/bin/jest.js"
}- Fullstack Development: integrating frontend (React + Redux + Vite) with backend (Express + Sequelize + PostgreSQL).
- API Design & RESTful Practices: building CRUD endpoints and managing entity relationships.
- Database Modeling: using Sequelize ORM to define models and relationships in PostgreSQL.
- Security & Best Practices: configuring CORS (for educational and portfolio purposes, CORS is open to all origins. This configuration allows public access from any frontend during development and testing.), Helmet, and handling environment variables.
- Deployment Skills: deploying backend on Render and frontend on Vercel/Netlify.
- Version Control & Collaboration: GitHub usage with
.gitignore,.env.example, and bilingual documentation. - UI/UX Design: building a cinematic interface with React-Bootstrap and Bootswatch.
- Professional Presentation: structured README, bilingual content, clear instructions, and demo links.
📁 MOVIES-APP
| ├── 📁 .github
│ | └── 📁 workflows/
│ | | └── main.yml
| ├── 📁 movies-app-backend
│ | └── 📁 node_modules/
│ | └── 📁 src/
| │ | └── 📁 controllers/
│ | | | └── actor.controllers.js
│ | | | └── director.controllers.js
│ | | | └── genre.controllers.js
│ | | | └── movie.controllers.js
| │ | └── 📁 db/
│ | | | └── connect.js
| │ | └── 📁 env/
│ | | | └── index.js
| │ | └── 📁 middlewares/
│ | | | └── catchError.js
│ | | | └── errorHandler.js
| │ | └── 📁 models/
│ | | | └── actor.model.js
│ | | | └── director.model.js
│ | | | └── genre.model.js
│ | | | └── movie.model.js
| │ | └── 📁 routes/
| │ | | └── 📁 api/
│ | | | | └── actor.routes.js
│ | | | | └── director.routes.js
│ | | | | └── genre.routes.js
│ | | | | └── index.js
│ | | | | └── movie.routes.js
│ | | | └── index.js
│ | | └── app.js
│ | | └── server.js
│ | └── 📁 tests/
│ | | └── actors.test.js
│ | | └── directors.test.js
│ | | └── genres.test.js
│ | | └── movies.test.js
│ | | └── setup.js
| | └── .env
| | └── .env.example
| | └── jest.config.js
| | └── package-lock.json
| | └── package.json
| ├── 📁 movies-app-frontend
│ | └── 📁 node_modules/
│ | └── 📁 src/
| │ | └── 📁 assets/
| │ | └── 📁 components/
| │ | | └── 📁 Actors/
│ | | | | └── ActorCard.jsx
│ | | | | └── ActorsForm.jsx
| │ | | └── 📁 Directors/
│ | | | | └── DirectorCard.jsx
│ | | | | └── DirectorForm.jsx
| │ | | └── 📁 Genres/
│ | | | | └── GenreItem.jsx
│ | | | | └── GenresModal.jsx
| │ | | └── 📁 Movies/
│ | | | | └── MovieCard.jsx
│ | | | └── ButtonsEditDelete.jsx
│ | | | └── EmptyImg.jsx
│ | | | └── index.js
│ | | | └── ItemsSelect.jsx
│ | | | └── LoadingScreen.jsx
│ | | | └── ModalForm.jsx
│ | | | └── NavBar.jsx
│ | | | └── Notification.jsx
│ | | | └── UniversalPagination.jsx
| │ | └── 📁 pages/
| │ | | └── Actors.jsx
| │ | | └── Directors.jsx
| │ | | └── Home.jsx
| │ | | └── index.js
| │ | | └── MovieDetail.jsx
| │ | | └── MovieForm.jsx
| │ | └── 📁 store/
| │ | | └── 📁 slices/
│ | | | | └── actors.slice.js
│ | | | | └── app.slice.js
│ | | | | └── directors.slice.js
│ | | | | └── genres.slice.js
│ | | | | └── movies.slice.js
| │ | | └── index.js
| │ | └── 📁 utils/
| │ | | └── axios.js
| │ | | └── formatDate.js
| │ | | └── getOneProperty.js
| │ | | └── listWithCommas.js
| │ | | └── searchAndFormatMovie.js
| │ | └── App.css
| │ | └── App.jsx
| │ | └── loading-screen.css
| │ | └── main.jsx
│ | └── .env
│ | └── .env.example
│ | └── index.html
│ | └── package-lock.json
│ | └── package.json
│ | └── vite.config.js
| └── .gitignore
| └── README.md- Clone this repository:
git clone https://github.com/Clic-stack/MoviesApp-FullStack-Project.git- Change directory movies-app-backend:
cd movies-app-backend- Install dependences:
npm install- Configure enviroment variables:
- Changes file name
.env.exampleto.env - Modify the necessary variable values.
- Example configuration:
PORT=4000 # -> Change for your server
DATABASE_URL=postgres://user:password@localhost:5432/movies
CORS_ORIGIN=http://localhost:5173 # -> Frontend URL (leave blank if not applicable)💡 Quick Setup Note: This project includes enviroment variables and configures instructions into .env.example file (remember all enviroment values is with your credentials) for development and testing environments. This facilitates rapid deployment and ensures the test suite runs out-of-the-box without extra security overhead.
- Run Tests:
npm test- Run Individual Test:
npm test name_file.test.js- Run de server in development mode:
npm run dev- Change directory to movies-app-frontend:
cd movies-app-frontend- Install dependencies:
npm install- Configure environment variables using
.env.examplefile and change name for.env:
VITE_API_URL=http://localhost:4000/api/v1Note: Ensure this matches your Backend URL.
- Run the development server:
npm run devDeveloped by Clio Salgado. Focused on building reliable, data-driven fullstack solutions with professional testing standards.
🔽 Versión en Español 🔽
Tip
Nota para Configuración Rápida: Este proyecto incluye variables de entorno e instrucciones de configuración en el archivo .env.example para entornos de desarrollo y pruebas, (recuerda que todos los valores deben corresponder a tus propias credenciales). Esto facilita un despliegue rápido y garantiza que la suite de pruebas funcione de inmediato (out-of-the-box) sin configuraciones de seguridad adicionales.
Aplicación fullstack profesional construída con React, Redux, Express, Sequelize y PostgreSQL.
Este proyecto implementa un pipeline CI/CD robusto y una suite de pruebas integral y completa, mostrando una interfaz cinemática, diseño de APIs escalables y arquitectura lista para producción.
🔗 https://gallerymovies.netlify.app
🔗 https://moviesapp-lc0z.onrender.com
🔗 https://documenter.getpostman.com/view/48309056/2sB3dLUX82
¿Qué significa el sello "passing" al inicio de este proyecto? Este proyecto utiliza Integración Continua (CI/CD). Significa que cada vez que realizo un cambio en el código, un sistema automatizado ejecuta más de 19 pruebas de seguridad y funcionamiento.
- Sello Verde (Passing): El código es estable, seguro y está listo para producción.
- Sello Rojo (Failing): Indica un error detectado antes de que afecte al usuario final.
Esto asegura que GalleryMovies mantenga estándares de calidad profesional de forma constante.
erDiagram
MOVIE ||--o{ GENRE_MOVIES : "belongs to"
GENRE ||--o{ GENRE_MOVIES : "has"
MOVIE ||--o{ ACTOR_MOVIES : "features"
ACTOR ||--o{ ACTOR_MOVIES : "stars in"
MOVIE ||--o{ DIRECTOR_MOVIES : "directed by"
DIRECTOR ||--o{ DIRECTOR_MOVIES : "directs"
MOVIE {
string name
string image
text synopsis
int release_year
}
ACTOR {
string first_name
string last_name
string nationality
}
DIRECTOR {
string first_name
string last_name
string nationality
}
GENRE {
string name
}
- Modelado complejo de datos: Implementación de bases de datos relacionales muchos a muchos usando el ORM de Sequelize.
- Lógica de negocio avanzada: Cálculo dinámico de asociaciones de películas y filtrado de datos cinematográficos.
- Aseguramiento de la Calidad: Logró total de una cobertura del 100% de la lógica de negocio principal mediante pruebas de integración automatizadas.
- Integración fluida y sin fisuras: Conexión de frontend en React + Redux con backend seguro en Express.
- Interfaz Cinemática: Interfaz inspirada en las principales plataformas de streaming.
- Relaciones Inteligentes: Asignación de múltiples Actores, Directores y Géneros a cualquier Película.
- Seguridad ante todo: Implementación de Helmet, CORS y gestión de variables de entorno.
- Optimizado para Desarrolladores: Scripts de prueba reproducibles y documentación bilingüe detallada.
##🧪 Suite de Pruebas Profesional (CI/CD) La confiabilidad de GalleryMovies está respaldada por un flujo de trabajo de pruebas automatizadas. Utilizando Jest y Supertest, el proyecto implementa más de 19 pruebas estratégicas que cubren:
- Operaciones CRUD Completas: Actores, Géneros, Directores y Películas.
- Integridad de Relaciones: Validación de asignaciones muchos-a-muchos (Actores a Película, Géneros a Película).
- Flujo de Trabajo Automatizado: Cada
pushopull requestactiva el pipeline de GitHub Actions, garantizando la estabilidad del código antes del despliegue.
Para correr los test localmente copia y pega el siguiente comando:
npm test| Frontend | Backend | Testing e Integración Continua (CI/CD) | Base de Datos | Seguridad y Middlewares |
|---|---|---|---|---|
| React 18 | Node.js | Jest | PostgreSQL | Helmet |
| Redux Toolkit | Express | Supertest | Render (Deployment) | CORS |
| React Router | Sequelize ORM | GitHub Actions | Netlify (Frontend) | |
| Vite | Morgan | NeonDB | ||
| Bootstrap | Postman | |||
| Bootswatch |
| Método | Endpoint | Función |
|---|---|---|
| GET | /movies |
Devuelve todas las películas con todos los géneros, actores y directores |
| POST | /movies |
Crea una nueva película |
| GET | /movies/:id |
Devuelve una película por id |
| PUT | /movies/:id |
Actualiza una película por id |
| DELETE | /movies/:id |
Elimina una película por id |
Nota: Los endpoints CRUD estándar para todos los modelos son igualmente aplicables a géneros (genres), actores (actors) y directores (directors).
| Modelo | Campos |
|---|---|
| Genres | id, name |
| Actors | id, first_name, last_name, nationality, image, birthday |
| Directors | id, first_name, last_name, nationality, image, birthday |
| Movies | id, name, image, synopsis, release_year |
Se testearon los siguientes endpoints:
GET /actors– Obtener todos los actoresPOST /actors– Crear un nuevo actorDELETE /actors/:id– Eliminar un actor por IDPUT /actors/:id– Actualizar un actor por ID
GET /genres– Obtener todos los génerosPOST /genres– Crear un nuevo géneroDELETE /genres/:id– Eliminar un género por IDPUT /genres/:id– Actualizar un género por ID
GET /directors– Obtener todos los directoresPOST /directors– Crear un nuevo directorDELETE /directors/:id– Eliminar un director por IDPUT /directors/:id– Actualizar un director por ID
GET /movies– Obtener todas las películasPOST /movies– Crear una nueva películaDELETE /movies/:id– Eliminar una película por IDPUT /movies/:id– Actualizar una película por IDPOST /movies/:id/actors– Asiganr actores a una películaPOST /movies/:id/directors– Asignar directores a una películaPOST /movies/:id/genres– Asignar géneros a una película
"scripts": {
"dev": "node --watch --env-file=.env src/server.js",
"start": "node src/server.js",
"test": "node --env-file=.env ./node_modules/jest/bin/jest.js"
}- Desarrollo Full-Stack: Integración de frontend (React + Redux + Vite) con un backend robusto (Express + Sequelize + PostgreSQL).
- Diseño de APIs y Prácticas RESTful: Construcción de endpoints CRUD y gestión avanzada de relaciones entre entidades.
- Modelado de Bases de Datos: Uso de Sequelize ORM para definir modelos relacionales y asociaciones complejas en PostgreSQL.
- Seguridad y Mejores Prácticas: Configuración de Helmet, gestión de variables de entorno y control de CORS (configurado para permitir acceso público durante la fase de desarrollo y pruebas en el portafolio).
- Habilidades de Despliegue (Deployment): Despliegue del backend en Render y del frontend en plataformas como Vercel o Netlify.
- Control de Versiones y Colaboración: Uso profesional de GitHub con archivos
.gitignore,.env.example, y documentación técnica bilingüe. - Diseño UI/UX: Creación de una interfaz cinematográfica fluida utilizando React-Bootstrap y Bootswatch.
- Presentación Profesional: Estructuración de un README detallado, contenido bilingüe, instrucciones claras y enlaces directos a la demo.
📁 MOVIES-APP
| ├── 📁 .github
│ | └── 📁 workflows/
│ | | └── main.yml
| ├── 📁 movies-app-backend
│ | └── 📁 node_modules/
│ | └── 📁 src/
| │ | └── 📁 controllers/
│ | | | └── actor.controllers.js
│ | | | └── director.controllers.js
│ | | | └── genre.controllers.js
│ | | | └── movie.controllers.js
| │ | └── 📁 db/
│ | | | └── connect.js
| │ | └── 📁 env/
│ | | | └── index.js
| │ | └── 📁 middlewares/
│ | | | └── catchError.js
│ | | | └── errorHandler.js
| │ | └── 📁 models/
│ | | | └── actor.model.js
│ | | | └── director.model.js
│ | | | └── genre.model.js
│ | | | └── movie.model.js
| │ | └── 📁 routes/
| │ | | └── 📁 api/
│ | | | | └── actor.routes.js
│ | | | | └── director.routes.js
│ | | | | └── genre.routes.js
│ | | | | └── index.js
│ | | | | └── movie.routes.js
│ | | | └── index.js
│ | | └── app.js
│ | | └── server.js
│ | └── 📁 tests/
│ | | └── actors.test.js
│ | | └── directors.test.js
│ | | └── genres.test.js
│ | | └── movies.test.js
│ | | └── setup.js
| | └── .env
| | └── .env.example
| | └── jest.config.js
| | └── package-lock.json
| | └── package.json
| ├── 📁 movies-app-frontend
│ | └── 📁 node_modules/
│ | └── 📁 src/
| │ | └── 📁 assets/
| │ | └── 📁 components/
| │ | | └── 📁 Actors/
│ | | | | └── ActorCard.jsx
│ | | | | └── ActorsForm.jsx
| │ | | └── 📁 Directors/
│ | | | | └── DirectorCard.jsx
│ | | | | └── DirectorForm.jsx
| │ | | └── 📁 Genres/
│ | | | | └── GenreItem.jsx
│ | | | | └── GenresModal.jsx
| │ | | └── 📁 Movies/
│ | | | | └── MovieCard.jsx
│ | | | └── ButtonsEditDelete.jsx
│ | | | └── EmptyImg.jsx
│ | | | └── index.js
│ | | | └── ItemsSelect.jsx
│ | | | └── LoadingScreen.jsx
│ | | | └── ModalForm.jsx
│ | | | └── NavBar.jsx
│ | | | └── Notification.jsx
│ | | | └── UniversalPagination.jsx
| │ | └── 📁 pages/
| │ | | └── Actors.jsx
| │ | | └── Directors.jsx
| │ | | └── Home.jsx
| │ | | └── index.js
| │ | | └── MovieDetail.jsx
| │ | | └── MovieForm.jsx
| │ | └── 📁 store/
| │ | | └── 📁 slices/
│ | | | | └── actors.slice.js
│ | | | | └── app.slice.js
│ | | | | └── directors.slice.js
│ | | | | └── genres.slice.js
│ | | | | └── movies.slice.js
| │ | | └── index.js
| │ | └── 📁 utils/
| │ | | └── axios.js
| │ | | └── formatDate.js
| │ | | └── getOneProperty.js
| │ | | └── listWithCommas.js
| │ | | └── searchAndFormatMovie.js
| │ | └── App.css
| │ | └── App.jsx
| │ | └── loading-screen.css
| │ | └── main.jsx
│ | └── .env
│ | └── .env.example
│ | └── index.html
│ | └── package-lock.json
│ | └── package.json
│ | └── vite.config.js
| └── .gitignore
| └── README.md- Clona este repositorio:
git clone https://github.com/Clic-stack/MoviesApp-FullStack-Project.git- Cambia a la carpeta movies-app-backend:
cd movies-app-backend- Instala dependencias:
npm install- Configura variables de entorno:
- Cambia el nombre del archivo
.env.examplea.env - Modifica los valores de las variables.
- Ejemplo de configuración:
PORT=4000 # -> Change for your server
DATABASE_URL=postgres://user:password@localhost:5432/movies
CORS_ORIGIN=http://localhost:5173 # -> Frontend URL (leave blank if not applicable)💡 Nota para Configuración Rápida: Este proyecto incluye variables de entorno e instrucciones de configuración en el archivo .env.example (recuerda que todos los valores deben corresponder a tus propias credenciales) para entornos de desarrollo y pruebas. Esto facilita un despliegue rápido y garantiza que la suite de pruebas funcione de inmediato (out-of-the-box) sin configuraciones de seguridad adicionales.
- Corre los tests:
npm test- Corre el test individualmente:
npm test name_file.test.js- Corre el servidor:
npm run dev- Cambia la terminal a la ruta movies-app-frontend:
cd movies-app-frontend- Instala dependencias:
npm install- Configura las variables de entorno usando el archivo
.env.exampley cambia el nombre del archivo a.env:
VITE_API_URL=http://localhost:4000/api/v1Nota: Asegúrate de colocar correctamente la URL de tu backend
- Corre el servidor:
npm run devDesarrollado por Clio Salgado. Enfocado en la construcción de soluciones full-stack confiables y basadas en datos, con estándares profesionales de testing.
