Chat about this codebase

AI-powered code exploration

Online

Project Overview

This project provides programmatic access to Indian Railways’ IRCTC services for checking PNR status and retrieving live train updates. It wraps IRCTC’s web endpoints into a simple, reusable interface, enabling developers to integrate real-time train information into applications without dealing directly with IRCTC’s web forms or HTML parsing.

Main Features

  • PNR Status Lookup
    Retrieve current booking status, chart preparation status, seat confirmation, and coach details.
  • Live Train Tracking
    Fetch real-time position, expected arrival/departure times, and delay information for any train.
  • Route & Schedule Retrieval
    List station stops, scheduled times, and halt durations for selected trains.
  • Error Handling & Retries
    Built-in mechanisms to handle rate limits, network issues, and IRCTC’s occasional downtime.

When to Use

  • Building travel assistant bots or mobile apps that notify users of PNR confirmations and delays
  • Integrating train schedules and real-time tracking into booking platforms or logistics dashboards
  • Automating customer support workflows that require up-to-date train information

Value Proposition

  • Accelerate development by avoiding manual scraping or reverse-engineering of IRCTC’s web interface
  • Ensure reliability with automated retry and error-handling strategies tailored for IRCTC’s constraints
  • Maintainable codebase that adapts to IRCTC changes without rewriting core business logic

Getting Started & Deployment

This section guides you through cloning the ortux/irctc repository, running it locally, and deploying it to GitHub Pages using the provided GitHub Actions workflow.

Prerequisites

  • Git (v2.0+)
  • Python 3 (for simple HTTP server) or Node.js (v12+) if you prefer serve/live-server
  • A GitHub repository named ortux/irctc (or your fork) with Pages enabled on the main branch

Clone the Repository

git clone https://github.com/ortux/irctc.git
cd irctc

Run Locally

Using Python HTTP Server

# From the repo root
python3 -m http.server 8000

Open http://localhost:8000/home/ in your browser.

Using npm “serve”

npm install -g serve
serve -l 8000 .

Navigate to http://localhost:8000/home/.

Directory Structure

/
├─ home/           # Train booking homepage (home/index.html)
├─ search/         # Search results page (search/index.html)
├─ status/         # PNR status interface (status/index.html)
├─ train_status/   # Live train tracking (train_status/index.html)
├─ index.html      # Client-side redirect to /home/
└─ .github/
   └─ workflows/
      └─ static.yml  # GitHub Actions workflow for Pages

Deploying to GitHub Pages

  1. In your repository Settings → Pages:

    • Source: main branch
    • Folder: ** / (root)**
  2. Commit and push to main or trigger manually.

The workflow at .github/workflows/static.yml handles checkout, artifact upload, and Pages deployment:

name: Deploy static content to Pages

on:
  push:
    branches: ["main"]
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: "pages"
  cancel-in-progress: false

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Configure Pages
        uses: actions/configure-pages@v4

      - name: Upload artifact
        uses: actions/upload-pages-artifact@v1
        with:
          path: .     # Deploy entire repo root

      - name: Deploy to GitHub Pages
        uses: actions/deploy-pages@v1

Concurrency Settings

Prevent overlapping deployments while letting in-flight jobs finish:

concurrency:
  # All deploy runs share the same queue
  group: "pages"
  # false → queue up new runs; allow current run to complete
  cancel-in-progress: false
  • Use cancel-in-progress: true for non-critical branches (e.g., staging).
  • Give each environment a unique group name when managing multiple workflows.

Customizing the Root Redirect

The root index.html auto-redirects to /home/. To change the target URL or message, edit:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="refresh" content="0; url=/home/">
  <title>Redirecting…</title>
</head>
<body>
  <p>Redirecting to the train booking page. If you aren’t redirected automatically, <a href="/home/">click here</a>.</p>
</body>
</html>

Adjust the content URL and anchor link text as needed.

Code Structure

This section outlines the project layout and the role of each major file. Use this guide to locate functionality and understand how components connect.

Project tree

assets/
  background.jpeg
backend/
  index.js
  navbar.js
  pnr.js
  results.js
home/
  index.html
search/
  index.html
status/
  index.html
train_status/
  index.html

assets/background.jpeg

• High-resolution train image used as page background or header hero.
• Reference in HTML or Tailwind CSS:

<div class="h-64 bg-cover" style="background-image: url('../assets/background.jpeg')"></div>

backend/index.js

Provides station autocomplete, debounced input handling, in-memory caching, timeout/fallback logic, and form submission wiring on the booking homepage.

Key responsibilities

  • Attach input listeners to #fromStation and #toStation
  • Debounce user keystrokes (200–300 ms)
  • Fetch suggestions with abortable timeout (5 s) and local fallback
  • Render dropdown items, handle selection, and store station codes
  • Listen for form submit to redirect to search page with query params

Inclusion in home/index.html

<script type="module" src="../backend/index.js"></script>

backend/navbar.js

Controls responsive navigation and theme toggling across all pages.

Features

  • Mobile menu show/hide on toggle button click
  • Window resize listener to reset menu state
  • Dark/light mode switch and prefers-color-scheme fallback
  • ARIA attributes for accessibility

Include before closing </body>

<script type="module" src="../backend/navbar.js"></script>

backend/pnr.js

Implements client-side PNR status checking on status/index.html.

Exports

  • async function checkPNR(pnr: string): Promise<void> – validates input, fetches API data, and updates DOM

Usage example in status/index.html

<input id="pnrInput" type="text" placeholder="Enter PNR" />
<button id="checkBtn">Check Status</button>
<script type="module">
  import { checkPNR } from '../backend/pnr.js';

  document.getElementById('checkBtn').addEventListener('click', () => {
    const pnr = document.getElementById('pnrInput').value.trim();
    checkPNR(pnr);
  });
</script>

backend/results.js

Handles train search results on search/index.html, including filtering and availability refresh.

Exports

  • async function init(): Promise<void> – entry point: reads URL params, fetches trains
  • async function fetchAndProcessTrains(params): Promise<ProcessedData>
  • function renderTrainCards(data): void – injects direct and nearby train cards
  • function refreshAvailability(trainId): Promise<void> – updates a single card

Initialization in search/index.html

<script type="module">
  import { init } from '../backend/results.js';
  document.addEventListener('DOMContentLoaded', init);
</script>

home/index.html

Train booking homepage

  • Station autocomplete inputs (#fromStation, #toStation)
  • Route type buttons (One-way, Round-trip)
  • Search form redirects to /search/index.html?from=…&to=…&date=…
  • Includes Tailwind CSS utilities and backend/index.js

search/index.html

Search results page

  • Header and nav (scripts from navbar.js)
  • Loading and error states
  • Filter panel (class, time, availability)
  • Direct vs. nearby train sections
  • Includes backend/results.js for data fetching and rendering

status/index.html

PNR status checker

  • Input field, search button
  • Sections for train details, passenger status, booking info
  • Error and retry UI
  • Imports backend/navbar.js and backend/pnr.js

train_status/index.html

Live train tracking interface

  • Inputs: train number, date picker
  • “Track Train” button triggers API fetch
  • Displays journey timeline, station statuses, and auto-refresh
  • Includes backend/navbar.js and inline or dedicated script for tracking logic

Navigating the codebase by this structure helps you locate features quickly, understand entry points, and extend functionality with minimal friction.

Customization & Configuration

This section explains how to configure API endpoints, adjust request timeouts, enable dark mode, replace assets, and tweak UI templates.

API Base URLs & Timeouts

Centralize your endpoints and timeouts in a config.js file:

// backend/config.js
export default {
  stationApi:   process.env.STATION_API_URL || 'https://api.irctc.co.in/stations',
  pnrApi:       process.env.PNR_API_URL     || 'https://api.irctc.co.in/pnr',
  searchApi:    process.env.SEARCH_API_URL  || 'https://api.irctc.co.in/search',
  requestTimeout: parseInt(process.env.REQUEST_TIMEOUT, 10) || 5000
};

Import and use in your fetch functions:

// backend/index.js
import config from './config';

async function fetchWithTimeout(url, options = {}) {
  const controller = new AbortController();
  const id = setTimeout(() => controller.abort(), config.requestTimeout);
  
  const res = await fetch(url, {
    ...options,
    signal: controller.signal
  });
  clearTimeout(id);
  return res.json();
}

export async function fetchStations(query) {
  const url = `${config.stationApi}?q=${encodeURIComponent(query)}`;
  return fetchWithTimeout(url);
}

Override values via environment variables or by editing config.js.

Dark-Mode Styling

Use CSS variables and a body class toggle. Create dark.css:

/* assets/css/dark.css */
:root {
  --bg-color: #121212;
  --text-color: #e0e0e0;
  --card-bg:   #1e1e1e;
}
body.dark-mode {
  background-color: var(--bg-color);
  color: var(--text-color);
}
.train-card {
  background-color: var(--card-bg);
}

Load it in your HTML and toggle via JS:

<link rel="stylesheet" href="assets/css/dark.css">
<button id="darkToggle">Toggle Dark Mode</button>
<script>
  document
    .getElementById('darkToggle')
    .addEventListener('click', () => document.body.classList.toggle('dark-mode'));
</script>

Asset Replacement

Replace assets/background.jpeg with your own image or change its reference:

/* assets/css/main.css */
body {
  background: url('../assets/background.jpeg') no-repeat center/cover;
}

To use a different filename:

  1. Place my-train.jpg in assets/.
  2. Update main.css:
    body {
      background: url('../assets/my-train.jpg') no-repeat center/cover;
    }
    

UI Template Tweaks

Station Autocomplete (backend/index.js)

Default item renderer:

function createDropdownItem(station) {
  const li = document.createElement('li');
  li.className = 'station-item';
  li.textContent = station.name;
  return li;
}

To show code and name:

function createDropdownItem(station) {
  const li = document.createElement('li');
  li.className = 'station-item';
  li.innerHTML = `
    <span class="station-code">${station.code}</span>
    <span class="station-name">${station.name}</span>
  `;
  return li;
}

PNR Status Checker (backend/pnr.js)

Wrap checkPNR() to add custom loading indicator:

import { checkPNR } from './pnr';

document.getElementById('pnrForm').addEventListener('submit', async e => {
  e.preventDefault();
  const loader = document.createElement('div');
  loader.id = 'custom-loader';
  loader.textContent = 'Checking…';
  document.body.append(loader);

  try {
    await checkPNR();
  } finally {
    loader.remove();
  }
});

Train Results (backend/results.js)

Default card renderer:

function renderTrainCard(train) {
  return `
    <div class="train-card">
      <h3>${train.name}</h3>
      <span>${train.availability}</span>
    </div>`;
}

To include departure time:

function renderTrainCard(train) {
  return `
    <div class="train-card">
      <h3>${train.name} (${train.number})</h3>
      <p>Departs at: ${train.departureTime}</p>
      <span>Status: ${train.availability}</span>
    </div>`;
}

Place these functions in your own copy of results.js or override via module aliasing in your build setup.

\n```\n\n### backend/navbar.js \nControls responsive navigation and theme toggling across all pages.\n\nFeatures \n- Mobile menu show/hide on toggle button click \n- Window resize listener to reset menu state \n- Dark/light mode switch and `prefers-color-scheme` fallback \n- ARIA attributes for accessibility\n\nInclude before closing `` \n```html\n\n```\n\n### backend/pnr.js \nImplements client-side PNR status checking on `status/index.html`.\n\nExports \n- `async function checkPNR(pnr: string): Promise` – validates input, fetches API data, and updates DOM\n\nUsage example in status/index.html \n```html\n\n\n\n```\n\n### backend/results.js \nHandles train search results on `search/index.html`, including filtering and availability refresh.\n\nExports \n- `async function init(): Promise` – entry point: reads URL params, fetches trains \n- `async function fetchAndProcessTrains(params): Promise` \n- `function renderTrainCards(data): void` – injects direct and nearby train cards \n- `function refreshAvailability(trainId): Promise` – updates a single card\n\nInitialization in search/index.html \n```html\n\n```\n\n### home/index.html \nTrain booking homepage \n- Station autocomplete inputs (`#fromStation`, `#toStation`) \n- Route type buttons (One-way, Round-trip) \n- Search form redirects to `/search/index.html?from=…&to=…&date=…` \n- Includes Tailwind CSS utilities and `backend/index.js`\n\n### search/index.html \nSearch results page \n- Header and nav (scripts from `navbar.js`) \n- Loading and error states \n- Filter panel (class, time, availability) \n- Direct vs. nearby train sections \n- Includes `backend/results.js` for data fetching and rendering\n\n### status/index.html \nPNR status checker \n- Input field, search button \n- Sections for train details, passenger status, booking info \n- Error and retry UI \n- Imports `backend/navbar.js` and `backend/pnr.js`\n\n### train_status/index.html \nLive train tracking interface \n- Inputs: train number, date picker \n- “Track Train” button triggers API fetch \n- Displays journey timeline, station statuses, and auto-refresh \n- Includes `backend/navbar.js` and inline or dedicated script for tracking logic\n\n---\n\nNavigating the codebase by this structure helps you locate features quickly, understand entry points, and extend functionality with minimal friction.\n## Customization & Configuration\n\nThis section explains how to configure API endpoints, adjust request timeouts, enable dark mode, replace assets, and tweak UI templates.\n\n### API Base URLs & Timeouts\n\nCentralize your endpoints and timeouts in a `config.js` file:\n\n```js\n// backend/config.js\nexport default {\n stationApi: process.env.STATION_API_URL || 'https://api.irctc.co.in/stations',\n pnrApi: process.env.PNR_API_URL || 'https://api.irctc.co.in/pnr',\n searchApi: process.env.SEARCH_API_URL || 'https://api.irctc.co.in/search',\n requestTimeout: parseInt(process.env.REQUEST_TIMEOUT, 10) || 5000\n};\n```\n\nImport and use in your fetch functions:\n\n```js\n// backend/index.js\nimport config from './config';\n\nasync function fetchWithTimeout(url, options = {}) {\n const controller = new AbortController();\n const id = setTimeout(() => controller.abort(), config.requestTimeout);\n \n const res = await fetch(url, {\n ...options,\n signal: controller.signal\n });\n clearTimeout(id);\n return res.json();\n}\n\nexport async function fetchStations(query) {\n const url = `${config.stationApi}?q=${encodeURIComponent(query)}`;\n return fetchWithTimeout(url);\n}\n```\n\nOverride values via environment variables or by editing `config.js`.\n\n### Dark-Mode Styling\n\nUse CSS variables and a body class toggle. Create `dark.css`:\n\n```css\n/* assets/css/dark.css */\n:root {\n --bg-color: #121212;\n --text-color: #e0e0e0;\n --card-bg: #1e1e1e;\n}\nbody.dark-mode {\n background-color: var(--bg-color);\n color: var(--text-color);\n}\n.train-card {\n background-color: var(--card-bg);\n}\n```\n\nLoad it in your HTML and toggle via JS:\n\n```html\n\n\n\n```\n\n### Asset Replacement\n\nReplace `assets/background.jpeg` with your own image or change its reference:\n\n```css\n/* assets/css/main.css */\nbody {\n background: url('../assets/background.jpeg') no-repeat center/cover;\n}\n```\n\nTo use a different filename:\n\n1. Place `my-train.jpg` in `assets/`.\n2. Update `main.css`:\n ```css\n body {\n background: url('../assets/my-train.jpg') no-repeat center/cover;\n }\n ```\n\n### UI Template Tweaks\n\n#### Station Autocomplete (backend/index.js)\n\nDefault item renderer:\n```js\nfunction createDropdownItem(station) {\n const li = document.createElement('li');\n li.className = 'station-item';\n li.textContent = station.name;\n return li;\n}\n```\n\nTo show code and name:\n```js\nfunction createDropdownItem(station) {\n const li = document.createElement('li');\n li.className = 'station-item';\n li.innerHTML = `\n ${station.code}\n ${station.name}\n `;\n return li;\n}\n```\n\n#### PNR Status Checker (backend/pnr.js)\n\nWrap `checkPNR()` to add custom loading indicator:\n```js\nimport { checkPNR } from './pnr';\n\ndocument.getElementById('pnrForm').addEventListener('submit', async e => {\n e.preventDefault();\n const loader = document.createElement('div');\n loader.id = 'custom-loader';\n loader.textContent = 'Checking…';\n document.body.append(loader);\n\n try {\n await checkPNR();\n } finally {\n loader.remove();\n }\n});\n```\n\n#### Train Results (backend/results.js)\n\nDefault card renderer:\n```js\nfunction renderTrainCard(train) {\n return `\n
\n

${train.name}

\n ${train.availability}\n
`;\n}\n```\n\nTo include departure time:\n```js\nfunction renderTrainCard(train) {\n return `\n
\n

${train.name} (${train.number})

\n

Departs at: ${train.departureTime}

\n Status: ${train.availability}\n
`;\n}\n```\n\nPlace these functions in your own copy of `results.js` or override via module aliasing in your build setup."; document.addEventListener('DOMContentLoaded', function() { const contentDiv = AppUtils.dom.query('#documentation-content'); const tocNav = AppUtils.dom.query('#toc-nav'); const tocNavMobile = AppUtils.dom.query('#toc-nav-mobile'); // Initialize mobile menu functionality MobileMenu.init(); // Apply content styling and initialize TOC if (contentDiv) { ContentStyling.applyProseStyles(contentDiv); TableOfContents.init(contentDiv, tocNav, tocNavMobile); } // Setup quick actions QuickActions.init(tocNav, contentDiv); });