Make ppt with individual images
mkdir -p /home/daytona/workspace/microbiology-ppt && node /home/daytona/skills/s…
~/microbiology-ppt/create_ppt.js
const pptxgen = require("pptxgenjs");
const fs = require("fs");
const imagesData = JSON.parse(fs.readFileSync("/home/daytona/workspace/microbiology-ppt/images.json", "utf8"));
const slides = [
{
title: "3.2 Morphology and Classification of Bacteria",
subtitle: "Part 1: Basic Shapes (Groups 1–3)",
},
{
title: "Morphology & Classification (Cont.) + Arrangement of Bacterial Cells",
subtitle: "Part 2: Shapes 4–7 & Cell Arrangements",
},
{
title: "Difference Between Gram Positive and Gram Negative Bacteria",
subtitle: "Paper II – Microbiology and Pathology",
},
];
let pres = new pptxgen();
pres.layout = "LAYOUT_16x9";
pres.title = "Microbiology and Pathology – Bacterial Morphology";
// --- Title slide ---
let titleSlide = pres.addSlide();
titleSlide.background = { color: "1A237E" };
titleSlide.addShape(pres.ShapeType.rect, {
x: 0, y: 0, w: "100%", h: "100%",
fill: { type: "solid", color: "1A237E" },
line: { color: "1A237E" }
});
// Decorative accent bar
titleSlide.addShape(pres.ShapeType.rect, {
x: 0, y: 2.4, w: "100%", h: 0.06,
fill: { color: "7C4DFF" },
line: { color: "7C4DFF" }
});
titleSlide.addText("Microbiology & Pathology", {
x: 0.5, y: 0.5, w: 9, h: 0.8,
fontSize: 14, color: "B39DDB", bold: false, align: "center",
fontFace: "Calibri", charSpacing: 4
});
titleSlide.addText("Bacterial Morphology\n& Classification", {
x: 0.5, y: 1.3, w: 9, h: 1.4,
fontSize: 36, color: "FFFFFF", bold: true, align: "center",
fontFace: "Calibri"
});
titleSlide.addText("Paper II – Microbiology and Pathology", {
x: 0.5, y: 2.7, w: 9, h: 0.5,
fontSize: 14, color: "CE93D8", align: "center", fontFace: "Calibri"
});
const topics = ["Bacterial Shapes (7 Groups)", "Arrangement of Bacterial Cells", "Gram +ve vs Gram -ve Bacteria"];
const topicColors = ["7C4DFF", "9C27B0", "AB47BC"];
let topicX = 0.5;
topics.forEach((t, i) => {
titleSlide.addShape(pres.ShapeType.roundRect, {
x: topicX, y: 3.4, w: 2.9, h: 0.6,
fill: { color: topicColors[i] },
line: { color: topicColors[i] },
rectRadius: 0.05
});
titleSlide.addText(t, {
x: topicX, y: 3.4, w: 2.9, h: 0.6,
fontSize: 11, color: "FFFFFF", bold: true, align: "center",
fontFace: "Calibri", valign: "middle"
});
topicX += 3.1;
});
titleSlide.addText("Section 3.2 | Class Notes", {
x: 0.5, y: 5.1, w: 9, h: 0.3,
fontSize: 10, color: "7E57C2", align: "center", fontFace: "Calibri"
});
// --- Image slides ---
const slideConfigs = [
{
headerBg: "283593",
accentColor: "5C6BC0",
labelColor: "C5CAE9",
imgTitle: "3.2 Morphology & Classification of Bacteria",
imgSubtitle: "Groups 1–3: Cocci · Bacilli · Vibrios",
},
{
headerBg: "4A148C",
accentColor: "7B1FA2",
labelColor: "E1BEE7",
imgTitle: "Morphology (cont.) & Arrangement of Bacterial Cells",
imgSubtitle: "Groups 4–7 · Diplococci · Streptococci · Staphylococci · Tetrads · Sarcina · Coryne",
},
{
headerBg: "1B5E20",
accentColor: "388E3C",
labelColor: "C8E6C9",
imgTitle: "Gram Positive vs Gram Negative Bacteria",
imgSubtitle: "Cell wall differences · Staining reactions · Appearance",
},
];
imagesData.forEach((imgObj, i) => {
const cfg = slideConfigs[i];
let slide = pres.addSlide();
// Dark background
slide.background = { color: "121212" };
// Header bar
slide.addShape(pres.ShapeType.rect, {
x: 0, y: 0, w: "100%", h: 0.75,
fill: { color: cfg.headerBg },
line: { color: cfg.headerBg }
});
// Accent left bar
slide.addShape(pres.ShapeType.rect, {
x: 0, y: 0, w: 0.07, h: 0.75,
fill: { color: cfg.accentColor },
line: { color: cfg.accentColor }
});
// Slide number badge
slide.addShape(pres.ShapeType.ellipse, {
x: 9.4, y: 0.1, w: 0.45, h: 0.45,
fill: { color: cfg.accentColor },
line: { color: cfg.accentColor }
});
slide.addText(`${i + 1}`, {
x: 9.4, y: 0.1, w: 0.45, h: 0.45,
fontSize: 13, color: "FFFFFF", bold: true, align: "center", valign: "middle",
fontFace: "Calibri", margin: 0
});
// Header title
slide.addText(cfg.imgTitle, {
x: 0.2, y: 0.05, w: 9, h: 0.4,
fontSize: 15, color: "FFFFFF", bold: true,
fontFace: "Calibri", valign: "middle", margin: 0
});
// Subtitle tag
slide.addText(cfg.imgSubtitle, {
x: 0.2, y: 0.45, w: 9.5, h: 0.25,
fontSize: 9, color: cfg.labelColor,
fontFace: "Calibri", italic: true, margin: 0
});
// Image — full width centered, filling most of the slide below header
if (imgObj.base64 && !imgObj.error) {
slide.addImage({
data: imgObj.base64,
x: 0.15,
y: 0.82,
w: 9.7,
h: 4.65,
sizing: { type: "contain", w: 9.7, h: 4.65 }
});
}
// Footer
slide.addShape(pres.ShapeType.rect, {
x: 0, y: 5.43, w: "100%", h: 0.2,
fill: { color: cfg.headerBg },
line: { color: cfg.headerBg }
});
slide.addText("Paper II · Microbiology and Pathology", {
x: 0.2, y: 5.43, w: 9.6, h: 0.2,
fontSize: 8, color: cfg.labelColor, align: "center",
fontFace: "Calibri", margin: 0
});
});
pres.writeFile({ fileName: "/home/daytona/workspace/microbiology-ppt/Bacterial_Morphology.pptx" })
.then(() => console.log("PPT created successfully!"))
.catch(err => console.error("Error:", err));
cd /home/daytona/workspace/microbiology-ppt && node create_ppt.js
Bacterial Morphology
Presentation · PPTX
Convert as a text
~/microbiology-ppt/create_text_ppt.js
const pptxgen = require("pptxgenjs");
let pres = new pptxgen();
pres.layout = "LAYOUT_16x9";
pres.title = "Microbiology and Pathology – Bacterial Morphology";
// ─── Color Palette ───────────────────────────────────────────────
const C = {
darkBg: "0D1B2A",
headerBg: "1B2A4A",
accent1: "4A90D9",
accent2: "7C4DFF",
accent3: "26A69A",
white: "FFFFFF",
offWhite: "E8EDF4",
muted: "90A4AE",
gold: "FFD54F",
green: "66BB6A",
red: "EF5350",
};
// ════════════════════════════════════════════════════════════════
// SLIDE 1 – Title
// ════════════════════════════════════════════════════════════════
{
let s = pres.addSlide();
s.background = { color: C.darkBg };
// Top accent bar
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:"100%", h:0.08, fill:{color:C.accent1}, line:{color:C.accent1} });
// Centre card
s.addShape(pres.ShapeType.roundRect, { x:1.2, y:0.7, w:7.6, h:4.2, fill:{color:C.headerBg}, line:{color:C.accent1, pt:1.5}, rectRadius:0.12 });
s.addText("PAPER II", { x:1.2, y:0.9, w:7.6, h:0.4, fontSize:11, color:C.accent1, bold:true, align:"center", charSpacing:5, fontFace:"Calibri" });
s.addText("Microbiology & Pathology", { x:1.2, y:1.3, w:7.6, h:0.5, fontSize:18, color:C.muted, align:"center", fontFace:"Calibri" });
// Divider
s.addShape(pres.ShapeType.rect, { x:3.5, y:1.88, w:3, h:0.04, fill:{color:C.accent1}, line:{color:C.accent1} });
s.addText("Bacterial Morphology\n& Classification", {
x:1.2, y:2.0, w:7.6, h:1.5,
fontSize:34, color:C.white, bold:true, align:"center", fontFace:"Calibri"
});
// Topic pills
const pills = [
{ label:"7 Bacterial Shapes", x:0.5, color:C.accent1 },
{ label:"Cell Arrangements", x:3.55, color:C.accent2 },
{ label:"Gram +ve vs Gram -ve", x:6.6, color:C.accent3 },
];
pills.forEach(p => {
s.addShape(pres.ShapeType.roundRect, { x:p.x, y:4.0, w:2.9, h:0.55, fill:{color:p.color}, line:{color:p.color}, rectRadius:0.08 });
s.addText(p.label, { x:p.x, y:4.0, w:2.9, h:0.55, fontSize:11, color:C.white, bold:true, align:"center", valign:"middle", fontFace:"Calibri", margin:0 });
});
// Bottom bar
s.addShape(pres.ShapeType.rect, { x:0, y:5.43, w:"100%", h:0.2, fill:{color:C.headerBg}, line:{color:C.headerBg} });
s.addText("Section 3.2 | Class Notes", { x:0, y:5.43, w:"100%", h:0.2, fontSize:8, color:C.muted, align:"center", fontFace:"Calibri", margin:0 });
}
// ════════════════════════════════════════════════════════════════
// SLIDE 2 – 3.2 Morphology & Classification (Shapes 1–3)
// ════════════════════════════════════════════════════════════════
{
let s = pres.addSlide();
s.background = { color: C.darkBg };
// Header
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:"100%", h:0.72, fill:{color:C.headerBg}, line:{color:C.headerBg} });
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:0.07, h:0.72, fill:{color:C.accent1}, line:{color:C.accent1} });
s.addText("3.2 Morphology and Classification of Bacteria", {
x:0.18, y:0.05, w:9.4, h:0.4, fontSize:16, color:C.white, bold:true, fontFace:"Calibri", margin:0
});
s.addText("Bacteria are classified into 7 groups depending on their shape", {
x:0.18, y:0.45, w:9.4, h:0.22, fontSize:9, color:C.muted, italic:true, fontFace:"Calibri", margin:0
});
// Shape cards
const shapes = [
{ num:"1", name:"Cocci", origin:"(Kokhos = berry)", desc:"Spherical in shape", color:C.accent1 },
{ num:"2", name:"Bacilli", origin:"(Baculus = rod)", desc:"Rod shaped cells", color:C.accent2 },
{ num:"3", name:"Vibrios", origin:"", desc:"Comma shaped, curved rods possessing vibratory motility", color:C.accent3 },
];
shapes.forEach((sh, i) => {
const x = 0.25 + i * 3.25;
// Card bg
s.addShape(pres.ShapeType.roundRect, { x, y:0.85, w:3.1, h:4.55, fill:{color:C.headerBg}, line:{color:sh.color, pt:1.5}, rectRadius:0.1 });
// Number badge
s.addShape(pres.ShapeType.ellipse, { x: x+1.15, y:0.95, w:0.8, h:0.8, fill:{color:sh.color}, line:{color:sh.color} });
s.addText(sh.num, { x: x+1.15, y:0.95, w:0.8, h:0.8, fontSize:20, color:C.white, bold:true, align:"center", valign:"middle", fontFace:"Calibri", margin:0 });
// Name
s.addText(sh.name, { x, y:1.85, w:3.1, h:0.5, fontSize:20, color:sh.color, bold:true, align:"center", fontFace:"Calibri" });
// Origin
if (sh.origin) s.addText(sh.origin, { x, y:2.35, w:3.1, h:0.3, fontSize:10, color:C.muted, align:"center", italic:true, fontFace:"Calibri" });
// Desc
s.addText(sh.desc, { x: x+0.15, y:2.75, w:2.8, h:1.5, fontSize:13, color:C.offWhite, align:"center", fontFace:"Calibri", wrap:true });
});
// Footer
s.addShape(pres.ShapeType.rect, { x:0, y:5.43, w:"100%", h:0.2, fill:{color:C.headerBg}, line:{color:C.headerBg} });
s.addText("Paper II · Microbiology and Pathology", { x:0, y:5.43, w:"100%", h:0.2, fontSize:8, color:C.muted, align:"center", fontFace:"Calibri", margin:0 });
}
// ════════════════════════════════════════════════════════════════
// SLIDE 3 – Shapes 4–7
// ════════════════════════════════════════════════════════════════
{
let s = pres.addSlide();
s.background = { color: C.darkBg };
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:"100%", h:0.72, fill:{color:C.headerBg}, line:{color:C.headerBg} });
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:0.07, h:0.72, fill:{color:C.accent2}, line:{color:C.accent2} });
s.addText("3.2 Morphology and Classification (cont.)", {
x:0.18, y:0.05, w:9.4, h:0.4, fontSize:16, color:C.white, bold:true, fontFace:"Calibri", margin:0
});
s.addText("Groups 4 – 7", { x:0.18, y:0.45, w:9.4, h:0.22, fontSize:9, color:C.muted, italic:true, fontFace:"Calibri", margin:0 });
const shapes4to7 = [
{ num:"4", name:"Spirilla", desc:"Rigid spiral forms", color:C.accent1 },
{ num:"5", name:"Spirochaetes", desc:"Thin flexuous spiral forms\n(Coiled hairs)", color:C.accent2 },
{ num:"6", name:"Actinomycetes", desc:"Branching filamentous bacteria.\nAppear like radiating rays of the sun (sunray appearance) in tissues — due to rigid cell wall.", color:C.accent3 },
{ num:"7", name:"Mycoplasma", desc:"Bacteria with defective cell wall — due to spontaneous mutation or penicillin administration.\nCalled: Protoplasts / Spheroplasts / L-forms", color:C.gold },
];
shapes4to7.forEach((sh, i) => {
const col = i % 2;
const row = Math.floor(i / 2);
const x = 0.25 + col * 4.9;
const y = 0.85 + row * 2.3;
s.addShape(pres.ShapeType.roundRect, { x, y, w:4.6, h:2.1, fill:{color:C.headerBg}, line:{color:sh.color, pt:1.5}, rectRadius:0.1 });
s.addShape(pres.ShapeType.ellipse, { x: x+0.15, y: y+0.6, w:0.55, h:0.55, fill:{color:sh.color}, line:{color:sh.color} });
s.addText(sh.num, { x: x+0.15, y: y+0.6, w:0.55, h:0.55, fontSize:13, color:C.white, bold:true, align:"center", valign:"middle", fontFace:"Calibri", margin:0 });
s.addText(sh.name, { x: x+0.8, y: y+0.08, w:3.65, h:0.45, fontSize:16, color:sh.color, bold:true, fontFace:"Calibri" });
s.addText(sh.desc, { x: x+0.8, y: y+0.55, w:3.65, h:1.4, fontSize:10.5, color:C.offWhite, fontFace:"Calibri", wrap:true });
});
s.addShape(pres.ShapeType.rect, { x:0, y:5.43, w:"100%", h:0.2, fill:{color:C.headerBg}, line:{color:C.headerBg} });
s.addText("Paper II · Microbiology and Pathology", { x:0, y:5.43, w:"100%", h:0.2, fontSize:8, color:C.muted, align:"center", fontFace:"Calibri", margin:0 });
}
// ════════════════════════════════════════════════════════════════
// SLIDE 4 – Arrangement of Bacterial Cells
// ════════════════════════════════════════════════════════════════
{
let s = pres.addSlide();
s.background = { color: C.darkBg };
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:"100%", h:0.72, fill:{color:C.headerBg}, line:{color:C.headerBg} });
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:0.07, h:0.72, fill:{color:C.accent3}, line:{color:C.accent3} });
s.addText("Arrangement of Bacterial Cells", {
x:0.18, y:0.05, w:9.4, h:0.4, fontSize:16, color:C.white, bold:true, fontFace:"Calibri", margin:0
});
s.addText("Classification by grouping pattern", { x:0.18, y:0.45, w:9.4, h:0.22, fontSize:9, color:C.muted, italic:true, fontFace:"Calibri", margin:0 });
// Two columns
const col1 = [
{ n:"1", label:"Diplococci", desc:"Cocci in pairs" },
{ n:"2", label:"Streptococci", desc:"Cocci in chains" },
{ n:"3", label:"Staphylococci", desc:"Cocci in clusters" },
{ n:"4", label:"Tetrads", desc:"Cocci in groups of four" },
];
const col2 = [
{ n:"5", label:"Sarcina", desc:"Cocci in pockets of eight" },
{ n:"6", label:"Streptobacilli", desc:"Bacilli in chains" },
{ n:"7", label:"Coryne bacteria", desc:"Bacilli in chinese letter pattern" },
];
const renderList = (items, colX, rowColors) => {
items.forEach((item, i) => {
const y = 0.85 + i * 0.62;
const clr = rowColors[i % rowColors.length];
s.addShape(pres.ShapeType.roundRect, { x:colX, y, w:4.6, h:0.54, fill:{color:C.headerBg}, line:{color:clr, pt:1}, rectRadius:0.07 });
// number badge
s.addShape(pres.ShapeType.rect, { x:colX, y, w:0.38, h:0.54, fill:{color:clr}, line:{color:clr}, rectRadius:0.07 });
s.addText(item.n, { x:colX, y, w:0.38, h:0.54, fontSize:12, color:C.white, bold:true, align:"center", valign:"middle", fontFace:"Calibri", margin:0 });
s.addText(item.label, { x:colX+0.45, y: y+0.04, w:2.2, h:0.25, fontSize:12, color:clr, bold:true, fontFace:"Calibri", margin:0 });
s.addText(item.desc, { x:colX+0.45, y: y+0.28, w:4.1, h:0.22, fontSize:9, color:C.muted, fontFace:"Calibri", margin:0 });
});
};
renderList(col1, 0.25, [C.accent1, C.accent2, C.accent3, C.gold]);
renderList(col2, 5.15, [C.accent3, C.accent1, C.accent2]);
s.addShape(pres.ShapeType.rect, { x:0, y:5.43, w:"100%", h:0.2, fill:{color:C.headerBg}, line:{color:C.headerBg} });
s.addText("Paper II · Microbiology and Pathology", { x:0, y:5.43, w:"100%", h:0.2, fontSize:8, color:C.muted, align:"center", fontFace:"Calibri", margin:0 });
}
// ════════════════════════════════════════════════════════════════
// SLIDE 5 – Gram Positive vs Gram Negative Bacteria
// ════════════════════════════════════════════════════════════════
{
let s = pres.addSlide();
s.background = { color: C.darkBg };
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:"100%", h:0.72, fill:{color:C.headerBg}, line:{color:C.headerBg} });
s.addShape(pres.ShapeType.rect, { x:0, y:0, w:0.07, h:0.72, fill:{color:C.accent3}, line:{color:C.accent3} });
s.addText("Gram Positive vs Gram Negative Bacteria", {
x:0.18, y:0.05, w:9.4, h:0.4, fontSize:16, color:C.white, bold:true, fontFace:"Calibri", margin:0
});
s.addText("Structural & staining differences", { x:0.18, y:0.45, w:9.4, h:0.22, fontSize:9, color:C.muted, italic:true, fontFace:"Calibri", margin:0 });
// Column headers
s.addShape(pres.ShapeType.roundRect, { x:0.25, y:0.82, w:4.6, h:0.5, fill:{color:"1565C0"}, line:{color:"1565C0"}, rectRadius:0.06 });
s.addText("Gram Positive (+)", { x:0.25, y:0.82, w:4.6, h:0.5, fontSize:14, color:C.white, bold:true, align:"center", valign:"middle", fontFace:"Calibri", margin:0 });
s.addShape(pres.ShapeType.roundRect, { x:5.15, y:0.82, w:4.6, h:0.5, fill:{color:"B71C1C"}, line:{color:"B71C1C"}, rectRadius:0.06 });
s.addText("Gram Negative (−)", { x:5.15, y:0.82, w:4.6, h:0.5, fontSize:14, color:C.white, bold:true, align:"center", valign:"middle", fontFace:"Calibri", margin:0 });
const rows = [
{ pos:"Simple cell wall", neg:"More complex cell wall" },
{ pos:"Thick peptidoglycan cell wall layer", neg:"Thin peptidoglycan cell wall layer" },
{ pos:"No outer lipopolysaccharide wall layer", neg:"Outer lipopolysaccharide (LPS) wall layer" },
{ pos:"Retain crystal violet / iodine", neg:"Retain safranin" },
{ pos:"Appear Blue / Purple", neg:"Appear Pink / Red" },
];
rows.forEach((row, i) => {
const y = 1.42 + i * 0.72;
const rowBg = i % 2 === 0 ? "1A2A3A" : "0D1B2A";
s.addShape(pres.ShapeType.rect, { x:0.25, y, w:4.6, h:0.66, fill:{color:rowBg}, line:{color:"1565C0", pt:0.5} });
s.addText(row.pos, { x:0.35, y: y+0.05, w:4.4, h:0.56, fontSize:11, color:i===4 ? C.accent1 : C.offWhite, fontFace:"Calibri", valign:"middle", bold: i===4 });
s.addShape(pres.ShapeType.rect, { x:5.15, y, w:4.6, h:0.66, fill:{color:rowBg}, line:{color:"B71C1C", pt:0.5} });
s.addText(row.neg, { x:5.25, y: y+0.05, w:4.4, h:0.56, fontSize:11, color:i===4 ? C.red : C.offWhite, fontFace:"Calibri", valign:"middle", bold: i===4 });
});
s.addShape(pres.ShapeType.rect, { x:0, y:5.43, w:"100%", h:0.2, fill:{color:C.headerBg}, line:{color:C.headerBg} });
s.addText("Paper II · Microbiology and Pathology", { x:0, y:5.43, w:"100%", h:0.2, fontSize:8, color:C.muted, align:"center", fontFace:"Calibri", margin:0 });
}
// ════════════════════════════════════════════════════════════════
// Write file
// ════════════════════════════════════════════════════════════════
pres.writeFile({ fileName: "/home/daytona/workspace/microbiology-ppt/Bacterial_Morphology_Text.pptx" })
.then(() => console.log("Done!"))
.catch(err => console.error(err));
cd /home/daytona/workspace/microbiology-ppt && node create_text_ppt.js
| Slide | Content |
|---|---|
| 1 | Title slide - Bacterial Morphology & Classification |
| 2 | Shapes 1-3 - Cocci, Bacilli, Vibrios (card layout) |
| 3 | Shapes 4-7 - Spirilla, Spirochaetes, Actinomycetes, Mycoplasma |
| 4 | Arrangement of Bacterial Cells - All 7 arrangements (Diplococci to Coryne bacteria) |
| 5 | Gram +ve vs Gram -ve comparison table with color-coded columns |
Bacterial Morphology Text
Presentation · PPTX