Skip to content

Showroom is a CRUD web app where I show off my best projects. Think portfolio, but you can update stuff whenever you want—and only you (or the right people) can make changes, thanks to a built-in security layer

Notifications You must be signed in to change notification settings

krub-dev/SHOWROOM-FULLSTACK-M3

Repository files navigation

Showroom banner

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.

🌐 Live SHOWROOM

🚀 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

📋 Project Overview

What is SHOWROOM?

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.

Showroom Project Desktop

Showroom Project Responsive

Key Features

  • 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)

Tech Stack:

  • 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)

🏗️ Directory Structure

📁 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

🏗️ Project Structure

Frontend Components

  • 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: /apihttp://localhost:3001 for seamless local development.

Backend Structure

  • 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.

Quick Start

Prerequisites:

  • Node.js (v18+)
  • npm
  • PostgreSQL 14+ (local installation or Docker)

1. Clone & Install:

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 install

2. Database Setup (Local PostgreSQL):

Option 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 localhost

Option 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

3. Configure Environment:

# In api-projects/ directory
cp .env.example .env

# Edit .env with your database credentials
# DATABASE_URL="postgresql://postgres:ironhack2025@localhost:5432/showroom"

4. Run Prisma Migrations & Seed:

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:5555

Expected output:

Starting seed...
Cleared existing projects
Created project: Minishell
Created project: sideForge Backend
...
Seed completed successfully!

5. Start Development Servers:

Terminal 1 - Frontend (Vue):

# From project root
npm run dev
# → Frontend available at http://localhost:5173

Terminal 2 - Backend (Express API):

cd api-projects
npm run dev
# → API available at http://localhost:3001

6. Verify Everything Works:

Test 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 projects

Access Points:


🚀 Production Deployment (Railway)

Live Application:

Deployment Setup:

1. Create PostgreSQL Database in Railway:

  • Add "PostgreSQL" service to your Railway project
  • Railway automatically provides DATABASE_URL variable

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.js

This 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 seed

🔄 Continuous Integration & Deployment (CI/CD):

This project implements automatic continuous deployment via Railway:

  • Automatic Deployment: Every push to main branch 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 production

5. 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 Configuration:

{
	"build": "vite build && cd api-projects && npm install",
	"start": "cd api-projects && npx prisma migrate deploy && node server.js"
}

🧩 API Endpoints

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/1

Response (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 exist
  • 400 Bad Request: Invalid ID format (not a number)

🎨 Features

🚀 Frontend

  • 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 for prefers-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.

🛠️ Backend

  • 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/health reports 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 main via 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.

💡 Advanced Features

  • 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).

🛡️ Error Handling

The application implements comprehensive error handling as required, with clear and recoverable error messages for different HTTP status codes:

HTTP Status Codes Handled:

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

Error Handling Features:

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

Testing Error Scenarios:

# 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"}'

🧪 Testing

Postman Collection

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:

  1. Health Check - Verify API and database connection
  2. Get All Projects - With pagination support
  3. Search Projects - By title, description, or technology
  4. Get Featured Projects - Filter by featured status
  5. Create Project - POST with authentication
  6. Update Project - PUT with authentication
  7. Delete Project - DELETE with authentication
  8. Test Auth Required - Negative test (should fail without auth)

How to use:

  1. Import Showroom_API.postman_collection.json to Postman
  2. Collection variables are pre-configured:
    • base_url: Railway production URL (change to http://localhost:3001 for local)
    • admin_key: ironhack2025
  3. Run individual requests or use Postman's Collection Runner
  4. 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.json

Integration Tests (Jest + Supertest)

The 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 test

Test 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

🦾 Accessibility (a11y)

The application implements WCAG 2.0 AA accessibility standards with Lighthouse Accessibility Score: 100/100

Implemented Features:

  • 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"> or aria-label attributes
  • Color Contrast - All text meets WCAG AA standard (≥4.5:1 contrast ratio)
  • Motion Preferences - Respects prefers-reduced-motion to disable animations for users with vestibular disorders
  • Alt Text - All images include descriptive alt attributes for screen readers
  • Semantic HTML - Proper use of headings, landmarks, and semantic elements

Lighthouse Audit Results:

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

💡 Advanced Feature: Advanced Sorting and Filtering (Interview-Level Demo)

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:

  1. The user enters a search term or selects technologies/tags.
  2. 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
  3. The backend processes the filters and returns only the projects that match the criteria, along with pagination metadata.
  4. 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.

▶️ Presentation Slides: Link


👤 Developer


Ironhack Web Development Bootcamp - Module 3 Final Project
Completed: 4 October 2025
Status: ✅ Production Ready & Deployed


Lab Origin Reference

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.

About

Showroom is a CRUD web app where I show off my best projects. Think portfolio, but you can update stuff whenever you want—and only you (or the right people) can make changes, thanks to a built-in security layer

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published