Files
Goa-gel-fullstack/create_presentation.js
Mahi 80566bf0a2 feat: Goa GEL Blockchain e-Licensing Platform - Full Stack Implementation
Complete implementation of the Goa Government e-Licensing platform with:

Backend:
- NestJS API with JWT authentication
- PostgreSQL database with Knex ORM
- Redis caching and session management
- MinIO document storage
- Hyperledger Besu blockchain integration
- Multi-department workflow system
- Comprehensive API tests (266/282 passing)

Frontend:
- Angular 21 with standalone components
- Angular Material + TailwindCSS UI
- Visual workflow builder
- Document upload with progress tracking
- Blockchain explorer integration
- Role-based dashboards (Admin, Department, Citizen)
- E2E tests with Playwright (37 tests)

Infrastructure:
- Docker Compose orchestration
- Blockscout blockchain explorer
- Development and production configurations
2026-02-07 10:23:29 -04:00

1427 lines
29 KiB
JavaScript

const pptxgen = require("pptxgenjs");
let pres = new pptxgen();
pres.layout = "LAYOUT_16x9";
pres.author = "Goa Government";
pres.title = "Goa GEL Blockchain Document Verification Platform";
// Color palette - Professional government/tech
const colors = {
primary: "0F4C81", // Deep blue
secondary: "1B7BAA", // Teal blue
accent: "00B4D8", // Bright cyan
lightBg: "F0F4F8", // Light blue-gray
darkBg: "0B2E4D", // Dark navy
white: "FFFFFF",
text: "1A1A1A",
lightText: "666666",
success: "06A77D",
};
// Helper function for fresh shadow objects
const makeShadow = () => ({
type: "outer",
blur: 6,
offset: 2,
color: "000000",
opacity: 0.12,
});
// Utility: Add title with accent bar
function addTitleWithBar(slide, title, x = 0.5, y = 0.4, w = 9, barColor = colors.accent) {
slide.addShape(pres.shapes.RECTANGLE, {
x: x,
y: y,
w: 0.08,
h: 0.6,
fill: { color: barColor },
line: { type: "none" },
});
slide.addText(title, {
x: x + 0.15,
y: y,
w: w - 0.2,
h: 0.6,
fontSize: 40,
bold: true,
color: colors.white,
fontFace: "Calibri",
valign: "middle",
margin: 0,
});
}
// ===== SLIDE 1: TITLE SLIDE =====
let slide1 = pres.addSlide();
slide1.background = { color: colors.darkBg };
slide1.addText("Goa GEL", {
x: 0.5,
y: 1.5,
w: 9,
h: 0.8,
fontSize: 60,
bold: true,
color: colors.accent,
align: "center",
fontFace: "Calibri",
});
slide1.addText("Blockchain-Based Document Verification Platform", {
x: 0.5,
y: 2.4,
w: 9,
h: 0.6,
fontSize: 36,
color: colors.white,
align: "center",
fontFace: "Calibri",
});
slide1.addText("for Government of Goa", {
x: 0.5,
y: 3.1,
w: 9,
h: 0.4,
fontSize: 20,
color: colors.lightBg,
align: "center",
fontFace: "Calibri",
});
slide1.addText("Technical Architecture Overview", {
x: 0.5,
y: 4.3,
w: 9,
h: 0.4,
fontSize: 18,
italic: true,
color: colors.accent,
align: "center",
fontFace: "Calibri",
});
// ===== SLIDE 2: AGENDA =====
let slide2 = pres.addSlide();
slide2.background = { color: colors.lightBg };
addTitleWithBar(slide2, "Agenda");
const agendaItems = [
"Problem Statement",
"Solution Overview",
"NBF Alignment",
"System Architecture",
"Blockchain Architecture",
"Smart Contracts",
"Technology Stack",
"Workflow Engine",
"Data Flow",
"Security Architecture",
"Deployment & POC Scope",
"Success Criteria & Timeline",
];
slide2.addText(
agendaItems.map((item, idx) => ({
text: item,
options: {
bullet: true,
breakLine: idx < agendaItems.length - 1,
},
})),
{
x: 1,
y: 1.2,
w: 8,
h: 3.8,
fontSize: 16,
color: colors.text,
fontFace: "Calibri",
}
);
// ===== SLIDE 3: PROBLEM STATEMENT =====
let slide3 = pres.addSlide();
slide3.background = { color: colors.white };
addTitleWithBar(slide3, "Problem Statement", 0.5, 0.3);
const problems = [
{
title: "Fragmented Mechanisms",
desc: "Multiple online/offline document processes",
},
{
title: "Lack of Trust",
desc: "No transparent verification mechanism",
},
{
title: "Poor Traceability",
desc: "Document history and approvals unclear",
},
{
title: "Tampering Risks",
desc: "No protection against document modification",
},
];
let yPos = 1.3;
problems.forEach((problem, idx) => {
const bgColor = [colors.primary, colors.secondary, colors.accent, "FF6B6B"][idx];
slide3.addShape(pres.shapes.RECTANGLE, {
x: 0.5 + idx * 2.25,
y: yPos,
w: 2.1,
h: 3.5,
fill: { color: bgColor },
line: { type: "none" },
shadow: makeShadow(),
});
slide3.addText(problem.title, {
x: 0.65 + idx * 2.25,
y: yPos + 0.3,
w: 1.8,
h: 1,
fontSize: 16,
bold: true,
color: colors.white,
align: "center",
fontFace: "Calibri",
});
slide3.addText(problem.desc, {
x: 0.65 + idx * 2.25,
y: yPos + 1.5,
w: 1.8,
h: 1.6,
fontSize: 13,
color: colors.white,
align: "center",
valign: "middle",
fontFace: "Calibri",
});
});
// ===== SLIDE 4: SOLUTION OVERVIEW =====
let slide4 = pres.addSlide();
slide4.background = { color: colors.lightBg };
addTitleWithBar(slide4, "Solution Overview: GEL Platform");
const solutions = [
{
title: "Single Ledger",
icon: "✓",
},
{
title: "Multi-Stakeholder Consensus",
icon: "✓",
},
{
title: "End-to-End Traceability",
icon: "✓",
},
{
title: "REST API Interoperability",
icon: "✓",
},
];
let xPos = 0.7;
solutions.forEach((sol) => {
slide4.addShape(pres.shapes.RECTANGLE, {
x: xPos,
y: 1.4,
w: 2.0,
h: 2.8,
fill: { color: colors.white },
line: { type: "none" },
shadow: makeShadow(),
});
slide4.addText(sol.icon, {
x: xPos,
y: 1.6,
w: 2.0,
h: 0.5,
fontSize: 48,
color: colors.success,
align: "center",
fontFace: "Calibri",
});
slide4.addText(sol.title, {
x: xPos + 0.1,
y: 2.2,
w: 1.8,
h: 1.8,
fontSize: 14,
bold: true,
color: colors.text,
align: "center",
valign: "middle",
fontFace: "Calibri",
});
xPos += 2.15;
});
// ===== SLIDE 5: NBF ALIGNMENT =====
let slide5 = pres.addSlide();
slide5.background = { color: colors.white };
addTitleWithBar(slide5, "National Blockchain Framework Alignment");
slide5.addShape(pres.shapes.RECTANGLE, {
x: 0.5,
y: 1.2,
w: 9,
h: 3.8,
fill: { color: colors.lightBg },
line: { type: "none" },
});
slide5.addText(
[
{ text: "NBF Document Chain Integration Path\n", options: { bold: true, fontSize: 18, breakLine: true } },
{
text:
"GEL Platform designed with future NBF compliance in mind. Current implementation follows recommended blockchain patterns and can be seamlessly integrated with National Blockchain Framework when available.\n\n",
options: { fontSize: 14, breakLine: true },
},
{
text: "Key Alignment Features:",
options: { bold: true, fontSize: 14, breakLine: true },
},
{
text: "QBFT consensus mechanism",
options: { bullet: true, breakLine: true },
},
{ text: "Validator node architecture", options: { bullet: true, breakLine: true } },
{ text: "Decentralized governance model", options: { bullet: true, breakLine: true } },
{ text: "Cross-chain interoperability", options: { bullet: true } },
],
{
x: 0.8,
y: 1.4,
w: 8.4,
h: 3.4,
fontSize: 14,
color: colors.text,
fontFace: "Calibri",
}
);
// ===== SLIDE 6: SYSTEM ARCHITECTURE =====
let slide6 = pres.addSlide();
slide6.background = { color: colors.lightBg };
addTitleWithBar(slide6, "System Architecture - High Level");
const components = [
{ name: "Frontend\n(Next.js 14)", x: 0.6, color: colors.primary },
{ name: "Backend API\n(NestJS)", x: 2.8, color: colors.secondary },
{ name: "Smart Contracts\n(ERC-721)", x: 5.0, color: colors.accent },
{ name: "Database\n(PostgreSQL)", x: 7.2, color: "FF6B6B" },
];
components.forEach((comp) => {
slide6.addShape(pres.shapes.RECTANGLE, {
x: comp.x,
y: 1.2,
w: 1.8,
h: 1.2,
fill: { color: comp.color },
line: { type: "none" },
shadow: makeShadow(),
});
slide6.addText(comp.name, {
x: comp.x,
y: 1.2,
w: 1.8,
h: 1.2,
fontSize: 12,
bold: true,
color: colors.white,
align: "center",
valign: "middle",
fontFace: "Calibri",
});
slide6.addShape(pres.shapes.LINE, {
x: comp.x + 1.8,
y: 1.8,
w: 0.8,
h: 0,
line: { color: colors.text, width: 2 },
});
});
// Remove last line
slide6.addShape(pres.shapes.RECTANGLE, {
x: 8.8,
y: 1.7,
w: 0.4,
h: 0.2,
fill: { color: colors.lightBg },
line: { type: "none" },
});
slide6.addText("Storage Layer (MinIO) | Blockchain (Hyperledger Besu)", {
x: 0.6,
y: 2.8,
w: 8.8,
h: 0.4,
fontSize: 13,
color: colors.text,
align: "center",
fontFace: "Calibri",
});
slide6.addShape(pres.shapes.RECTANGLE, {
x: 0.6,
y: 3.5,
w: 8.8,
h: 1.5,
fill: { color: colors.white },
line: { type: "none" },
shadow: makeShadow(),
});
slide6.addText(
[
{ text: "Architectural Principles\n", options: { bold: true, fontSize: 12, breakLine: true } },
{ text: "Microservices: Independent, scalable components", options: { bullet: true, breakLine: true } },
{ text: "API-First: RESTful interfaces for all services", options: { bullet: true, breakLine: true } },
{ text: "Event-Driven: Async communication between layers", options: { bullet: true } },
],
{
x: 0.9,
y: 3.6,
w: 8.2,
h: 1.3,
fontSize: 11,
color: colors.text,
fontFace: "Calibri",
}
);
// ===== SLIDE 7: BLOCKCHAIN ARCHITECTURE =====
let slide7 = pres.addSlide();
slide7.background = { color: colors.white };
addTitleWithBar(slide7, "Blockchain Architecture - Deep Dive");
slide7.addShape(pres.shapes.RECTANGLE, {
x: 0.5,
y: 1.2,
w: 4.2,
h: 3.8,
fill: { color: colors.lightBg },
line: { type: "none" },
});
slide7.addText(
[
{ text: "Hyperledger Besu\n\n", options: { bold: true, fontSize: 14, breakLine: true } },
{ text: "QBFT Consensus", options: { bullet: true, breakLine: true } },
{ text: "4 Validator Nodes", options: { bullet: true, breakLine: true } },
{ text: "Immediate Finality", options: { bullet: true, breakLine: true } },
{ text: "Enterprise-Grade", options: { bullet: true, breakLine: true } },
{ text: "EVM Compatible", options: { bullet: true } },
],
{
x: 0.8,
y: 1.4,
w: 3.6,
h: 3.4,
fontSize: 13,
color: colors.text,
fontFace: "Calibri",
}
);
slide7.addShape(pres.shapes.RECTANGLE, {
x: 5.2,
y: 1.2,
w: 4.2,
h: 3.8,
fill: { color: colors.primary },
line: { type: "none" },
});
slide7.addText(
[
{ text: "Network Topology\n\n", options: { bold: true, fontSize: 14, color: colors.white, breakLine: true } },
{
text: "Validator 1",
options: { bullet: true, color: colors.white, breakLine: true },
},
{
text: "Validator 2",
options: { bullet: true, color: colors.white, breakLine: true },
},
{
text: "Validator 3",
options: { bullet: true, color: colors.white, breakLine: true },
},
{
text: "Validator 4",
options: { bullet: true, color: colors.white, breakLine: true },
},
{
text: "Public RPC Nodes",
options: { bullet: true, color: colors.white },
},
],
{
x: 5.5,
y: 1.4,
w: 3.6,
h: 3.4,
fontSize: 13,
color: colors.white,
fontFace: "Calibri",
}
);
// ===== SLIDE 8: SMART CONTRACTS =====
let slide8 = pres.addSlide();
slide8.background = { color: colors.lightBg };
addTitleWithBar(slide8, "Smart Contracts - NFT-Based Approach");
const contracts = [
{
name: "LicenseRequestNFT",
desc: "ERC-721 Soulbound",
y: 1.3,
},
{
name: "ApprovalManager",
desc: "Multi-stage approvals",
y: 2.4,
},
{
name: "DepartmentRegistry",
desc: "Department governance",
y: 3.5,
},
{
name: "WorkflowRegistry",
desc: "Process orchestration",
y: 4.6,
},
];
contracts.forEach((contract) => {
slide8.addShape(pres.shapes.RECTANGLE, {
x: 0.6,
y: contract.y,
w: 0.08,
h: 0.7,
fill: { color: colors.accent },
line: { type: "none" },
});
slide8.addText(contract.name, {
x: 0.8,
y: contract.y,
w: 3.5,
h: 0.35,
fontSize: 14,
bold: true,
color: colors.text,
fontFace: "Calibri",
valign: "top",
margin: 0,
});
slide8.addText(contract.desc, {
x: 0.8,
y: contract.y + 0.35,
w: 3.5,
h: 0.35,
fontSize: 12,
color: colors.lightText,
fontFace: "Calibri",
valign: "top",
margin: 0,
});
slide8.addShape(pres.shapes.RECTANGLE, {
x: 4.5,
y: contract.y,
w: 5.0,
h: 0.7,
fill: { color: colors.white },
line: { type: "none" },
shadow: makeShadow(),
});
const details = [
["Status Tracking", "Access Control", "Event Logging"],
["Sequential Flow", "Parallel Stages", "Conditional Logic"],
["Department IDs", "Role Binding", "Approval Rights"],
["Stage Management", "Versioning", "State Transitions"],
];
slide8.addText(details[contracts.indexOf(contract)].join(" | "), {
x: 4.7,
y: contract.y + 0.15,
w: 4.6,
h: 0.4,
fontSize: 11,
color: colors.text,
align: "left",
fontFace: "Calibri",
});
});
// ===== SLIDE 9: TECHNOLOGY STACK =====
let slide9 = pres.addSlide();
slide9.background = { color: colors.white };
addTitleWithBar(slide9, "Technology Stack");
const stackLayers = [
{
title: "Frontend",
tech: "Next.js 14, React, TypeScript",
y: 1.3,
},
{
title: "Backend",
tech: "NestJS, TypeScript, Node.js",
y: 2.3,
},
{
title: "Database",
tech: "PostgreSQL (relational), Redis (caching)",
y: 3.3,
},
{
title: "Storage",
tech: "MinIO (S3-compatible object storage)",
y: 4.3,
},
];
stackLayers.forEach((layer, idx) => {
const colors_alt = [colors.primary, colors.secondary, colors.accent, "FF6B6B"];
slide9.addShape(pres.shapes.RECTANGLE, {
x: 0.6,
y: layer.y,
w: 8.8,
h: 0.8,
fill: { color: colors_alt[idx] },
line: { type: "none" },
});
slide9.addText(layer.title, {
x: 0.9,
y: layer.y + 0.15,
w: 2.0,
h: 0.5,
fontSize: 14,
bold: true,
color: colors.white,
valign: "middle",
fontFace: "Calibri",
margin: 0,
});
slide9.addText(layer.tech, {
x: 3.2,
y: layer.y + 0.15,
w: 6.0,
h: 0.5,
fontSize: 13,
color: colors.white,
valign: "middle",
fontFace: "Calibri",
margin: 0,
});
});
// ===== SLIDE 10: WORKFLOW ENGINE =====
let slide10 = pres.addSlide();
slide10.background = { color: colors.lightBg };
addTitleWithBar(slide10, "Workflow Engine");
slide10.addText("Multi-Department Approval System", {
x: 0.5,
y: 1.2,
w: 9,
h: 0.3,
fontSize: 16,
bold: true,
color: colors.text,
fontFace: "Calibri",
});
const stages = [
"Submission",
"Department Review",
"Senior Approval",
"Final Authorization",
"NFT Minted",
];
let stageX = 0.8;
stages.forEach((stage, idx) => {
const boxW = 1.6;
slide10.addShape(pres.shapes.RECTANGLE, {
x: stageX,
y: 1.8,
w: boxW,
h: 0.8,
fill: { color: idx < 3 ? colors.primary : idx === 3 ? colors.secondary : colors.success },
line: { type: "none" },
});
slide10.addText(stage, {
x: stageX,
y: 1.8,
w: boxW,
h: 0.8,
fontSize: 11,
bold: true,
color: colors.white,
align: "center",
valign: "middle",
fontFace: "Calibri",
});
if (idx < stages.length - 1) {
slide10.addShape(pres.shapes.LINE, {
x: stageX + boxW,
y: 2.2,
w: 0.35,
h: 0,
line: { color: colors.text, width: 2 },
});
}
stageX += boxW + 0.45;
});
const features = [
{
title: "Sequential & Parallel",
desc: "Configure approval stages as sequential or parallel",
},
{
title: "Document Versioning",
desc: "Track all document revisions through workflow",
},
{
title: "Auto-Invalidation",
desc: "Automatically invalidate approvals upon document change",
},
];
let featureY = 3.0;
features.forEach((feature) => {
slide10.addShape(pres.shapes.RECTANGLE, {
x: 0.8,
y: featureY,
w: 0.06,
h: 0.4,
fill: { color: colors.accent },
line: { type: "none" },
});
slide10.addText(feature.title, {
x: 0.95,
y: featureY,
w: 3.0,
h: 0.25,
fontSize: 12,
bold: true,
color: colors.text,
fontFace: "Calibri",
margin: 0,
});
slide10.addText(feature.desc, {
x: 0.95,
y: featureY + 0.28,
w: 3.0,
h: 0.35,
fontSize: 11,
color: colors.lightText,
fontFace: "Calibri",
margin: 0,
});
featureY += 1.35;
});
// Right side - diagram
slide10.addShape(pres.shapes.RECTANGLE, {
x: 4.5,
y: 3.0,
w: 4.8,
h: 2.2,
fill: { color: colors.white },
line: { type: "none" },
shadow: makeShadow(),
});
slide10.addText(
[
{ text: "Approval Flow Example\n", options: { bold: true, fontSize: 12, breakLine: true } },
{ text: "1. Submit Document", options: { bullet: true, breakLine: true } },
{ text: "2. Department A Reviews", options: { bullet: true, breakLine: true } },
{ text: "3. Department B Reviews (parallel)", options: { bullet: true, breakLine: true } },
{ text: "4. Director Approves", options: { bullet: true, breakLine: true } },
{ text: "5. NFT Minted on Chain", options: { bullet: true } },
],
{
x: 4.8,
y: 3.2,
w: 4.2,
h: 1.8,
fontSize: 11,
color: colors.text,
fontFace: "Calibri",
}
);
// ===== SLIDE 11: DATA FLOW =====
let slide11 = pres.addSlide();
slide11.background = { color: colors.white };
addTitleWithBar(slide11, "Data Flow - License Approval Process");
const flowSteps = [
{
num: "1",
title: "Submission",
desc: "User submits license request with documents",
},
{
num: "2",
title: "Review",
desc: "Department staff reviews document",
},
{
num: "3",
title: "Approval",
desc: "Document approved by authority",
},
{
num: "4",
title: "NFT Minting",
desc: "Approved document minted as NFT",
},
];
let flowX = 0.7;
flowSteps.forEach((step, idx) => {
const boxW = 2.0;
// Step box
slide11.addShape(pres.shapes.RECTANGLE, {
x: flowX,
y: 1.5,
w: boxW,
h: 1.2,
fill: { color: colors.primary },
line: { type: "none" },
shadow: makeShadow(),
});
slide11.addText(step.num, {
x: flowX + 0.2,
y: 1.6,
w: 0.5,
h: 0.4,
fontSize: 20,
bold: true,
color: colors.accent,
fontFace: "Calibri",
margin: 0,
});
slide11.addText(step.title, {
x: flowX + 0.8,
y: 1.6,
w: 1.0,
h: 0.4,
fontSize: 12,
bold: true,
color: colors.white,
fontFace: "Calibri",
margin: 0,
});
slide11.addText(step.desc, {
x: flowX + 0.2,
y: 2.1,
w: 1.6,
h: 0.5,
fontSize: 10,
color: colors.lightBg,
fontFace: "Calibri",
margin: 0,
});
// Arrow
if (idx < flowSteps.length - 1) {
slide11.addShape(pres.shapes.LINE, {
x: flowX + boxW,
y: 2.1,
w: 0.4,
h: 0,
line: { color: colors.text, width: 2 },
});
slide11.addText("→", {
x: flowX + boxW + 0.1,
y: 1.95,
w: 0.2,
h: 0.3,
fontSize: 16,
color: colors.text,
align: "center",
fontFace: "Calibri",
});
}
flowX += boxW + 0.5;
});
// Database integration info
slide11.addShape(pres.shapes.RECTANGLE, {
x: 0.7,
y: 3.2,
w: 8.6,
h: 1.9,
fill: { color: colors.lightBg },
line: { type: "none" },
});
slide11.addText(
[
{ text: "Data Storage Strategy\n", options: { bold: true, fontSize: 13, breakLine: true } },
{ text: "Document Metadata (PostgreSQL): Status, timestamps, approver info", options: { bullet: true, breakLine: true } },
{ text: "Document Files (MinIO): Original and versioned documents", options: { bullet: true, breakLine: true } },
{ text: "Blockchain Record (Besu): Immutable approval chain and NFT reference", options: { bullet: true, breakLine: true } },
{ text: "Event Log (Event Bus): Real-time updates for UI and integrations", options: { bullet: true } },
],
{
x: 0.95,
y: 3.35,
w: 8.1,
h: 1.6,
fontSize: 11,
color: colors.text,
fontFace: "Calibri",
}
);
// ===== SLIDE 12: SECURITY ARCHITECTURE =====
let slide12 = pres.addSlide();
slide12.background = { color: colors.lightBg };
addTitleWithBar(slide12, "Security Architecture");
const securityLayers = [
{
layer: "API Level",
features: ["API Key Authentication", "JWT Tokens", "Rate Limiting"],
},
{
layer: "Wallet Level",
features: ["Custodial Wallet Management", "Private Key Protection", "Transaction Signing"],
},
{
layer: "Integration Level",
features: ["Mock DigiLocker (POC)", "Production: Real DigiLocker", "Digital Signature Verification"],
},
];
let secY = 1.3;
securityLayers.forEach((sec) => {
slide12.addShape(pres.shapes.RECTANGLE, {
x: 0.6,
y: secY,
w: 8.8,
h: 0.9,
fill: { color: colors.white },
line: { type: "none" },
shadow: makeShadow(),
});
slide12.addText(sec.layer, {
x: 0.85,
y: secY + 0.15,
w: 1.8,
h: 0.6,
fontSize: 13,
bold: true,
color: colors.primary,
valign: "middle",
fontFace: "Calibri",
margin: 0,
});
slide12.addText(sec.features.join(" • "), {
x: 2.7,
y: secY + 0.15,
w: 6.5,
h: 0.6,
fontSize: 11,
color: colors.text,
valign: "middle",
fontFace: "Calibri",
margin: 0,
});
secY += 1.1;
});
// Security principles
slide12.addShape(pres.shapes.RECTANGLE, {
x: 0.6,
y: 4.6,
w: 8.8,
h: 0.8,
fill: { color: colors.accent },
line: { type: "none" },
});
slide12.addText(
"Zero Trust Architecture | Defense in Depth | Least Privilege Access",
{
x: 0.85,
y: 4.65,
w: 8.3,
h: 0.7,
fontSize: 12,
bold: true,
color: colors.white,
align: "center",
valign: "middle",
fontFace: "Calibri",
margin: 0,
}
);
// ===== SLIDE 13: DEPLOYMENT ARCHITECTURE =====
let slide13 = pres.addSlide();
slide13.background = { color: colors.white };
addTitleWithBar(slide13, "Deployment Architecture");
slide13.addText("Docker Compose for POC", {
x: 0.5,
y: 1.2,
w: 9,
h: 0.3,
fontSize: 14,
bold: true,
color: colors.text,
fontFace: "Calibri",
});
const services = [
{
name: "Frontend",
port: ":3000",
y: 1.7,
},
{
name: "API Service",
port: ":3001",
y: 2.4,
},
{
name: "PostgreSQL",
port: ":5432",
y: 3.1,
},
{
name: "MinIO Storage",
port: ":9000",
y: 3.8,
},
{
name: "Besu Node 1",
port: ":8545",
y: 4.5,
},
];
services.forEach((svc) => {
slide13.addShape(pres.shapes.RECTANGLE, {
x: 0.6,
y: svc.y,
w: 3.5,
h: 0.5,
fill: { color: colors.primary },
line: { type: "none" },
});
slide13.addText(svc.name, {
x: 0.85,
y: svc.y + 0.05,
w: 2.0,
h: 0.4,
fontSize: 12,
bold: true,
color: colors.white,
valign: "middle",
fontFace: "Calibri",
margin: 0,
});
slide13.addText(svc.port, {
x: 3.0,
y: svc.y + 0.05,
w: 1.0,
h: 0.4,
fontSize: 11,
color: colors.accent,
valign: "middle",
fontFace: "Calibri",
margin: 0,
});
slide13.addShape(pres.shapes.RECTANGLE, {
x: 4.3,
y: svc.y,
w: 5.1,
h: 0.5,
fill: { color: colors.lightBg },
line: { type: "none" },
});
});
slide13.addText("Health Checks & Auto-Recovery | Persistent Volumes | Network Isolation", {
x: 0.6,
y: 5.3,
w: 8.8,
h: 0.35,
fontSize: 11,
color: colors.text,
align: "center",
fontFace: "Calibri",
});
// ===== SLIDE 14: POC SCOPE =====
let slide14 = pres.addSlide();
slide14.background = { color: colors.lightBg };
addTitleWithBar(slide14, "POC Scope - Resort License Demo");
// In-scope column
slide14.addShape(pres.shapes.RECTANGLE, {
x: 0.5,
y: 1.2,
w: 4.4,
h: 4.0,
fill: { color: colors.white },
line: { type: "none" },
shadow: makeShadow(),
});
slide14.addText("In-Scope Features", {
x: 0.7,
y: 1.35,
w: 4.0,
h: 0.4,
fontSize: 14,
bold: true,
color: colors.success,
fontFace: "Calibri",
});
slide14.addText(
[
{ text: "End-to-end license workflow", options: { bullet: true, breakLine: true } },
{ text: "3-department approval chain", options: { bullet: true, breakLine: true } },
{ text: "Document upload & storage", options: { bullet: true, breakLine: true } },
{ text: "NFT minting on Besu", options: { bullet: true, breakLine: true } },
{ text: "API endpoints", options: { bullet: true, breakLine: true } },
{ text: "Basic UI workflows", options: { bullet: true } },
],
{
x: 0.8,
y: 1.85,
w: 4.0,
h: 3.1,
fontSize: 11,
color: colors.text,
fontFace: "Calibri",
}
);
// Out-of-scope column
slide14.addShape(pres.shapes.RECTANGLE, {
x: 5.1,
y: 1.2,
w: 4.4,
h: 4.0,
fill: { color: colors.white },
line: { type: "none" },
shadow: makeShadow(),
});
slide14.addText("Out-of-Scope (Future)", {
x: 5.3,
y: 1.35,
w: 4.0,
h: 0.4,
fontSize: 14,
bold: true,
color: "FF6B6B",
fontFace: "Calibri",
});
slide14.addText(
[
{ text: "Real DigiLocker integration", options: { bullet: true, breakLine: true } },
{ text: "Multi-language support", options: { bullet: true, breakLine: true } },
{ text: "Advanced analytics", options: { bullet: true, breakLine: true } },
{ text: "Mobile applications", options: { bullet: true, breakLine: true } },
{ text: "Scaling to production", options: { bullet: true, breakLine: true } },
{ text: "External API integrations", options: { bullet: true } },
],
{
x: 5.3,
y: 1.85,
w: 4.0,
h: 3.1,
fontSize: 11,
color: colors.text,
fontFace: "Calibri",
}
);
// ===== SLIDE 15: SUCCESS CRITERIA =====
let slide15 = pres.addSlide();
slide15.background = { color: colors.white };
addTitleWithBar(slide15, "Success Criteria");
const criteria = [
{
title: "Complete Workflow",
metric: "100%",
desc: "End-to-end document flow functional",
},
{
title: "Department Integration",
metric: "3",
desc: "3 departments successfully integrated",
},
{
title: "Version Control",
metric: "100%",
desc: "Document versioning operational",
},
{
title: "Visual Builder",
metric: "MVP",
desc: "Workflow configuration UI ready",
},
];
let critX = 0.55;
criteria.forEach((crit) => {
const boxW = 2.15;
slide15.addShape(pres.shapes.RECTANGLE, {
x: critX,
y: 1.3,
w: boxW,
h: 3.5,
fill: { color: colors.white },
line: { type: "none" },
shadow: makeShadow(),
});
slide15.addText(crit.metric, {
x: critX,
y: 1.5,
w: boxW,
h: 0.7,
fontSize: 36,
bold: true,
color: colors.accent,
align: "center",
fontFace: "Calibri",
});
slide15.addText(crit.title, {
x: critX + 0.15,
y: 2.3,
w: boxW - 0.3,
h: 0.8,
fontSize: 12,
bold: true,
color: colors.text,
align: "center",
fontFace: "Calibri",
});
slide15.addText(crit.desc, {
x: critX + 0.15,
y: 3.2,
w: boxW - 0.3,
h: 1.4,
fontSize: 10,
color: colors.lightText,
align: "center",
valign: "middle",
fontFace: "Calibri",
});
critX += boxW + 0.15;
});
// ===== SLIDE 16: TIMELINE & NEXT STEPS =====
let slide16 = pres.addSlide();
slide16.background = { color: colors.lightBg };
addTitleWithBar(slide16, "Timeline & Next Steps");
const timeline = [
{ phase: "Phase 1", duration: "Week 1-2", milestone: "Architecture Setup" },
{ phase: "Phase 2", duration: "Week 3-4", milestone: "Core Development" },
{ phase: "Phase 3", duration: "Week 5-6", milestone: "Integration & Testing" },
{ phase: "Phase 4", duration: "Week 7-8", milestone: "POC Demonstration" },
];
let timelineY = 1.4;
timeline.forEach((item, idx) => {
slide16.addShape(pres.shapes.RECTANGLE, {
x: 0.6,
y: timelineY,
w: 8.8,
h: 0.75,
fill: { color: colors.white },
line: { type: "none" },
shadow: makeShadow(),
});
slide16.addText(item.phase, {
x: 0.8,
y: timelineY + 0.12,
w: 1.2,
h: 0.5,
fontSize: 12,
bold: true,
color: colors.primary,
valign: "middle",
fontFace: "Calibri",
margin: 0,
});
slide16.addText(item.duration, {
x: 2.2,
y: timelineY + 0.12,
w: 1.8,
h: 0.5,
fontSize: 11,
color: colors.text,
valign: "middle",
fontFace: "Calibri",
margin: 0,
});
slide16.addText(item.milestone, {
x: 4.2,
y: timelineY + 0.12,
w: 5.0,
h: 0.5,
fontSize: 11,
color: colors.text,
valign: "middle",
fontFace: "Calibri",
margin: 0,
});
timelineY += 0.95;
});
// Next steps
slide16.addShape(pres.shapes.RECTANGLE, {
x: 0.6,
y: 4.5,
w: 8.8,
h: 0.85,
fill: { color: colors.accent },
line: { type: "none" },
});
slide16.addText(
[
{ text: "Next Steps: ", options: { bold: true, breakLine: true } },
{ text: "Stakeholder approval", options: { bullet: true, breakLine: true } },
{ text: "Resource allocation", options: { bullet: true, breakLine: true } },
{ text: "Project kickoff", options: { bullet: true } },
],
{
x: 0.9,
y: 4.55,
w: 8.2,
h: 0.75,
fontSize: 11,
color: colors.white,
fontFace: "Calibri",
}
);
// ===== SLIDE 17: Q&A =====
let slide17 = pres.addSlide();
slide17.background = { color: colors.darkBg };
slide17.addShape(pres.shapes.RECTANGLE, {
x: 2.0,
y: 1.8,
w: 6.0,
h: 2.0,
fill: { color: colors.primary },
line: { type: "none" },
shadow: makeShadow(),
});
slide17.addText("Questions?", {
x: 2.0,
y: 2.2,
w: 6.0,
h: 0.8,
fontSize: 54,
bold: true,
color: colors.accent,
align: "center",
fontFace: "Calibri",
});
slide17.addText("Thank you for your attention", {
x: 2.0,
y: 3.1,
w: 6.0,
h: 0.4,
fontSize: 18,
color: colors.white,
align: "center",
fontFace: "Calibri",
});
// Save presentation
pres.writeFile({ fileName: "/sessions/cool-elegant-faraday/mnt/Goa-GEL/Goa-GEL-Architecture-Presentation.pptx" });
console.log("Presentation created successfully!");