Skip to content

Hamil1/ShipTrack

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

60 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

ShipTrack - Universal Package Tracking System

A modern, full-stack shipping tracking application that provides a unified interface for tracking packages across all major US carriers. Built with Next.js, Prisma, and TypeScript.

πŸš€ Features

  • Real Carrier API Integration: Live tracking through FedEx API (sandbox)
  • Major Carrier Support: Track packages from FedEx, USPS, and UPS
  • Smart Carrier Detection: Automatically detects carrier based on tracking number format
  • Real-time Tracking: Get up-to-date package status and location information
  • Graceful Fallback: Automatic fallback to mock data when APIs are unavailable
  • User Authentication: Secure JWT-based authentication system with tiered access
  • Tracking History: Save and view tracking history for authenticated users (30 minutes cache)
  • Modern UI: Beautiful, responsive interface built with Tailwind CSS
  • Type Safety: Full TypeScript support throughout the application
  • Multi-Platform Deployment: Support for both Vercel and Docker deployments

πŸ” Authentication Strategy

ShipTrack implements a tiered authentication system that provides the best user experience:

Public Access (No Authentication Required)

  • βœ… Basic package tracking functionality
  • βœ… Universal carrier support
  • βœ… Real-time tracking information
  • βœ… Smart carrier detection

Enhanced Features (Authentication Required)

  • πŸ”’ Tracking History: Save all your tracking searches
  • πŸ”’ Personalized Experience: User-specific data and preferences

This approach ensures that:

  • Anyone can track packages without creating an account (like real carrier websites)
  • Users are incentivized to sign up for enhanced features
  • The system scales from casual users to power users

πŸ› οΈ Tech Stack

  • Frontend: Next.js 14 (App Router), React, TypeScript, Tailwind CSS
  • Backend: Next.js API Routes, Prisma ORM
  • Database: PostgreSQL
  • Authentication: JWT with bcrypt password hashing
  • Validation: Zod schema validation
  • Testing: Jest (ready for implementation)
  • Containerization: Docker
  • Deployment: Vercel (recommended) or Docker containers

πŸ“‹ Prerequisites

  • Node.js 18+
  • npm or yarn
  • Git
  • Docker (for containerized deployment)

πŸš€ Quick Start

Option 1: Local Development (Recommended for Development)

1. Clone the Repository

git clone git@github.com:Hamil1/ShipTrack.git
cd ShipTrack

2. Install Dependencies

npm install

3. Set Up Environment Variables

Copy the example environment file and configure it for your setup:

cp .env.example .env

Generate a Secure JWT Secret:

Before editing the .env file, generate a secure JWT secret:

node -e "console.log('JWT_SECRET=\"' + require('crypto').randomBytes(64).toString('hex') + '\"')"

Copy the output and use it as your JWT_SECRET value in the .env file.

Then edit the .env file with your specific values. See .env.example for all available environment variables and their descriptions.

Important Notes:

  • If you're using Docker, the database URL will be automatically configured by the Docker Compose environment variables.
  • Carrier API keys are optional. The app will use mock data if APIs are not configured.
  • USPS API: Has geographic restrictions and may not be available outside the US.
  • JWT_SECRET: Must be a secure, random string. Never use the default placeholder value in production.

4. Set Up Database

# Generate Prisma client
npx prisma generate

# For Local Development (without Docker)
# You'll need PostgreSQL installed locally, then:
npx prisma db push

# For Docker Development
./scripts/init-db.sh dev

5. Run the Development Server

npm run dev

Open http://localhost:3000 to view the application.

Option 2: Docker Development Environment

1. Clone and Navigate

git clone git@github.com:Hamil1/ShipTrack.git
cd ShipTrack

2. Configure JWT Secret

Use the same JWT secret you generated in the earlier step for your Docker environment. Update the JWT_SECRET value in your docker-compose.yml file or .env file as needed.

3. Initialize Development Database

# Initialize the development database
./scripts/init-db.sh

4. Run with Docker (Recommended)

# Using the convenience script
./scripts/docker-dev.sh

# Or manually
docker compose up --build

Access the app at http://localhost:3001 Access the database at localhost:5433

🐳 Docker Commands

Development

# Initialize development database
./scripts/init-db.sh

# Start development environment
docker compose up --build

# Start development environment (detached)
docker compose up --build -d

# View logs
docker compose logs -f shiptrack-app

# Stop development environment
docker compose down

# Stop development environment and remove orphaned containers
docker compose down --remove-orphans

πŸ“š API Documentation

Authentication Endpoints

POST /api/auth/register

Register a new user account.

Request Body:

{
  "name": "John Doe",
  "email": "john@example.com",
  "password": "password123"
}

Response:

{
  "success": true,
  "data": {
    "user": {
      "id": "user_id",
      "name": "John Doe",
      "email": "john@example.com",
      "createdAt": "2024-01-01T00:00:00.000Z",
      "updatedAt": "2024-01-01T00:00:00.000Z"
    },
    "token": "jwt_token_here"
  },
  "message": "User registered successfully"
}

POST /api/auth/login

Authenticate a user and receive a JWT token.

Request Body:

{
  "email": "john@example.com",
  "password": "password123"
}

Response:

{
  "success": true,
  "data": {
    "user": {
      "id": "user_id",
      "name": "John Doe",
      "email": "john@example.com",
      "createdAt": "2024-01-01T00:00:00.000Z",
      "updatedAt": "2024-01-01T00:00:00.000Z"
    },
    "token": "jwt_token_here"
  },
  "message": "Login successful"
}

Tracking Endpoints

POST /api/track

Universal tracking endpoint that works for both authenticated and non-authenticated users.

Request Body:

{
  "trackingNumber": "1Z999AA1234567890"
}

Headers (optional):

Authorization: Bearer <jwt_token>

Response (Non-authenticated):

{
  "success": true,
  "data": {
    "trackingNumber": "1Z999AA1234567890",
    "carrier": "UPS",
    "status": "In Transit",
    "location": "Memphis, TN",
    "timestamp": "2024-01-01T12:00:00.000Z",
    "description": "Package in transit to next facility",
    "events": [...]
  },
  "message": "Tracking information retrieved for UPS (Sign up for enhanced features)"
}

Response (Authenticated):

{
  "success": true,
  "data": {
    "trackingNumber": "1Z999AA1234567890",
    "carrier": "UPS",
    "status": "In Transit",
    "location": "Memphis, TN",
    "timestamp": "2024-01-01T12:00:00.000Z",
    "description": "Package in transit to next facility",
    "events": [...],
    "userFeatures": {
      "historySaved": true,
      "enhancedUpdates": true
    }
  },
  "message": "Tracking information retrieved for UPS (Enhanced features enabled)"
}

GET /api/track/[trackingNumber]

Get cached tracking information for a specific tracking number. This endpoint implements intelligent caching:

  1. Personal Cache: For authenticated users, checks their personal tracking history first
  2. Global Cache: Falls back to any user's recent tracking data
  3. Freshness Check: Returns cached data if it's less than 30 minutes old
  4. Carrier API: Calls carrier API if no fresh cached data exists
  5. Auto-Save: Saves new tracking data to user's history if authenticated

Headers (optional):

Authorization: Bearer <jwt_token>

Response (Cached):

{
  "success": true,
  "data": {
    "trackingNumber": "1Z999AA1234567890",
    "carrier": "UPS",
    "status": "In Transit",
    "location": "Memphis, TN",
    "timestamp": "2024-01-01T12:00:00.000Z",
    "description": "Package in transit to next facility",
    "events": [...]
  },
  "message": "Cached tracking information retrieved for UPS"
}

Response (Fresh):

{
  "success": true,
  "data": {
    "trackingNumber": "1Z999AA1234567890",
    "carrier": "UPS",
    "status": "In Transit",
    "location": "Memphis, TN",
    "timestamp": "2024-01-01T12:00:00.000Z",
    "description": "Package in transit to next facility",
    "events": [...]
  },
  "message": "Fresh tracking information retrieved for UPS"
}

GET /api/track/history

Get all tracking history for the authenticated user (requires authentication).

Headers (required):

Authorization: Bearer <jwt_token>

Response:

{
  "success": true,
  "data": [
    {
      "id": "history_id",
      "trackingNumber": "1Z999AA1234567890",
      "carrier": "UPS",
      "status": "In Transit",
      "location": "Memphis, TN",
      "timestamp": "2024-01-01T12:00:00.000Z",
      "description": "Package in transit to next facility",
      "createdAt": "2024-01-01T00:00:00.000Z",
      "updatedAt": "2024-01-01T00:00:00.000Z"
    }
  ],
  "message": "Tracking history retrieved successfully"
}

GET /api/track/history/[trackingNumber]

Get full tracking history for a specific tracking number (requires authentication).

Headers (required):

Authorization: Bearer <jwt_token>

πŸ” Supported Carriers

Carrier Tracking Number Format Example API Status
FedEx 12-14 digits 123456789012 βœ… Real API
USPS 9xxx + 15-18 digits 9400100000000000000000 ⚠️ Geographic Restrictions
UPS 1Z + 6 chars + 10 digits 1Z999AA1234567890 ⚠️ Credentials Required

πŸ—οΈ Project Structure

ShipTrack/
β”œβ”€β”€ .github/                          # GitHub Actions workflows
β”‚   └── workflows/
β”‚       └── deploy.yml
β”œβ”€β”€ .husky/                           # Git hooks configuration
β”œβ”€β”€ config/                           # Carrier configuration files
β”‚   └── carriers/
β”‚       β”œβ”€β”€ fedex.json
β”‚       β”œβ”€β”€ ups.json
β”‚       └── usps.json
β”œβ”€β”€ docs/                             # Documentation
β”‚   β”œβ”€β”€ CARRIER_ONBOARDING_README.md
β”‚   β”œβ”€β”€ DEPLOYMENT.md
β”‚   β”œβ”€β”€ README.md
β”‚   β”œβ”€β”€ TRACKING_STATUSES.md
β”‚   └── USPS_API_TROUBLESHOOTING.md
β”œβ”€β”€ prisma/                           # Database schema and migrations
β”‚   └── schema.prisma
β”œβ”€β”€ public/                           # Static assets
β”‚   β”œβ”€β”€ carriers/                     # Carrier logo SVGs
β”‚   β”‚   β”œβ”€β”€ fedex.svg
β”‚   β”‚   β”œβ”€β”€ ups.svg
β”‚   β”‚   └── usps.svg
β”‚   β”œβ”€β”€ favicon.ico
β”‚   └── ...
β”œβ”€β”€ scripts/                          # Development and deployment scripts
β”‚   β”œβ”€β”€ cleanup.sh
β”‚   β”œβ”€β”€ docker-dev-hot-reload.sh
β”‚   β”œβ”€β”€ docker-dev.sh
β”‚   β”œβ”€β”€ docker-prod.sh
β”‚   └── init-db.sh
β”œβ”€β”€ src/                              # Application source code
β”‚   β”œβ”€β”€ app/                          # Next.js App Router
β”‚   β”‚   β”œβ”€β”€ api/                      # API routes
β”‚   β”‚   β”‚   β”œβ”€β”€ auth/                 # Authentication endpoints
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ login/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ register/
β”‚   β”‚   β”‚   β”‚   └── validate/
β”‚   β”‚   β”‚   └── track/                # Tracking endpoints
β”‚   β”‚   β”‚       β”œβ”€β”€ [trackingNumber]/
β”‚   β”‚   β”‚       └── history/
β”‚   β”‚   β”‚           └── [trackingNumber]/
β”‚   β”‚   β”œβ”€β”€ favicon.ico
β”‚   β”‚   β”œβ”€β”€ globals.css
β”‚   β”‚   β”œβ”€β”€ layout.tsx
β”‚   β”‚   └── page.tsx
β”‚   β”œβ”€β”€ components/                   # React components
β”‚   β”‚   β”œβ”€β”€ common/                   # Reusable UI components
β”‚   β”‚   β”‚   β”œβ”€β”€ Button.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ Card.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ CarrierBadge.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ ErrorDisplay.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ Input.tsx
β”‚   β”‚   β”‚   └── index.ts
β”‚   β”‚   β”œβ”€β”€ AuthPrompt.tsx
β”‚   β”‚   β”œβ”€β”€ Header.tsx
β”‚   β”‚   β”œβ”€β”€ LoginForm.tsx
β”‚   β”‚   β”œβ”€β”€ RegisterForm.tsx
β”‚   β”‚   β”œβ”€β”€ TrackingForm.tsx
β”‚   β”‚   β”œβ”€β”€ TrackingHistory.tsx
β”‚   β”‚   β”œβ”€β”€ TrackingResult.tsx
β”‚   β”‚   └── UserMenu.tsx
β”‚   β”œβ”€β”€ contexts/                     # React contexts
β”‚   β”‚   └── AuthContext.tsx
β”‚   β”œβ”€β”€ lib/                          # Library configurations
β”‚   β”‚   └── prisma.ts
β”‚   β”œβ”€β”€ providers/                    # Carrier API providers
β”‚   β”‚   β”œβ”€β”€ BaseCarrierProvider.ts
β”‚   β”‚   β”œβ”€β”€ FedExProvider.ts
β”‚   β”‚   β”œβ”€β”€ UPSProvider.ts
β”‚   β”‚   └── USPSProvider.ts
β”‚   β”œβ”€β”€ services/                     # Business logic services
β”‚   β”‚   β”œβ”€β”€ CarrierRegistry.ts
β”‚   β”‚   └── TrackingService.ts
β”‚   β”œβ”€β”€ types/                        # TypeScript type definitions
β”‚   β”‚   β”œβ”€β”€ carrier.ts
β”‚   β”‚   └── index.ts
β”‚   └── utils/                        # Utility functions
β”‚       β”œβ”€β”€ __tests__/                # Test files
β”‚       β”‚   β”œβ”€β”€ auth.test.ts
β”‚       β”‚   β”œβ”€β”€ carrierDetection.test.ts
β”‚       β”‚   └── trackingService.test.ts
β”‚       β”œβ”€β”€ auth.ts
β”‚       β”œβ”€β”€ carrierDetection.ts
β”‚       β”œβ”€β”€ carrierDetection.test.ts
β”‚       β”œβ”€β”€ carrierLogos.ts
β”‚       └── trackingService.ts
β”œβ”€β”€ .dockerignore
β”œβ”€β”€ .env                              # Environment variables
β”œβ”€β”€ .env.example                      # Environment variables template
β”œβ”€β”€ .gitignore
β”œβ”€β”€ docker-compose.yml                # Docker Compose configuration
β”œβ”€β”€ Dockerfile                        # Production Dockerfile
β”œβ”€β”€ Dockerfile.dev                    # Development Dockerfile
β”œβ”€β”€ eslint.config.mjs                 # ESLint configuration
β”œβ”€β”€ jest.config.js                    # Jest test configuration
β”œβ”€β”€ jest.setup.js                     # Jest setup file
β”œβ”€β”€ next-env.d.ts                     # Next.js TypeScript definitions
β”œβ”€β”€ next.config.ts                    # Next.js configuration
β”œβ”€β”€ package.json                      # Node.js dependencies and scripts
β”œβ”€β”€ postcss.config.mjs                # PostCSS configuration
β”œβ”€β”€ README.md                         # Project documentation
β”œβ”€β”€ tsconfig.json                     # TypeScript configuration
β”œβ”€β”€ tsconfig.tsbuildinfo              # TypeScript build info
└── vercel.json                       # Vercel deployment configuration

πŸ§ͺ Testing

The application includes comprehensive test coverage for critical functionality:

Running Tests

# Run all tests
npm test

# Run tests in watch mode
npm run test:watch

# Run tests with coverage
npm run test:coverage

πŸ”§ Development

Database Management

# View database in Prisma Studio
npx prisma studio

# Reset database
npx prisma db push --force-reset

# Generate migration
npx prisma migrate dev --name <migration_name>

Code Quality

# Run ESLint
npm run lint

# Run TypeScript check
npm run type-check

# Format code
npm run format

# Run tests (automatically runs before git commit)
npm test

Git Hooks

The project uses Husky to ensure code quality:

  • Pre-commit: Runs tests before each commit

This ensures that broken code cannot be committed to the repository.

πŸ› Known Issues & Limitations

  • API Integration Status:
    • βœ… FedEx: Full API integration working (sandbox)
    • ⚠️ USPS: Geographic restrictions may apply (US-based users only)
    • ⚠️ UPS: Requires valid OAuth credentials
  • Caching: Basic caching implemented. Consider Redis for production caching.
  • Real-time Updates: Polling-based updates. Consider WebSockets for real-time functionality.

Note: This is a technical assessment project. For production use, additional security measures, error handling, and carrier API integrations would be required.

How to test the app:

image image image image

About

This is a tracking app which uses services like FedEx, USP, and USPS

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors