Professional full-stack web application developed during Ironhack Web Development Course. This project showcases a complete Vue.js frontend with an Express.js backend, featuring advanced CRUD operations, a featured projects system, and an modern dark UI design. The application is deployed on Railway with a PostgreSQL database, ensuring reliable cloud hosting and scalable data management.
🚀 Deployed Application: https://showroom-fullstack-m3-production.up.railway.app/
Platform: Railway Cloud Deployment
Status: ✅ Production Ready
Backend API: Railway PostgreSQL with Prisma ORM
Database: Managed PostgreSQL 14+ instance
The showroom includes:
- 🏠 Home (
/) - Landing page with featured projects showcase - 📋 Projects (
/projects) - Complete projects list with search, pagination, and featured filter - 📞 Contact (
/contact) - Professional contact form with LinkedIn integration - ⚙️ Admin Panel (
/crud) - Secure CRUD interface with API Key Authentication and health check - 📱 Mobile Responsive - Hamburger menu and mobile-optimized design
SHOWROOM is a portfolio-style web app to manage and display your best projects.
It features a full CRUD system, project search/filter by title and technologies, and real-time admin controls.
- Full stack (Vue.js + Express.js)
- Projects CRUD: create, view, edit, delete
- Secure admin actions (API Key Authentication)
- Featured projects system
- List, detail, and admin forms
- Search/filter by title and technologies (tags)
- Server-side paginated project listing
- Responsive design (mobile-first)
- Professional contact form with LinkedIn
- Animated transitions
- Error and loading states in UI
- Button to test backend/database connection
- Deployed in production (Railway)
- Frontend: Vue.js 3 (Composition API), Vue Router, CSS3, HTML5
- Backend: Node.js, Express.js, CORS
- Database: PostgreSQL 14+ with Prisma ORM
- Data Layer: Prisma Client, Migrations, Seeding
- UI/UX: Dark theme, mobile-first, smooth animations
- Tools: Vite, npm, Git, VS Code, Railway
- Deployment: Railway (Frontend + Backend + PostgreSQL Database)
📁 SHOWROOM-FULLSTACK-M3/
├── 🖥️ Frontend (Vue.js) → http://localhost:5173 | Production: Railway
│ ├── src/
│ │ ├── components/
│ │ │ ├── Home.vue # Landing page with responsive design
│ │ │ ├── ProjectList.vue # Projects list with search, pagination, skeleton loader
│ │ │ ├── ApiProjects.vue # CRUD Manager with health check
│ │ │ ├── Contact.vue # Dark theme contact form with toast notifications
│ │ │ ├── NotFound404.vue # 404 error page with animations
│ │ │ ├── LinkedInButton.vue # Professional networking button
│ │ │ └── SkeletonLoader.vue # Loading skeleton with shimmer effect
│ │ ├── router/
│ │ │ └── index.js # Vue Router configuration (/, /projects, /contact, /crud)
│ │ ├── assets/
│ │ │ ├── banner-krub.png # Profile banner
│ │ │ ├── banner-showroom.png # Project banner
│ │ │ └── krub-logo.png # Logo image
│ │ ├── App.vue # Main app with hamburger menu navigation
│ │ ├── main.js # Vue app entry point
│ │ └── style.css # Global styles (focus-visible, prefers-reduced-motion)
│ ├── public/
│ │ └── krub-logo.png # Public assets
│ ├── index.html # HTML entry point
│ ├── vite.config.js # Vite config with /api proxy
│ ├── package.json # Frontend dependencies (showroom-fullstack v1.0.0)
│ └── package-lock.json # Lock file for reproducible builds
├── 🌐 Backend (Express API) → http://localhost:3001 | Production: Railway
│ ├── api-projects/
│ │ ├── prisma/
│ │ │ ├── schema.prisma # Database schema (Project model)
│ │ │ ├── seed.js # Database seeding with 10 projects
│ │ │ └── migrations/ # Migration history (auto-generated)
│ │ ├── tests/
│ │ │ ├── server.test.js # Integration tests (Jest + Supertest) - 17 tests
│ │ │ └── run-tests.sh # Automated test runner script
│ │ ├── server.js # Express server with CRUD + SPA routing
│ │ ├── .env # Local environment variables (gitignored)
│ │ ├── .env.example # Environment template with secure defaults
│ │ ├── package.json # Backend dependencies (showroom-api v1.0.0)
│ │ └── package-lock.json # Lock file for reproducible builds
├── Showroom_API.postman_collection.json # Postman collection with 9 endpoints + tests
├── README.md # This file
└── .gitignore # Git ignore rules
App.vue— Main application shell with responsive hamburger menu navigation.Home.vue— Landing page featuring a professional showroom and elegant design.ProjectList.vue— Display all/featured projects with search, pagination, error handling, and skeleton loader.ApiProjects.vue— CRUD manager with API Key Authentication, health check button, and comprehensive error handling.SkeletonLoader.vue— Reusable loading skeleton component with shimmer animation effect.Contact.vue— Dark theme contact form with LinkedIn integration.NotFound404.vue— Custom 404 error page with animated elements.LinkedInButton.vue— Reusable LinkedIn networking component.router/index.js— Vue Router configuration with routes:/,/projects,/contact,/crud, and 404 fallback.style.css— Global styles including focus-visible states and prefers-reduced-motion support.vite.config.js— Dev server proxy:/api→http://localhost:3001for seamless local development.
server.js— Express server with full CRUD REST endpoints and SPA routing support.prisma/schema.prisma— Database schema with Project model definition.prisma/seed.js— Database seeding script with 10 sample projects.prisma/migrations/— Database migration history (auto-generated)..env— Local environment variables (DATABASE_URL, PORT, etc.).env.example— Template for environment configuration.- Data operations: Prisma ORM with PostgreSQL, full ACID compliance.
- Authentication: API Key Authentication middleware for write operations.
- CORS: Production-ready configuration.
- Static file serving and SPA fallback.
- Error handling and logging.
- Data validation with Prisma (required fields, types).
- Health check endpoint for monitoring.
- Node.js (v18+)
- npm
- PostgreSQL 14+ (local installation or Docker)
git clone https://github.com/krub-dev/SHOWROOM-FULLSTACK-M3.git
cd SHOWROOM-FULLSTACK-M3
# Install frontend dependencies
npm install
# Install backend dependencies
cd api-projects
npm installOption A: Native PostgreSQL Installation (Recommended)
# Install PostgreSQL (Ubuntu/Debian)
sudo apt update
sudo apt install postgresql postgresql-contrib
# Start PostgreSQL service
sudo systemctl start postgresql
sudo systemctl enable postgresql
# Create database and set password
sudo -u postgres psql
CREATE DATABASE showroom;
ALTER USER postgres PASSWORD 'ironhack2025';
\q
# Verify connection
psql -U postgres -d showroom -h localhostOption B: Docker (Alternative)
docker run --name showroom-postgres \
-e POSTGRES_PASSWORD=ironhack2025 \
-e POSTGRES_DB=showroom \
-p 5432:5432 \
-d postgres:16-alpine
# Verify container is running
docker ps# In api-projects/ directory
cp .env.example .env
# Edit .env with your database credentials
# DATABASE_URL="postgresql://postgres:ironhack2025@localhost:5432/showroom"cd api-projects
# Generate Prisma Client
npx prisma generate
# Apply migrations (creates Project table)
npx prisma migrate dev
# Seed database with 10 sample projects
npm run seed
# Optional: Open Prisma Studio (visual database GUI)
npx prisma studio
# → Opens at http://localhost:5555Expected output:
Starting seed...
Cleared existing projects
Created project: Minishell
Created project: sideForge Backend
...
Seed completed successfully!
Terminal 1 - Frontend (Vue):
# From project root
npm run dev
# → Frontend available at http://localhost:5173Terminal 2 - Backend (Express API):
cd api-projects
npm run dev
# → API available at http://localhost:3001Test Backend:
# Health check
curl http://localhost:3001/api/health
# Expected: {"status":"ok","database":"connected",...}
# List projects
curl http://localhost:3001/api/projects | jq
# Expected: Array with 10 projectsAccess Points:
- Frontend: http://localhost:5173
- Backend API: http://localhost:3001/api/projects
- Health Check: http://localhost:3001/api/health
- Prisma Studio: http://localhost:5555 (if running
npx prisma studio)
- Frontend + Backend: https://showroom-fullstack-m3-production.up.railway.app
- API Health: https://showroom-fullstack-m3-production.up.railway.app/api/health
- Projects Endpoint: https://showroom-fullstack-m3-production.up.railway.app/api/projects
1. Create PostgreSQL Database in Railway:
- Add "PostgreSQL" service to your Railway project
- Railway automatically provides
DATABASE_URLvariable
2. Configure Backend Service:
Add these environment variables in Railway:
DATABASE_URL=<provided by Railway PostgreSQL service>
NODE_ENV=production
ADMIN_PASSWORD=<your-secure-password>3. Set Start Command:
cd api-projects && npx prisma migrate deploy && node server.jsThis command:
- Applies database migrations on deploy
- Starts the Express server
4. Seed Production Database:
Connect via Railway SSH:
railway ssh --project=<project-id> --environment=<env-id> --service=<service-id>
# Inside SSH session:
cd api-projects
export DATABASE_URL="<your-railway-database-url>"
npm run seedThis project implements automatic continuous deployment via Railway:
- ✅ Automatic Deployment: Every push to
mainbranch triggers automatic deployment - ✅ Build Verification: Railway automatically runs build process and validates before deploying
- ✅ Zero-Downtime: New versions are deployed without service interruption
- ✅ Instant Rollback: Previous deployments can be restored instantly if needed
- ✅ Database Migrations: Prisma migrations run automatically on each deployment via start command
Deployment Workflow:
git push origin main → Railway detects push → Builds project → Runs migrations → Deploys to production5. Verify Deployment:
# Test your deployment (example using the original project URL)
curl https://showroom-fullstack-m3-production.up.railway.app/api/health
curl https://showroom-fullstack-m3-production.up.railway.app/api/projects
# Replace with your actual Railway URL:
# curl https://your-project-name.up.railway.app/api/health
# curl https://your-project-name.up.railway.app/api/projects{
"build": "vite build && cd api-projects && npm install",
"start": "cd api-projects && npx prisma migrate deploy && node server.js"
}| Method | Endpoint | Description | Auth Required | Notes |
|---|---|---|---|---|
| GET | /api/projects |
Get all projects | No | Supports search, pagination |
| GET | /api/projects/:id |
Get single project by ID | No | Returns 404 if not found |
| GET | /api/projects?search=&page=&pageSize= |
List with search & pagination | No | Filters by title/tags |
| POST | /api/projects |
Create new project | Yes | x-admin-key header |
| PUT | /api/projects/:id |
Update project | Yes | x-admin-key header |
| DELETE | /api/projects/:id |
Delete project | Yes | x-admin-key header |
| GET | /api/health |
Health check | No | DB/API connection test |
Request Body Schema (POST/PUT):
{
"title": "Project Title", // Required: string
"description": "Project description", // Required: string
"image": "https://...", // Optional: string (URL)
"technologies": ["Vue.js", "Node.js"], // Required: array of strings
"rating": 5, // Optional: integer (default: 5)
"repo": "https://github.com/...", // Optional: string (URL)
"featured": false // Optional: boolean (default: false)
}Response Schema:
{
"id": 1, // Auto-generated
"title": "Project Title",
"description": "Project description",
"image": "https://...",
"technologies": ["Vue.js", "Node.js"],
"rating": 5,
"repo": "https://github.com/...",
"featured": false,
"createdAt": "2025-10-03T10:00:00.000Z", // Auto-generated
"updatedAt": "2025-10-03T10:00:00.000Z" // Auto-updated
}Authentication Header (for POST/PUT/DELETE):
x-admin-key: <your-admin-password>Example: Get Single Project
curl http://localhost:3000/api/projects/1Response (200 OK):
{
"id": 1,
"title": "E-commerce Platform",
"description": "Full-stack e-commerce solution",
"image": "https://...",
"technologies": ["React", "Node.js", "PostgreSQL"],
"featured": true,
"githubUrl": "https://github.com/...",
"liveUrl": "https://...",
"createdAt": "2025-10-03T10:00:00.000Z",
"updatedAt": "2025-10-03T10:00:00.000Z"
}Error Responses:
404 Not Found: Project with specified ID doesn't exist400 Bad Request: Invalid ID format (not a number)
- SPA Routing: Navigation with Vue Router, routes
/,/projects,/contact,/crud, and 404 fallback. - Featured Projects System: Dynamic toggle between featured and all projects.
- CRUD Admin Panel: Admin interface with API Key authentication, complete panel to create, edit, and delete projects.
- Search & Filter: Search by title and technologies, tag-based filters (clickable), pagination with next/prev controls and page size options.
- Responsive & Mobile-First: Adaptive design, hamburger menu (44x44px), optimized for mobile, tablet, and desktop.
- Dark Theme UI: Consistent golden/dark palette (
#f5ca1c), smooth animations, and support forprefers-reduced-motion. - Component Architecture: Reusable components with Composition API, modular architecture.
- Form Handling: Advanced forms with validation, professional contact form with LinkedIn integration.
- Error/Loading States: Skeleton loader with shimmer effect, robust error handling, and success/loading states.
- Accessibility (a11y): WCAG 2.0 AA, ARIA labels,
:focus-visible, high contrast, keyboard navigation, alt text on images. - Professional Styling: Hover effects, modern transitions, consistent design.
- Health Check Button: Button to test backend/database connection (
/api/health). - Notifications: Color-coded visual feedback for CRUD actions.
- LinkedIn Integration: Professional button for networking.
- RESTful API: Standard endpoints with Express.js, PostgreSQL, and Prisma ORM.
- Database Persistence: Migrations, automatic seeding with 10 projects, ACID support, and visual management via Prisma Studio.
- Featured Projects: Backend support for featured project categorization.
- API Key Authentication: All write operations protected by API Key (
x-admin-key). - Error Handling: Comprehensive error handling with specific HTTP codes and clear messages; logging in development and production.
- Input/Data Validation: Strict validations (required title, rating 1-5, correct types).
- Health Check Endpoint:
/api/healthreports API and database connection status. - Search & Pagination: Case-insensitive search in PostgreSQL, server-side pagination with metadata.
- CORS Production-Ready: Secure configuration for Railway deployment.
- Static/SPARouting Support: Express server with fallback for SPA routes.
- Express Middleware: Static file serving, JSON parsing, request validation.
- Auto-incremental IDs: Primary keys managed by the database.
- CI/CD Pipeline: Automatic deployment on each push to
mainvia Railway, Prisma migrations executed in production. - Graceful Shutdown: Clean Prisma client disconnection when stopping the server.
- Independent Environments: Complete separation between local and production databases.
- Dynamic Project Filtering: Real-time filtering by tags, project's name and featured projects.
- Admin Dashboard: Full project management with a dropdown interface.
- Color-coded Notifications: Visual feedback by operation type (success/error/info).
- Enhanced Accessibility: Advanced focus management, aria-live regions, Lighthouse optimization ≥95.
- Real-time Updates: Instant UI refresh after API operations.
- Mobile Optimization: Touch-friendly interface, optimal spacing, smooth mobile experience.
- Homogeneous Design: Consistent style and UX across all components.
- Graceful Degradation: Elegant fallback if backend is unavailable (clear messages and retry option).
The application implements comprehensive error handling as required, with clear and recoverable error messages for different HTTP status codes:
| Status | Scenario | User Message | Recovery Action |
|---|---|---|---|
| 400 | Invalid request data | "Invalid data. Please check all required fields." | Form preserved, user can correct and retry |
| 401 | Authentication failed | "Authentication failed. Please verify your admin access code." | User can re-enter correct password |
| 404 | Resource not found | "Not found. Server may be unavailable / Project may have been deleted." | Retry button available |
| 500 | Server error | "Server error. Please try again in a few moments." | Retry button available |
ProjectList.vue (Public view):
⚠️ Large error icon with descriptive message- 🔄 Retry button to attempt loading again
- Preserves search query and filter state
- Graceful degradation when backend is unavailable
ApiProjects.vue (Admin panel):
- Form data preserved on error (no data loss)
- Specific error messages for create/update/delete operations
- Visual feedback with color-coded alerts
- Prevents accidental data loss
Backend error responses:
- Structured JSON error messages
- Appropriate HTTP status codes
- Detailed error information in development mode
- Sanitized error messages in production
# Test 500 - Backend unavailable
pkill -f "node.*server.js"
# Visit http://localhost:5173 → See error message + retry button
# Test 401 - Wrong authentication
# Go to /crud → Enter wrong password → See auth error
# Test 404 - Non-existent project
curl http://localhost:3001/api/projects/99999
# Test 400 - Invalid data
curl -X POST http://localhost:3001/api/projects \
-H "Content-Type: application/json" \
-H "x-admin-key: ironhack2025" \
-d '{"description":"Missing title"}'A complete Postman collection is included: Showroom_API.postman_collection.json
Features:
- ✅ All CRUD endpoints (GET, POST, PUT, DELETE)
- ✅ Health check endpoint
- ✅ Search and pagination examples
- ✅ Featured filter example
- ✅ Automated test scripts for each request
- ✅ Pre-configured environment variables
- ✅ Authentication headers setup
Endpoints included:
- Health Check - Verify API and database connection
- Get All Projects - With pagination support
- Search Projects - By title, description, or technology
- Get Featured Projects - Filter by featured status
- Create Project - POST with authentication
- Update Project - PUT with authentication
- Delete Project - DELETE with authentication
- Test Auth Required - Negative test (should fail without auth)
How to use:
- Import
Showroom_API.postman_collection.jsonto Postman - Collection variables are pre-configured:
base_url: Railway production URL (change tohttp://localhost:3001for local)admin_key:ironhack2025
- Run individual requests or use Postman's Collection Runner
- All requests include automated tests that verify responses
Running tests:
# Install Newman (Postman CLI) - optional
npm install -g newman
# Run collection from command line
newman run Showroom_API.postman_collection.jsonThe project includes comprehensive automated integration tests that validate all CRUD operations against a real API server and PostgreSQL database.
Test Suite Coverage:
- ✅ Health check endpoint validation
- ✅ GET all projects with pagination
- ✅ Search functionality
- ✅ Featured projects filter
- ✅ CREATE - Project creation with full validation
- ✅ UPDATE - Project updates with authentication
- ✅ DELETE - Project deletion with cleanup
- ✅ Authentication validation (401 errors)
- ✅ Input validation (400 errors)
- ✅ Not found errors (404 errors)
Running integration tests:
cd api-projects
# Option 1: Use the automated test runner script (recommended)
npm run test:integration
# Option 2: Use the shell script directly
cd tests && ./run-tests.sh
# Option 3: Manual approach
# Start server in one terminal
npm start
# Run tests in another terminal
npm testTest Results:
✅ 17/17 tests passing (100% coverage)
Test Suites: 1 passed, 1 total
Tests: 17 passed, 17 total
- Health check ✓
- All GET operations ✓
- GET by ID ✓
- CREATE → UPDATE → DELETE lifecycle ✓
- Authentication validation ✓
- Error handling ✓
- Input validation ✓
Technical Implementation:
- Tests organized in logical execution order (CREATE → UPDATE → DELETE)
- Automatic PostgreSQL sequence reset before tests to prevent ID conflicts
- Complete cleanup after test execution
- Real database integration (not mocked) for production-like testing
The application implements WCAG 2.0 AA accessibility standards with Lighthouse Accessibility Score: 100/100 ✅
- ✅ Keyboard Navigation - Visible focus states (
:focus-visible) with 3px golden outline on all interactive elements - ✅ Labels & ARIA - All form inputs have associated
<label for="id">oraria-labelattributes - ✅ Color Contrast - All text meets WCAG AA standard (≥4.5:1 contrast ratio)
- ✅ Motion Preferences - Respects
prefers-reduced-motionto disable animations for users with vestibular disorders - ✅ Alt Text - All images include descriptive
altattributes for screen readers - ✅ Semantic HTML - Proper use of headings, landmarks, and semantic elements
Performance: 98/100 ✅
Accessibility: 100/100 🎯 Perfect Score
Best Practices: 96/100 ✅
SEO: 83/100 ✅
Tested with:
- Google Lighthouse (Chrome DevTools)
- Manual keyboard navigation (Tab, Enter, Escape)
- Color contrast analyzer tools
- Screen reader compatibility validation
Implemented in this project:
SHOWROOM provides robust search and filtering capabilities both in the UI and the backend API. Users can:
- Search projects by title and technologies (tags).
- Toggle between featured projects and all projects.
- Navigate through paginated results using next/prev controls.
Tech stack:
- Vue.js with the Composition API for reactive UI.
- Fetch API for HTTP requests with dynamic parameters.
- Express.js and Prisma ORM for efficient, case-insensitive, and paginated searches in PostgreSQL.
Workflow:
- The user enters a search term or selects technologies/tags.
- The UI collects these parameters and sends them to the backend:
GET /api/projects?search=vue&page=1&pageSize=6&tags=Node.js,Vue.js - The backend processes the filters and returns only the projects that match the criteria, along with pagination metadata.
- The frontend instantly displays the filtered projects, with visual indicators for active filters and pagination.
Test coverage:
- Integration tests verify searching, filtering, and pagination in the backend.
- Frontend tests confirm correct filtering and pagination in the UI.
User benefits:
- Find relevant projects quickly and with precision.
- Professional experience with flexible search and multi-tag filtering.
- Efficient navigation, even with a large number of projects.
- GitHub: @krub-dev
- LinkedIn: Kiko Rubio Illán
- Portfolio: krub.dev
- Live Demo: krubSHOWROOM
Ironhack Web Development Bootcamp - Module 3 Final Project
Completed: 4 October 2025
Status: ✅ Production Ready & Deployed
This project builds on previous Ironhack labs (Module 3, Week 2), extended and refactored to meet the requirements of the final bootcamp project. See Labs Repo for historical previews versions.


