~/back-pain-pptx/build.js
const pptxgen = require("pptxgenjs");
const fs = require("fs");
const pres = new pptxgen();
pres.layout = "LAYOUT_16x9";
pres.title = "Back Pain: Differential Diagnosis, Investigations & Management";
// Load images
const img = {};
for (let i = 0; i <= 6; i++) {
const p = `/home/daytona/workspace/back-pain-pptx/img${i}.txt`;
if (fs.existsSync(p)) img[i] = fs.readFileSync(p, "utf8");
}
// Color palette — deep navy + white + crimson accent + teal highlights
const NAV = "0D1B2A"; // deep navy (dominant bg)
const NAV2 = "1A2E45"; // slightly lighter navy for cards
const WHT = "FFFFFF";
const CRM = "C0392B"; // crimson / red accent
const TEA = "1ABC9C"; // teal highlight
const GLD = "F1C40F"; // gold accent
const LGR = "BDC3C7"; // light grey
const DGR = "2C3E50"; // dark blue-grey
// Helper: slide background
function bg(slide) {
slide.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 5.625, fill: { color: NAV }, line: { color: NAV } });
}
// Helper: header bar with title
function header(slide, title, sub) {
slide.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 1.0, fill: { color: CRM }, line: { color: CRM } });
slide.addShape(pres.shapes.RECTANGLE, { x: 0, y: 1.0, w: 10, h: 0.05, fill: { color: TEA }, line: { color: TEA } });
slide.addText(title, { x: 0.3, y: 0.05, w: 9.4, h: 0.7, fontSize: 26, bold: true, color: WHT, fontFace: "Calibri", valign: "middle", margin: 0 });
if (sub) slide.addText(sub, { x: 0.3, y: 0.72, w: 9.4, h: 0.32, fontSize: 12, color: "FFCCCC", fontFace: "Calibri", valign: "middle", margin: 0 });
}
// Helper: section label
function sectionBadge(slide, text, x, y, w, color) {
slide.addShape(pres.shapes.ROUNDED_RECTANGLE, { x, y, w, h: 0.32, fill: { color: color || TEA }, line: { color: color || TEA }, rectRadius: 0.05 });
slide.addText(text, { x, y, w, h: 0.32, fontSize: 9, bold: true, color: WHT, align: "center", valign: "middle", fontFace: "Calibri", margin: 0 });
}
// Helper: card
function card(slide, x, y, w, h, fillColor) {
slide.addShape(pres.shapes.ROUNDED_RECTANGLE, { x, y, w, h, fill: { color: fillColor || NAV2 }, line: { color: "2980B9", width: 0.5 }, rectRadius: 0.08, shadow: { type: "outer", color: "000000", blur: 4, offset: 2, angle: 135, opacity: 0.25 } });
}
// ─────────────────────────────────────────────
// SLIDE 1 — TITLE SLIDE
// ─────────────────────────────────────────────
{
const s = pres.addSlide();
bg(s);
// full-width accent bar
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 0.12, h: 5.625, fill: { color: CRM }, line: { color: CRM } });
s.addShape(pres.shapes.RECTANGLE, { x: 0.12, y: 0, w: 0.06, h: 5.625, fill: { color: TEA }, line: { color: TEA } });
s.addText("BACK PAIN", { x: 0.5, y: 0.7, w: 9, h: 1.1, fontSize: 52, bold: true, color: WHT, fontFace: "Calibri", margin: 0 });
s.addText("Differential Diagnosis · Investigations · Management", { x: 0.5, y: 1.85, w: 9, h: 0.55, fontSize: 20, color: TEA, fontFace: "Calibri", margin: 0 });
s.addShape(pres.shapes.RECTANGLE, { x: 0.5, y: 2.5, w: 5, h: 0.04, fill: { color: CRM }, line: { color: CRM } });
s.addText("Family Medicine | MBBS Year 3", { x: 0.5, y: 2.65, w: 9, h: 0.4, fontSize: 15, color: LGR, fontFace: "Calibri", margin: 0 });
s.addText("Student Presentation — ~8 minutes", { x: 0.5, y: 3.1, w: 9, h: 0.35, fontSize: 13, color: "7F8C8D", fontFace: "Calibri", margin: 0 });
// Spine silhouette icon using circles
s.addShape(pres.shapes.OVAL, { x: 8.1, y: 0.8, w: 1.4, h: 1.4, fill: { color: NAV2 }, line: { color: CRM, width: 2 } });
s.addText("⚕", { x: 8.1, y: 0.85, w: 1.4, h: 1.3, fontSize: 44, color: CRM, align: "center", valign: "middle", margin: 0 });
}
// ─────────────────────────────────────────────
// SLIDE 2 — FRAMEWORK (3 BUCKETS)
// ─────────────────────────────────────────────
{
const s = pres.addSlide();
bg(s);
header(s, "THE CLINICAL FRAMEWORK", "Start every back pain consultation with this");
// 3 bucket cards
const buckets = [
{ label: "~85%", title: "NONSPECIFIC\nMECHANICAL", sub: "Muscle strain, disc, posture\nNo red flags\nSelf-limiting", color: "27AE60" },
{ label: "~10%", title: "RADICULAR\n(SCIATICA)", sub: "Nerve root irritation\nLeg pain below knee\nDermatomal pattern", color: "E67E22" },
{ label: "~5%", title: "RED FLAG\nCONDITION", sub: "Cancer · Infection\nFracture · Cauda Equina\nRequires urgent workup", color: CRM },
];
const xs = [0.25, 3.55, 6.85];
buckets.forEach((b, i) => {
card(s, xs[i], 1.2, 3.1, 3.8, NAV2);
s.addShape(pres.shapes.OVAL, { x: xs[i] + 0.9, y: 1.35, w: 1.3, h: 0.55, fill: { color: b.color }, line: { color: b.color } });
s.addText(b.label, { x: xs[i] + 0.9, y: 1.35, w: 1.3, h: 0.55, fontSize: 16, bold: true, color: WHT, align: "center", valign: "middle", fontFace: "Calibri", margin: 0 });
s.addText(b.title, { x: xs[i] + 0.1, y: 2.0, w: 2.9, h: 0.75, fontSize: 14, bold: true, color: WHT, align: "center", fontFace: "Calibri", margin: 0 });
s.addShape(pres.shapes.RECTANGLE, { x: xs[i] + 0.6, y: 2.75, w: 1.9, h: 0.03, fill: { color: b.color }, line: { color: b.color } });
s.addText(b.sub, { x: xs[i] + 0.1, y: 2.85, w: 2.9, h: 1.0, fontSize: 11, color: LGR, align: "center", fontFace: "Calibri", margin: 0 });
});
s.addText("Your primary task: RULE OUT Bucket 3 first, then manage the rest", { x: 0.3, y: 5.1, w: 9.4, h: 0.38, fontSize: 13, bold: true, color: GLD, align: "center", fontFace: "Calibri", margin: 0 });
}
// ─────────────────────────────────────────────
// SLIDE 3 — DIFFERENTIAL DIAGNOSIS TABLE
// ─────────────────────────────────────────────
{
const s = pres.addSlide();
bg(s);
header(s, "DIFFERENTIAL DIAGNOSIS", "Organised by category");
const rows = [
["MECHANICAL", "Muscle strain · Ligament sprain · Disc herniation · Facet joint pain · Spondylolysis · Spondylolisthesis", "27AE60"],
["DEGENERATIVE", "Degenerative disc disease · Spondylosis · Spinal stenosis (neurogenic claudication)", "2ECC71"],
["INFLAMMATORY", "Ankylosing spondylitis · Psoriatic arthritis · Reactive arthritis", "E67E22"],
["INFECTIOUS", "Vertebral osteomyelitis · Discitis · Epidural abscess · TB spine (Pott's disease)", CRM],
["NEOPLASTIC", "Spinal metastases · Multiple myeloma · Primary spinal tumours · Leukaemia/Lymphoma", "9B59B6"],
["VASCULAR", "AAA · Aortic dissection · Spinal epidural haematoma · Spinal AVM", "E74C3C"],
["REFERRED / VISCERAL", "Renal colic · Pyelonephritis · Pancreatitis · Ovarian/testicular · Ectopic pregnancy · MI · PE", "3498DB"],
];
rows.forEach((r, i) => {
const y = 1.15 + i * 0.6;
s.addShape(pres.shapes.RECTANGLE, { x: 0.15, y, w: 2.1, h: 0.5, fill: { color: r[2] }, line: { color: r[2] } });
s.addText(r[0], { x: 0.15, y, w: 2.1, h: 0.5, fontSize: 9.5, bold: true, color: WHT, align: "center", valign: "middle", fontFace: "Calibri", margin: 0 });
s.addShape(pres.shapes.RECTANGLE, { x: 2.3, y, w: 7.5, h: 0.5, fill: { color: NAV2 }, line: { color: r[2], width: 0.8 } });
s.addText(r[1], { x: 2.35, y, w: 7.4, h: 0.5, fontSize: 10.5, color: WHT, valign: "middle", fontFace: "Calibri", margin: 0 });
});
}
// ─────────────────────────────────────────────
// SLIDE 4 — CLINICAL CLUES
// ─────────────────────────────────────────────
{
const s = pres.addSlide();
bg(s);
header(s, "CLINICAL CLUES AT A GLANCE", "Pain pattern → likely cause");
const clues = [
["Movement ↑ pain, rest relieves, no neurology", "Mechanical / Muscle strain", "27AE60"],
["Leg pain below knee, dermatomal, worse with Valsalva", "Disc herniation / Sciatica", "E67E22"],
["Bilateral leg pain walking, shopping cart sign", "Spinal stenosis", "3498DB"],
["Young man, morning stiffness >1hr, improves with exercise", "Ankylosing spondylitis", "E67E22"],
["Age >50, night pain, weight loss", "Malignancy ⚠", CRM],
["Fever + back pain + IVDU/DM/immunocompromised", "Osteomyelitis / Epidural abscess ⚠", CRM],
["Saddle numbness + urinary retention", "Cauda Equina — EMERGENCY 🚨", "8E44AD"],
["Colicky flank → groin + haematuria", "Renal colic (referred)", "3498DB"],
["Tearing back pain + pulsatile mass + hypotension", "Ruptured AAA — EMERGENCY 🚨", "8E44AD"],
["Back pain in a CHILD", "Always red flag — investigate", CRM],
];
clues.forEach((c, i) => {
const col = i < 5 ? 0 : 1;
const row = i < 5 ? i : i - 5;
const x = col === 0 ? 0.15 : 5.1;
const y = 1.15 + row * 0.82;
s.addShape(pres.shapes.ROUNDED_RECTANGLE, { x, y, w: 4.8, h: 0.72, fill: { color: NAV2 }, line: { color: c[2], width: 1 }, rectRadius: 0.06 });
s.addShape(pres.shapes.RECTANGLE, { x, y, w: 0.08, h: 0.72, fill: { color: c[2] }, line: { color: c[2] } });
s.addText(c[0], { x: x + 0.15, y: y + 0.03, w: 4.6, h: 0.32, fontSize: 9.5, color: LGR, fontFace: "Calibri", margin: 0 });
s.addText("→ " + c[1], { x: x + 0.15, y: y + 0.35, w: 4.6, h: 0.3, fontSize: 10, bold: true, color: WHT, fontFace: "Calibri", margin: 0 });
});
}
// ─────────────────────────────────────────────
// SLIDE 5 — DISC HERNIATION + MRI IMAGE
// ─────────────────────────────────────────────
{
const s = pres.addSlide();
bg(s);
header(s, "DISC HERNIATION & RADICULOPATHY", "Most important specific cause to understand");
// Left content
const steps = [
"Ageing → loss of nucleus water content",
"Annulus fibrosus thins and tears",
"Nucleus pulposus herniates — usually posterolateral",
"Compresses and inflames adjacent nerve root",
"→ RADICULOPATHY (pain + numbness + weakness)",
];
const stepColors = [TEA, TEA, TEA, CRM, GLD];
steps.forEach((st, i) => {
const y = 1.25 + i * 0.6;
s.addShape(pres.shapes.OVAL, { x: 0.2, y: y + 0.05, w: 0.4, h: 0.4, fill: { color: stepColors[i] }, line: { color: stepColors[i] } });
s.addText(`${i + 1}`, { x: 0.2, y: y + 0.05, w: 0.4, h: 0.4, fontSize: 11, bold: true, color: WHT, align: "center", valign: "middle", fontFace: "Calibri", margin: 0 });
s.addText(st, { x: 0.7, y, w: 4.8, h: 0.55, fontSize: 12, color: i >= 3 ? GLD : WHT, fontFace: "Calibri", valign: "middle", bold: i >= 3, margin: 0 });
});
// Nerve root table
s.addShape(pres.shapes.RECTANGLE, { x: 0.2, y: 4.25, w: 5.1, h: 0.25, fill: { color: CRM }, line: { color: CRM } });
s.addText("Nerve Root Map", { x: 0.2, y: 4.25, w: 5.1, h: 0.25, fontSize: 10, bold: true, color: WHT, align: "center", valign: "middle", fontFace: "Calibri", margin: 0 });
const nrRows = [
["L4", "Knee extension", "Medial shin", "Knee jerk ↓"],
["L5 (most common)", "Foot dorsiflexion", "Dorsum foot", "No reliable reflex"],
["S1", "Plantarflexion", "Lateral foot/sole", "Ankle jerk ↓"],
];
const nrW = [0.9, 1.4, 1.3, 1.5];
const nrX = [0.2, 1.1, 2.5, 3.8];
nrRows.forEach((row, ri) => {
const y = 4.5 + ri * 0.35;
const bg2 = ri % 2 === 0 ? NAV2 : "152638";
s.addShape(pres.shapes.RECTANGLE, { x: 0.2, y, w: 5.1, h: 0.33, fill: { color: bg2 }, line: { color: bg2 } });
row.forEach((cell, ci) => {
s.addText(cell, { x: nrX[ci], y, w: nrW[ci], h: 0.33, fontSize: 9, color: ci === 0 ? GLD : WHT, bold: ci === 0, fontFace: "Calibri", valign: "middle", margin: 3 });
});
});
// Right: MRI image
if (img[0]) {
s.addImage({ data: img[0], x: 5.55, y: 1.2, w: 4.2, h: 4.1 });
s.addShape(pres.shapes.RECTANGLE, { x: 5.55, y: 5.1, w: 4.2, h: 0.2, fill: { color: DGR }, line: { color: DGR } });
s.addText("MRI axial — L4/5 disc herniation compressing right L5 nerve root", { x: 5.55, y: 5.1, w: 4.2, h: 0.22, fontSize: 7.5, color: LGR, italic: true, align: "center", fontFace: "Calibri", margin: 0 });
}
}
// ─────────────────────────────────────────────
// SLIDE 6 — SPINAL STENOSIS
// ─────────────────────────────────────────────
{
const s = pres.addSlide();
bg(s);
header(s, "SPINAL STENOSIS", "Neurogenic claudication — common in the elderly");
// Left content
s.addText("What happens:", { x: 0.2, y: 1.15, w: 5.1, h: 0.35, fontSize: 13, bold: true, color: TEA, fontFace: "Calibri", margin: 0 });
const causes = ["Thickened ligamentum flavum", "Facet joint hypertrophy + osteophytes", "Disc bulging centrally", "→ Narrows spinal canal / neural foramina", "→ Compresses cauda equina nerve roots"];
causes.forEach((c, i) => {
s.addText((i < 3 ? "• " : "") + c, { x: 0.3, y: 1.55 + i * 0.38, w: 5.1, h: 0.35, fontSize: 11.5, color: i >= 3 ? GLD : WHT, bold: i >= 3, fontFace: "Calibri", margin: 0 });
});
s.addText("Neurogenic Claudication", { x: 0.2, y: 3.55, w: 5.1, h: 0.35, fontSize: 13, bold: true, color: CRM, fontFace: "Calibri", margin: 0 });
const claudRows = [
["Worse with", "Walking, standing, back extension"],
["Better with", "Sitting, bending forward (shopping cart sign)"],
["Pulses", "Normal (unlike vascular claudication)"],
["Imaging", "MRI shows canal narrowing"],
];
claudRows.forEach((row, i) => {
const y = 3.95 + i * 0.38;
s.addShape(pres.shapes.RECTANGLE, { x: 0.2, y, w: 1.3, h: 0.33, fill: { color: CRM }, line: { color: CRM } });
s.addText(row[0], { x: 0.2, y, w: 1.3, h: 0.33, fontSize: 10, bold: true, color: WHT, align: "center", valign: "middle", fontFace: "Calibri", margin: 0 });
s.addShape(pres.shapes.RECTANGLE, { x: 1.55, y, w: 3.75, h: 0.33, fill: { color: NAV2 }, line: { color: NAV2 } });
s.addText(row[1], { x: 1.6, y, w: 3.7, h: 0.33, fontSize: 10.5, color: WHT, valign: "middle", fontFace: "Calibri", margin: 0 });
});
// Right: MRI image
if (img[1]) {
s.addImage({ data: img[1], x: 5.55, y: 1.2, w: 4.2, h: 3.8 });
s.addText("MRI — central canal stenosis (A=normal, B=stenosis with ligamentum flavum thickening)", { x: 5.55, y: 5.05, w: 4.2, h: 0.32, fontSize: 7.5, color: LGR, italic: true, align: "center", fontFace: "Calibri", margin: 0 });
}
}
// ─────────────────────────────────────────────
// SLIDE 7 — ANKYLOSING SPONDYLITIS
// ─────────────────────────────────────────────
{
const s = pres.addSlide();
bg(s);
header(s, "ANKYLOSING SPONDYLITIS", "Inflammatory back pain — axial spondyloarthritis");
// Content left
const features = [
["Patient", "Young male, onset <40 years"],
["Onset", "Insidious, gradual over months"],
["Pain", "Lower back, buttocks, sacroiliac joints"],
["Morning stiffness", ">1 hour — hallmark feature"],
["Improves with", "Exercise, movement — NOT rest"],
["Night pain", "Wakes patient, improves on getting up"],
["HLA-B27", "Positive in ~90%"],
["Hallmark imaging", "Bilateral sacroiliitis → bamboo spine"],
];
features.forEach((f, i) => {
const y = 1.2 + i * 0.51;
s.addShape(pres.shapes.RECTANGLE, { x: 0.2, y, w: 2.2, h: 0.43, fill: { color: "E67E22" }, line: { color: "E67E22" } });
s.addText(f[0], { x: 0.2, y, w: 2.2, h: 0.43, fontSize: 10, bold: true, color: WHT, align: "center", valign: "middle", fontFace: "Calibri", margin: 0 });
s.addShape(pres.shapes.RECTANGLE, { x: 2.45, y, w: 3.05, h: 0.43, fill: { color: NAV2 }, line: { color: NAV2 } });
s.addText(f[1], { x: 2.5, y, w: 3.0, h: 0.43, fontSize: 10.5, color: WHT, valign: "middle", fontFace: "Calibri", margin: 0 });
});
// Right: AS/bamboo spine image
if (img[4]) {
s.addImage({ data: img[4], x: 5.7, y: 1.2, w: 4.1, h: 4.0 });
s.addText("X-ray: Bamboo spine (syndesmophytes) + bilateral sacroiliitis", { x: 5.7, y: 5.2, w: 4.1, h: 0.25, fontSize: 7.5, color: LGR, italic: true, align: "center", fontFace: "Calibri", margin: 0 });
}
}
// ─────────────────────────────────────────────
// SLIDE 8 — SPINAL INFECTION
// ─────────────────────────────────────────────
{
const s = pres.addSlide();
bg(s);
header(s, "SPINAL INFECTION", "Osteomyelitis · Discitis · Epidural Abscess");
// Left: risk factors + features
s.addText("Risk Factors", { x: 0.2, y: 1.15, w: 4.8, h: 0.35, fontSize: 13, bold: true, color: CRM, fontFace: "Calibri", margin: 0 });
const risks = ["IV drug use (IVDU)", "Diabetes mellitus", "Immunosuppression / HIV", "Recent spinal surgery / UTI", "TB history (endemic areas)"];
risks.forEach((r, i) => {
s.addShape(pres.shapes.OVAL, { x: 0.2, y: 1.55 + i * 0.38, w: 0.22, h: 0.22, fill: { color: CRM }, line: { color: CRM } });
s.addText(r, { x: 0.5, y: 1.52 + i * 0.38, w: 4.5, h: 0.3, fontSize: 11, color: WHT, fontFace: "Calibri", margin: 0 });
});
s.addText("Clinical Features", { x: 0.2, y: 3.55, w: 4.8, h: 0.35, fontSize: 13, bold: true, color: GLD, fontFace: "Calibri", margin: 0 });
const feats = ["Fever + severe, localised back pain", "Point tenderness over spinous process", "Progressive neurological deficit (late)", "↑ ESR, ↑ CRP, ↑ WBC"];
feats.forEach((f, i) => {
s.addShape(pres.shapes.OVAL, { x: 0.2, y: 3.95 + i * 0.38, w: 0.22, h: 0.22, fill: { color: GLD }, line: { color: GLD } });
s.addText(f, { x: 0.5, y: 3.92 + i * 0.38, w: 4.5, h: 0.3, fontSize: 11, color: WHT, fontFace: "Calibri", margin: 0 });
});
// Right: MRI infection image
if (img[5]) {
s.addImage({ data: img[5], x: 5.4, y: 1.2, w: 4.4, h: 4.1 });
s.addText("MRI — Discitis-osteomyelitis L2/3 with endplate destruction + psoas involvement", { x: 5.4, y: 5.3, w: 4.4, h: 0.28, fontSize: 7.5, color: LGR, italic: true, align: "center", fontFace: "Calibri", margin: 0 });
}
}
// ─────────────────────────────────────────────
// SLIDE 9 — CAUDA EQUINA SYNDROME
// ─────────────────────────────────────────────
{
const s = pres.addSlide();
bg(s);
// Red urgency header
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 1.0, fill: { color: "8E0000" }, line: { color: "8E0000" } });
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 1.0, w: 10, h: 0.05, fill: { color: GLD }, line: { color: GLD } });
s.addText("⚠ CAUDA EQUINA SYNDROME — SURGICAL EMERGENCY", { x: 0.2, y: 0.08, w: 9.6, h: 0.85, fontSize: 22, bold: true, color: WHT, fontFace: "Calibri", valign: "middle", margin: 0 });
// Left: Features
s.addText("Features — ALL must be screened for:", { x: 0.2, y: 1.15, w: 4.9, h: 0.38, fontSize: 12, bold: true, color: GLD, fontFace: "Calibri", margin: 0 });
const cesFeats = [
["SADDLE ANAESTHESIA", "Numbness around anus, perineum, genitals — pathognomonic"],
["URINARY RETENTION", "Painless — patient cannot feel a full bladder"],
["URINARY INCONTINENCE", "Or altered urinary sensation"],
["FAECAL INCONTINENCE", "Loss of rectal fullness sensation"],
["BILATERAL LEG WEAKNESS", "Major motor deficit: hip flexors, knee, foot"],
["REDUCED ANAL TONE", "On digital rectal examination"],
];
cesFeats.forEach((f, i) => {
const y = 1.6 + i * 0.56;
s.addShape(pres.shapes.RECTANGLE, { x: 0.2, y, w: 2.0, h: 0.48, fill: { color: "8E0000" }, line: { color: "8E0000" } });
s.addText(f[0], { x: 0.2, y, w: 2.0, h: 0.48, fontSize: 8.5, bold: true, color: WHT, align: "center", valign: "middle", fontFace: "Calibri", margin: 0 });
s.addShape(pres.shapes.RECTANGLE, { x: 2.25, y, w: 2.8, h: 0.48, fill: { color: NAV2 }, line: { color: NAV2 } });
s.addText(f[1], { x: 2.3, y, w: 2.75, h: 0.48, fontSize: 10, color: LGR, valign: "middle", fontFace: "Calibri", margin: 0 });
});
// Action box
s.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 0.2, y: 5.0, w: 5.1, h: 0.42, fill: { color: "8E0000" }, line: { color: GLD, width: 2 }, rectRadius: 0.06 });
s.addText("ACTION: Same-day EMERGENCY MRI → Neurosurgical referral", { x: 0.2, y: 5.0, w: 5.1, h: 0.42, fontSize: 11, bold: true, color: GLD, align: "center", valign: "middle", fontFace: "Calibri", margin: 0 });
// Right: CES classification table image
if (img[3]) {
s.addImage({ data: img[3], x: 5.45, y: 1.15, w: 4.4, h: 3.5 });
s.addText("CES Classification — Bailey & Love's Surgery 28E", { x: 5.45, y: 4.7, w: 4.4, h: 0.25, fontSize: 7.5, color: LGR, italic: true, align: "center", fontFace: "Calibri", margin: 0 });
}
}
// ─────────────────────────────────────────────
// SLIDE 10 — EXAMINATION
// ─────────────────────────────────────────────
{
const s = pres.addSlide();
bg(s);
header(s, "EXAMINATION OF THE BACK", "Look · Feel · Move · Special Tests");
// 4 quadrant layout
const quads = [
{
title: "LOOK", color: TEA,
items: ["Scoliosis / kyphosis / lordosis loss", "Paraspinal muscle wasting or spasm", "Skin: hairy tuft/dimple = spina bifida", "Haematoma, bruising (trauma)"]
},
{
title: "FEEL", color: "E67E22",
items: ["Spinous process percussion tenderness", " → fracture / infection / tumour", "Paraspinal muscle spasm", "Step-off deformity → spondylolisthesis"]
},
{
title: "MOVE", color: "3498DB",
items: ["Flexion 40–60° (pain = discogenic)", "Extension 20–35° (pain = facet/spondylolysis)", "Lateral bending, rotation", "Schober's test for ankylosing spondylitis"]
},
{
title: "SPECIAL TESTS", color: CRM,
items: ["SLR (Lasègue): 30–70° leg pain → L4/5/S1", "Crossed SLR: specific for disc extrusion", "Femoral stretch: L2/3/4 radiculopathy", "Saddle sensation + anal tone (CES screen)"]
}
];
const qx = [0.15, 5.1, 0.15, 5.1];
const qy = [1.15, 1.15, 3.45, 3.45];
quads.forEach((q, i) => {
card(s, qx[i], qy[i], 4.7, 2.0, NAV2);
s.addShape(pres.shapes.RECTANGLE, { x: qx[i], y: qy[i], w: 4.7, h: 0.38, fill: { color: q.color }, line: { color: q.color } });
s.addText(q.title, { x: qx[i], y: qy[i], w: 4.7, h: 0.38, fontSize: 13, bold: true, color: WHT, align: "center", valign: "middle", fontFace: "Calibri", margin: 0 });
q.items.forEach((item, j) => {
s.addText("• " + item, { x: qx[i] + 0.15, y: qy[i] + 0.45 + j * 0.37, w: 4.4, h: 0.35, fontSize: 10, color: WHT, fontFace: "Calibri", margin: 0 });
});
});
}
// ─────────────────────────────────────────────
// SLIDE 11 — SLR TEST + image
// ─────────────────────────────────────────────
{
const s = pres.addSlide();
bg(s);
header(s, "STRAIGHT LEG RAISE (SLR) TEST", "Lasègue's sign — the key test for radiculopathy");
// Steps
const steps = [
"Patient lies SUPINE on examination table",
"Examiner raises leg with knee FULLY EXTENDED",
"Positive: pain radiates DOWN the leg (not just back) between 30°–70°",
"Add ankle dorsiflexion → increases sciatic tension (confirms result)",
"Tests L4, L5, S1 nerve roots",
];
const sColors = [TEA, TEA, CRM, GLD, "3498DB"];
steps.forEach((st, i) => {
const y = 1.2 + i * 0.64;
s.addShape(pres.shapes.OVAL, { x: 0.2, y: y + 0.1, w: 0.38, h: 0.38, fill: { color: sColors[i] }, line: { color: sColors[i] } });
s.addText(`${i + 1}`, { x: 0.2, y: y + 0.1, w: 0.38, h: 0.38, fontSize: 11, bold: true, color: WHT, align: "center", valign: "middle", fontFace: "Calibri", margin: 0 });
s.addText(st, { x: 0.7, y, w: 4.8, h: 0.58, fontSize: 11.5, color: i >= 2 ? GLD : WHT, bold: i >= 2, fontFace: "Calibri", valign: "middle", margin: 0 });
});
// Stats box
s.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 0.2, y: 4.55, w: 4.9, h: 0.75, fill: { color: NAV2 }, line: { color: TEA, width: 1.5 }, rectRadius: 0.08 });
s.addText([
{ text: "Sensitivity: ", options: { color: LGR } },
{ text: "85–91% ", options: { color: GLD, bold: true } },
{ text: " Specificity: ", options: { color: LGR } },
{ text: "26–52%", options: { color: GLD, bold: true } },
], { x: 0.2, y: 4.55, w: 4.9, h: 0.4, fontSize: 12, fontFace: "Calibri", align: "center", valign: "middle", margin: 0 });
s.addText("Crossed SLR — sensitivity 23–34%, specificity 86–90% (specific for extrusion)", { x: 0.2, y: 4.95, w: 4.9, h: 0.32, fontSize: 9.5, color: LGR, italic: true, align: "center", fontFace: "Calibri", margin: 0 });
// Right: SLR image
if (img[2]) {
s.addImage({ data: img[2], x: 5.4, y: 1.2, w: 4.4, h: 4.1 });
s.addText("Clinical illustration — Straight Leg Raise (Lasègue's test)", { x: 5.4, y: 5.3, w: 4.4, h: 0.25, fontSize: 7.5, color: LGR, italic: true, align: "center", fontFace: "Calibri", margin: 0 });
}
}
// ─────────────────────────────────────────────
// SLIDE 12 — INVESTIGATIONS
// ─────────────────────────────────────────────
{
const s = pres.addSlide();
bg(s);
header(s, "INVESTIGATIONS", "When to investigate and what to order");
// Imaging rule banner
s.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 0.2, y: 1.1, w: 9.6, h: 0.5, fill: { color: "1A5276" }, line: { color: TEA, width: 1.5 }, rectRadius: 0.06 });
s.addText("⚠ DO NOT IMAGE in first 6 weeks if NO red flags — 1 in 4 asymptomatic adults have MRI disc findings (false positives lead to harm)", { x: 0.25, y: 1.1, w: 9.5, h: 0.5, fontSize: 10.5, bold: true, color: GLD, align: "center", valign: "middle", fontFace: "Calibri", margin: 0 });
const invRows = [
["BLOODS\n(FBC, ESR, CRP,\nCa²⁺, PSA, LFTs)", "Suspected infection or malignancy\nor inflammatory disease", "↑ ESR/CRP in infection & malignancy;\nPSA for prostate; Ca²⁺ for mets", "27AE60"],
["X-RAY SPINE", "Trauma (alignment), scoliosis,\nosteoporotic fracture", "Cannot detect early infection/tumour —\nneeds 40–60% bone destruction first", "E67E22"],
["MRI SPINE ✅\n(Investigation of choice)", "Any red flag present;\n>6 wks no improvement;\nSuspected cord/cauda equina", "Sensitivity & specificity >90% for\nmalignancy, infection, epidural lesions;\nUse with contrast for abscess/mets", CRM],
["CT SPINE", "Trauma (best for bone detail);\nMRI contraindicated", "Radiation = 300 chest X-rays;\nnot first-line", "9B59B6"],
["USS / CT ABDOMEN", "Suspected AAA", "Urgent USS if stable;\nCT angiogram if urgent", "3498DB"],
["URINE DIPSTICK/\nCULTURE", "Suspected pyelonephritis\nor renal colic", "Simple, fast, first-line for\nreferred causes", TEA],
];
invRows.forEach((row, i) => {
const y = 1.7 + i * 0.61;
s.addShape(pres.shapes.RECTANGLE, { x: 0.15, y, w: 1.85, h: 0.53, fill: { color: row[3] }, line: { color: row[3] } });
s.addText(row[0], { x: 0.15, y, w: 1.85, h: 0.53, fontSize: 8.5, bold: true, color: WHT, align: "center", valign: "middle", fontFace: "Calibri", margin: 0 });
s.addShape(pres.shapes.RECTANGLE, { x: 2.05, y, w: 3.6, h: 0.53, fill: { color: NAV2 }, line: { color: row[3], width: 0.5 } });
s.addText(row[1], { x: 2.1, y, w: 3.55, h: 0.53, fontSize: 9.5, color: WHT, valign: "middle", fontFace: "Calibri", margin: 0 });
s.addShape(pres.shapes.RECTANGLE, { x: 5.7, y, w: 4.1, h: 0.53, fill: { color: "152638" }, line: { color: row[3], width: 0.5 } });
s.addText(row[2], { x: 5.75, y, w: 4.0, h: 0.53, fontSize: 9.5, color: LGR, valign: "middle", fontFace: "Calibri", italic: true, margin: 0 });
});
}
// ─────────────────────────────────────────────
// SLIDE 13 — EVALUATION ALGORITHM (with flowchart image)
// ─────────────────────────────────────────────
{
const s = pres.addSlide();
bg(s);
header(s, "EVALUATION ALGORITHM", "Goldman-Cecil Medicine — acute & subacute back pain");
if (img[6]) {
s.addImage({ data: img[6], x: 0.5, y: 1.1, w: 9.0, h: 4.3 });
}
s.addText("If red flags detected → urgent MRI ± specialist referral. No red flags → treat conservatively; image if not improved at 6 weeks", { x: 0.3, y: 5.2, w: 9.4, h: 0.28, fontSize: 9.5, color: LGR, italic: true, align: "center", fontFace: "Calibri", margin: 0 });
}
// ─────────────────────────────────────────────
// SLIDE 14 — MANAGEMENT: MECHANICAL BACK PAIN
// ─────────────────────────────────────────────
{
const s = pres.addSlide();
bg(s);
header(s, "MANAGEMENT — MECHANICAL BACK PAIN", "The majority of patients — treat conservatively");
const steps = [
{ num: "1", title: "REASSURE", body: "90% resolve in 6–12 weeks\nBack pain = rarely serious\nAvoid over-investigation and labelling", color: "27AE60" },
{ num: "2", title: "STAY ACTIVE", body: "Bed rest is HARMFUL and delays recovery\nEncourage normal activity as tolerated\nAerobic exercise + core strengthening", color: TEA },
{ num: "3", title: "ANALGESIA", body: "1st line: Paracetamol + NSAIDs (ibuprofen/diclofenac)\nAdd: Short-course muscle relaxant (spasm)\nAvoid: Long-term opioids (dependency risk)", color: "E67E22" },
{ num: "4", title: "PHYSIOTHERAPY", body: "Manual therapy, stretching, posture correction\nNICE guideline recommends as 1st-line\nAcupuncture: some evidence for chronic pain", color: "3498DB" },
{ num: "5", title: "REVIEW AT 6 WEEKS", body: "If not improving → MRI and re-assess\nScreen for yellow flags (psychosocial)\nCBT if central sensitisation suspected", color: "9B59B6" },
];
steps.forEach((st, i) => {
const col = i < 3 ? 0 : (i === 3 ? 0 : 1);
const x = [0.2, 5.15, 0.2, 5.15, 2.65][i];
const y = [1.15, 1.15, 3.15, 3.15, 1.15][i];
const w = i === 4 ? 4.7 : 4.7;
const h = 1.8;
card(s, x, y, w, h, NAV2);
s.addShape(pres.shapes.RECTANGLE, { x, y, w, h: 0.38, fill: { color: st.color }, line: { color: st.color } });
s.addText(`${st.num}. ${st.title}`, { x: x, y, w, h: 0.38, fontSize: 12, bold: true, color: WHT, align: "center", valign: "middle", fontFace: "Calibri", margin: 0 });
s.addText(st.body, { x: x + 0.15, y: y + 0.45, w: w - 0.25, h: 1.25, fontSize: 10, color: WHT, fontFace: "Calibri", margin: 0 });
});
// Bottom note
s.addShape(pres.shapes.RECTANGLE, { x: 0.2, y: 5.1, w: 9.6, h: 0.35, fill: { color: "1A5276" }, line: { color: "1A5276" } });
s.addText("Radiculopathy (sciatica): add Gabapentin/Pregabalin for neuropathic pain • Epidural steroid injection if no improvement • Surgery only if progressive deficit", { x: 0.25, y: 5.1, w: 9.5, h: 0.35, fontSize: 9.5, color: LGR, align: "center", valign: "middle", fontFace: "Calibri", margin: 0 });
}
// ─────────────────────────────────────────────
// SLIDE 15 — MANAGEMENT: SPECIFIC RED FLAG CONDITIONS
// ─────────────────────────────────────────────
{
const s = pres.addSlide();
bg(s);
header(s, "MANAGEMENT — RED FLAG CONDITIONS", "Specific urgency and treatment for each cause");
const conditions = [
{ title: "CAUDA EQUINA", action: "Emergency MRI same day → neurosurgery → surgical decompression within hours", urgency: "EMERGENCY", color: "8E0000" },
{ title: "MALIGNANCY", action: "Oncology referral (2-week cancer pathway) · MRI with contrast · Radiotherapy / chemotherapy / surgical decompression", urgency: "URGENT", color: "9B59B6" },
{ title: "SPINAL INFECTION", action: "Urgent MRI + blood cultures + FBC/CRP/ESR · IV antibiotics (after cultures) · Neurosurgical referral if abscess or neuro deficit", urgency: "URGENT", color: CRM },
{ title: "VERTEBRAL FRACTURE (stable)", action: "Analgesia · Orthopaedic review · Osteoporosis treatment · Consider vertebroplasty/kyphoplasty for ongoing pain", urgency: "SEMI-URGENT", color: "E67E22" },
{ title: "RUPTURED AAA", action: "Do NOT delay for imaging if unstable · Urgent vascular surgery · IV access + resuscitation · CT aortogram if stable", urgency: "LIFE-THREATENING", color: "8E0000" },
{ title: "ANKYLOSING SPONDYLITIS", action: "Rheumatology referral · NSAIDs (1st line) · DMARDs (sulfasalazine) · Biologics (TNF inhibitors, IL-17 inhibitors) if refractory · Physio", urgency: "PLANNED", color: "E67E22" },
];
conditions.forEach((c, i) => {
const y = 1.15 + i * 0.72;
s.addShape(pres.shapes.RECTANGLE, { x: 0.15, y, w: 0.8, h: 0.62, fill: { color: c.color }, line: { color: c.color } });
s.addText(c.urgency, { x: 0.15, y, w: 0.8, h: 0.62, fontSize: 7, bold: true, color: WHT, align: "center", valign: "middle", fontFace: "Calibri", margin: 0 });
s.addShape(pres.shapes.RECTANGLE, { x: 1.0, y, w: 2.3, h: 0.62, fill: { color: c.color }, line: { color: c.color } });
s.addText(c.title, { x: 1.0, y, w: 2.3, h: 0.62, fontSize: 11, bold: true, color: WHT, align: "center", valign: "middle", fontFace: "Calibri", margin: 0 });
s.addShape(pres.shapes.RECTANGLE, { x: 3.35, y, w: 6.45, h: 0.62, fill: { color: NAV2 }, line: { color: c.color, width: 0.8 } });
s.addText(c.action, { x: 3.4, y, w: 6.35, h: 0.62, fontSize: 10, color: WHT, valign: "middle", fontFace: "Calibri", margin: 0 });
});
s.addShape(pres.shapes.RECTANGLE, { x: 0.15, y: 5.25, w: 9.7, h: 0.22, fill: { color: NAV2 }, line: { color: NAV2 } });
s.addText("Chronic LBP: Multimodal — exercise + CBT (cognitive behavioural therapy) + analgesia + address yellow flags (psychosocial)", { x: 0.2, y: 5.25, w: 9.6, h: 0.22, fontSize: 9, color: LGR, align: "center", fontFace: "Calibri", margin: 0 });
}
// ─────────────────────────────────────────────
// SLIDE 16 — WHEN TO REFER
// ─────────────────────────────────────────────
{
const s = pres.addSlide();
bg(s);
header(s, "WHEN & WHERE TO REFER", "Matching the patient to the right team");
const refs = [
{ who: "Neurosurgery", when: "Cauda equina symptoms\nProgressive neurological deficit", urgent: "SAME DAY", color: "8E0000" },
{ who: "Vascular Surgery", when: "Suspected ruptured AAA\nAortic dissection", urgent: "IMMEDIATE", color: "8E0000" },
{ who: "Oncology", when: "Suspected malignancy\n(weight loss + night pain + age >50)", urgent: "2-WEEK PATHWAY", color: "9B59B6" },
{ who: "Infectious Disease /\nNeurosurgery", when: "Spinal infection (abscess, osteomyelitis)\nEspecially if neurological deficit", urgent: "URGENT", color: CRM },
{ who: "Rheumatology", when: "Ankylosing spondylitis\nInflammatory back pain", urgent: "PLANNED", color: "E67E22" },
{ who: "Orthopaedics /\nNeurosurgery", when: "Spinal stenosis refractory to conservative Rx\nDisc herniation > 6–12 weeks, failing Rx", urgent: "PLANNED", color: "3498DB" },
{ who: "Physiotherapy\n± Pain Clinic", when: "Mechanical back pain failing 6 weeks Rx\nChronic LBP — multimodal needed", urgent: "ROUTINE", color: "27AE60" },
];
const cols = [0, 0, 0, 1, 1, 1, 1];
const xPos = [0.2, 0.2, 0.2, 5.1, 5.1, 5.1, 5.1];
let leftRow = 0, rightRow = 0;
refs.forEach((r, i) => {
const col = cols[i];
const row = col === 0 ? leftRow++ : rightRow++;
const x = xPos[i];
const y = 1.15 + row * 1.38;
const h = 1.28;
card(s, x, y, 4.75, h, NAV2);
s.addShape(pres.shapes.RECTANGLE, { x, y, w: 4.75, h: 0.3, fill: { color: r.color }, line: { color: r.color } });
s.addText(r.who + " | " + r.urgent, { x, y, w: 4.75, h: 0.3, fontSize: 10, bold: true, color: WHT, align: "center", valign: "middle", fontFace: "Calibri", margin: 0 });
s.addText(r.when, { x: x + 0.15, y: y + 0.36, w: 4.45, h: 0.88, fontSize: 10.5, color: WHT, fontFace: "Calibri", margin: 0 });
});
}
// ─────────────────────────────────────────────
// Write file
// ─────────────────────────────────────────────
pres.writeFile({ fileName: "/home/daytona/workspace/back-pain-pptx/BackPain_FamilyMedicine.pptx" })
.then(() => console.log("✅ DONE: BackPain_FamilyMedicine.pptx"))
.catch(e => { console.error("ERROR:", e); process.exit(1); });