AutomationFlowsAI & RAG › AI Model Gpt-4.1-mini and Hosting on AWS S3

AI Model Gpt-4.1-mini and Hosting on AWS S3

ByThomas Heal @chopgod on n8n.io

This workflow contains community nodes that are only compatible with the self-hosted version of n8n.

Chat trigger trigger★★★☆☆ complexityAI-powered13 nodesAgentOutput Parser StructuredOpenAI ChatChat TriggerN8N Nodes PdfcoAWS S3
AI & RAG Trigger: Chat trigger Nodes: 13 Complexity: ★★★☆☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #7003 — we link there as the canonical source.

This workflow follows the Agent → Chat Trigger recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "03cec18c-cb05-40d3-8a26-bf6cdc3c99c5",
      "name": "HTML",
      "type": "n8n-nodes-base.html",
      "position": [
        704,
        -112
      ],
      "parameters": {
        "html": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>{{ $json.output.companyName }} Case Study</title>\n    <style>\n        /* Import Manrope font */\n        @import url('https://fonts.googleapis.com/css2?family=Manrope:wght@200;300;400;500;600;700;800&display=swap');\n        \n        /* CSS Variables for Interlinked Brand Colors */\n        :root {\n            /* Primary Colors */\n            --primary-01: #FAFBFF;\n            --primary-02: #004EEA;\n            --primary-03: #001B35;\n            --primary-04: #008DED;\n            \n            /* Grayscale Colors */\n            --cloud: #EDEFF7;\n            --smoke: #D3D6E0;\n            --steel: #BCBFCC;\n            --space: #9DA2B3;\n            --graphite: #6E7180;\n            --arsenic: #40424D;\n            --phantom: #1E1E24;\n            --black: #000000;\n        }\n        \n        /* Reset and Base Styles */\n        * {\n            margin: 0;\n            padding: 0;\n            box-sizing: border-box;\n        }\n        \n        body {\n            font-family: 'Manrope', sans-serif;\n            background-color: var(--primary-01);\n            color: var(--primary-03);\n            line-height: 1.6;\n            overflow-x: hidden;\n        }\n        \n        /* Header Styles */\n        header {\n            background-color: var(--primary-03);\n            padding: 2rem 0;\n            position: fixed;\n            width: 100%;\n            top: 0;\n            z-index: 1000;\n            box-shadow: 0 2px 10px rgba(0, 27, 53, 0.1);\n        }\n        \n        .header-content {\n            max-width: 1200px;\n            margin: 0 auto;\n            padding: 0 2rem;\n            display: flex;\n            justify-content: space-between;\n            align-items: center;\n        }\n        \n        .logo {\n            display: flex;\n            align-items: center;\n            gap: 0.5rem;\n            text-decoration: none;\n            color: white;\n            font-weight: 700;\n            font-size: 1.5rem;\n        }\n        \n        .logo-icon {\n            width: 40px;\n            height: 40px;\n            position: relative;\n        }\n        \n        .logo-icon::before,\n        .logo-icon::after {\n            content: '';\n            position: absolute;\n            width: 20px;\n            height: 20px;\n            border-radius: 4px;\n        }\n        \n        .logo-icon::before {\n            background-color: var(--primary-02);\n            top: 0;\n            left: 0;\n        }\n        \n        .logo-icon::after {\n            background-color: var(--primary-04);\n            bottom: 0;\n            right: 0;\n        }\n        \n        /* Main Content */\n        main {\n            margin-top: 100px;\n            min-height: calc(100vh - 100px);\n        }\n        \n        /* Hero Section */\n        .hero {\n            background: linear-gradient(135deg, var(--primary-03) 0%, var(--primary-02) 100%);\n            color: white;\n            padding: 4rem 0;\n            position: relative;\n            overflow: hidden;\n        }\n        \n        .hero::before {\n            content: '';\n            position: absolute;\n            top: -50%;\n            right: -10%;\n            width: 500px;\n            height: 500px;\n            background: radial-gradient(circle, var(--primary-04) 0%, transparent 70%);\n            opacity: 0.3;\n            border-radius: 50%;\n        }\n        \n        .hero-content {\n            max-width: 1200px;\n            margin: 0 auto;\n            padding: 0 2rem;\n            position: relative;\n            z-index: 1;\n        }\n        \n        .hero h1 {\n            font-size: 3rem;\n            font-weight: 800;\n            margin-bottom: 1rem;\n            animation: fadeInUp 0.8s ease-out;\n        }\n        \n        .hero .tagline {\n            font-size: 1.25rem;\n            font-weight: 300;\n            margin-bottom: 2rem;\n            opacity: 0.9;\n            animation: fadeInUp 0.8s ease-out 0.2s backwards;\n        }\n        \n        .hero-meta {\n            display: flex;\n            gap: 2rem;\n            flex-wrap: wrap;\n            animation: fadeInUp 0.8s ease-out 0.4s backwards;\n        }\n        \n        .meta-item {\n            display: flex;\n            flex-direction: column;\n            gap: 0.25rem;\n        }\n        \n        .meta-label {\n            font-size: 0.875rem;\n            opacity: 0.7;\n            text-transform: uppercase;\n            letter-spacing: 0.5px;\n        }\n        \n        .meta-value {\n            font-size: 1.125rem;\n            font-weight: 600;\n        }\n        \n        /* Section Styles */\n        .section {\n            padding: 4rem 0;\n        }\n        \n        .container {\n            max-width: 1200px;\n            margin: 0 auto;\n            padding: 0 2rem;\n        }\n        \n        .section-title {\n            font-size: 2.5rem;\n            font-weight: 700;\n            color: var(--primary-03);\n            margin-bottom: 3rem;\n            text-align: center;\n            position: relative;\n        }\n        \n        .section-title::after {\n            content: '';\n            position: absolute;\n            bottom: -1rem;\n            left: 50%;\n            transform: translateX(-50%);\n            width: 80px;\n            height: 4px;\n            background: linear-gradient(90deg, var(--primary-02) 0%, var(--primary-04) 100%);\n            border-radius: 2px;\n        }\n        \n        /* Description Section */\n        .description {\n            background-color: var(--cloud);\n        }\n        \n        .description-content {\n            max-width: 800px;\n            margin: 0 auto;\n            text-align: center;\n            font-size: 1.125rem;\n            line-height: 1.8;\n            color: var(--arsenic);\n        }\n        \n        /* Phases Section */\n        .phases {\n            background-color: white;\n        }\n        \n        .phases-grid {\n            display: grid;\n            grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));\n            gap: 2rem;\n            margin-top: 3rem;\n        }\n        \n        .phase-card {\n            background: linear-gradient(135deg, var(--primary-01) 0%, white 100%);\n            border-radius: 12px;\n            padding: 2rem;\n            box-shadow: 0 5px 20px rgba(0, 27, 53, 0.1);\n            transition: transform 0.3s ease, box-shadow 0.3s ease;\n            position: relative;\n            overflow: hidden;\n        }\n        \n        .phase-card::before {\n            content: '';\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 4px;\n            background: linear-gradient(90deg, var(--primary-02) 0%, var(--primary-04) 100%);\n        }\n        \n        .phase-card:hover {\n            transform: translateY(-5px);\n            box-shadow: 0 10px 30px rgba(0, 27, 53, 0.15);\n        }\n        \n        .phase-number {\n            display: inline-flex;\n            align-items: center;\n            justify-content: center;\n            width: 40px;\n            height: 40px;\n            background-color: var(--primary-02);\n            color: white;\n            border-radius: 50%;\n            font-weight: 700;\n            margin-bottom: 1rem;\n        }\n        \n        .phase-title {\n            font-size: 1.5rem;\n            font-weight: 700;\n            color: var(--primary-03);\n            margin-bottom: 1rem;\n        }\n        \n        .phase-description {\n            color: var(--graphite);\n            margin-bottom: 1.5rem;\n        }\n        \n        .phase-details {\n            display: flex;\n            flex-direction: column;\n            gap: 0.75rem;\n        }\n        \n        .detail-item {\n            display: flex;\n            gap: 0.5rem;\n            padding: 0.5rem 0;\n            border-bottom: 1px solid var(--cloud);\n        }\n        \n        .detail-label {\n            font-weight: 600;\n            color: var(--primary-02);\n            min-width: 100px;\n        }\n        \n        .detail-value {\n            color: var(--arsenic);\n            flex: 1;\n        }\n        \n        /* Timeline Section */\n        .timeline {\n            background-color: var(--cloud);\n        }\n        \n        .timeline-container {\n            position: relative;\n            padding: 2rem 0;\n        }\n        \n        .timeline-line {\n            position: absolute;\n            left: 50%;\n            top: 0;\n            bottom: 0;\n            width: 2px;\n            background-color: var(--primary-02);\n            transform: translateX(-50%);\n        }\n        \n        .timeline-item {\n            display: flex;\n            align-items: center;\n            margin-bottom: 3rem;\n            position: relative;\n        }\n        \n        .timeline-item:nth-child(even) {\n            flex-direction: row-reverse;\n        }\n        \n        .timeline-content {\n            flex: 1;\n            padding: 2rem;\n            background-color: white;\n            border-radius: 12px;\n            box-shadow: 0 5px 20px rgba(0, 27, 53, 0.1);\n            margin: 0 2rem;\n            position: relative;\n        }\n        \n        .timeline-dot {\n            position: absolute;\n            left: 50%;\n            transform: translateX(-50%);\n            width: 20px;\n            height: 20px;\n            background-color: var(--primary-04);\n            border: 4px solid white;\n            border-radius: 50%;\n            box-shadow: 0 0 0 4px var(--primary-02);\n            z-index: 1;\n        }\n        \n        .timeline-date {\n            font-weight: 700;\n            color: var(--primary-02);\n            margin-bottom: 0.5rem;\n        }\n        \n        .timeline-title {\n            font-size: 1.25rem;\n            font-weight: 600;\n            color: var(--primary-03);\n            margin-bottom: 0.5rem;\n        }\n        \n        .timeline-description {\n            color: var(--graphite);\n        }\n        \n        /* Deliverables Section */\n        .deliverables {\n            background-color: white;\n        }\n        \n        .deliverables-grid {\n            display: grid;\n            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));\n            gap: 2rem;\n            margin-top: 3rem;\n        }\n        \n        .deliverable-card {\n            background-color: var(--primary-01);\n            border-radius: 12px;\n            padding: 2rem;\n            text-align: center;\n            transition: transform 0.3s ease;\n            border: 2px solid transparent;\n        }\n        \n        .deliverable-card:hover {\n            transform: translateY(-5px);\n            border-color: var(--primary-02);\n        }\n        \n        .deliverable-icon {\n            width: 60px;\n            height: 60px;\n            background: linear-gradient(135deg, var(--primary-02) 0%, var(--primary-04) 100%);\n            border-radius: 12px;\n            margin: 0 auto 1.5rem;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            color: white;\n            font-size: 1.5rem;\n        }\n        \n        .deliverable-title {\n            font-size: 1.25rem;\n            font-weight: 600;\n            color: var(--primary-03);\n            margin-bottom: 1rem;\n        }\n        \n        .deliverable-description {\n            color: var(--graphite);\n        }\n        \n        /* CTA Section */\n        .cta-section {\n            background: linear-gradient(135deg, var(--primary-02) 0%, var(--primary-04) 100%);\n            color: white;\n            padding: 4rem 0;\n            text-align: center;\n        }\n        \n        .cta-content h2 {\n            font-size: 2.5rem;\n            font-weight: 700;\n            margin-bottom: 1rem;\n        }\n        \n        .cta-content p {\n            font-size: 1.25rem;\n            margin-bottom: 2rem;\n            opacity: 0.9;\n        }\n        \n        .cta-button {\n            display: inline-block;\n            padding: 1rem 2.5rem;\n            background-color: white;\n            color: var(--primary-02);\n            text-decoration: none;\n            border-radius: 50px;\n            font-weight: 600;\n            transition: transform 0.3s ease, box-shadow 0.3s ease;\n        }\n        \n        .cta-button:hover {\n            transform: translateY(-2px);\n            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);\n        }\n        \n        /* Footer */\n        footer {\n            background-color: var(--primary-03);\n            color: white;\n            padding: 2rem 0;\n            text-align: center;\n        }\n        \n        .footer-content {\n            max-width: 1200px;\n            margin: 0 auto;\n            padding: 0 2rem;\n        }\n        \n        /* Animations */\n        @keyframes fadeInUp {\n            from {\n                opacity: 0;\n                transform: translateY(30px);\n            }\n            to {\n                opacity: 1;\n                transform: translateY(0);\n            }\n        }\n        \n        /* Responsive Design */\n        @media (max-width: 768px) {\n            .hero h1 {\n                font-size: 2rem;\n            }\n            \n            .section-title {\n                font-size: 1.75rem;\n            }\n            \n            .timeline-line {\n                left: 20px;\n            }\n            \n            .timeline-item,\n            .timeline-item:nth-child(even) {\n                flex-direction: column;\n                padding-left: 40px;\n            }\n            \n            .timeline-dot {\n                left: 20px;\n            }\n            \n            .timeline-content {\n                margin: 0;\n            }\n            \n            .phases-grid,\n            .deliverables-grid {\n                grid-template-columns: 1fr;\n            }\n        }\n    </style>\n</head>\n<body>\n    <!-- Header -->\n    <header>\n        <div class=\"header-content\">\n            <a href=\"#\" class=\"logo\">\n                <div class=\"logo-icon\"></div>\n                <span>Your custom HTML here</span>\n            </a>\n        </div>\n    </header>\n\n    <!-- Main Content -->\n    <main>\n        <!-- Hero Section -->\n        <section class=\"hero\">\n            <div class=\"hero-content\">\n                <h1>{{ $json.output.companyName }} Case Study</h1>\n                <p class=\"tagline\">Empowering Possibilities, Humanly AI-Ligned</p>\n                <div class=\"hero-meta\">\n                    <div class=\"meta-item\">\n                        <span class=\"meta-label\">Industry</span>\n                        <span class=\"meta-value\">{{ $json.output.industry }}</span>\n                    </div>\n                    <div class=\"meta-item\">\n                        <span class=\"meta-label\">Duration</span>\n                        <span class=\"meta-value\">{{ $json.output.duration }}</span>\n                    </div>\n                    <div class=\"meta-item\">\n                        <span class=\"meta-label\">Investment</span>\n                        <span class=\"meta-value\">{{ $json.output.investment }}</span>\n                    </div>\n                </div>\n            </div>\n        </section>\n\n        <!-- Description Section -->\n        <section class=\"section description\">\n            <div class=\"container\">\n                <h2 class=\"section-title\">Overview</h2>\n                <p class=\"description-content\">\n                  {{ $json.output.description }}\n                </p>\n            </div>\n        </section>\n\n        <!-- Phases Section -->\n        <section class=\"section phases\">\n            <div class=\"container\">\n                <h2 class=\"section-title\">Implementation Phases</h2>\n                <div class=\"phases-grid\">\n                    <div class=\"phase-card\">\n                        <div class=\"phase-number\">1</div>\n                        <h3 class=\"phase-title\">{{ $json.output.phases[0].title }}</h3>\n                        <p class=\"phase-description\">{{ $json.output.phases[0].description }}</p>\n                        <div class=\"phase-details\">\n                            <div class=\"detail-item\">\n                                <span class=\"detail-label\">Year:</span>\n                                <span class=\"detail-value\">{{ $json.output.phases[0].details[0].value }}</span>\n                            </div>\n                            <div class=\"detail-item\">\n                                <span class=\"detail-label\">Key Activity:</span>\n                                <span class=\"detail-value\">{{ $json.output.phases[0].details[1].value }}</span>\n                            </div>\n                            <div class=\"detail-item\">\n                                <span class=\"detail-label\">Milestone:</span>\n                                <span class=\"detail-value\">{{ $json.output.phases[0].details[2].value }}</span>\n                            </div>\n                        </div>\n                    </div>\n\n                    <div class=\"phase-card\">\n                        <div class=\"phase-number\">2</div>\n                        <h3 class=\"phase-title\">{{ $json.output.phases[1].title }}</h3>\n                        <p class=\"phase-description\">{{ $json.output.phases[1].description }}</p>\n                        <div class=\"phase-details\">\n                            <div class=\"detail-item\">\n                                <span class=\"detail-label\">Year:</span>\n                                <span class=\"detail-value\">{{ $json.output.phases[1].details[0].value }}</span>\n                            </div>\n                            <div class=\"detail-item\">\n                                <span class=\"detail-label\">Key Activity:</span>\n                                <span class=\"detail-value\">{{ $json.output.phases[1].details[1].value }}</span>\n                            </div>\n                            <div class=\"detail-item\">\n                                <span class=\"detail-label\">Milestone:</span>\n                                <span class=\"detail-value\">{{ $json.output.phases[1].details[2].value }}</span>\n                            </div>\n                        </div>\n                    </div>\n\n                    <div class=\"phase-card\">\n                        <div class=\"phase-number\">3</div>\n                        <h3 class=\"phase-title\">{{ $json.output.phases[2].title }}</h3>\n                        <p class=\"phase-description\">{{ $json.output.phases[2].description }}</p>\n                        <div class=\"phase-details\">\n                            <div class=\"detail-item\">\n                                <span class=\"detail-label\">Year:</span>\n                                <span class=\"detail-value\">{{ $json.output.phases[2].details[0].value }}</span>\n                            </div>\n                            <div class=\"detail-item\">\n                                <span class=\"detail-label\">Key Activity:</span>\n                                <span class=\"detail-value\">{{ $json.output.phases[2].details[1].value }}</span>\n                            </div>\n                            <div class=\"detail-item\">\n                                <span class=\"detail-label\">Milestone:</span>\n                                <span class=\"detail-value\">{{ $json.output.phases[2].details[2].value }}</span>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </section>\n\n        <!-- Timeline Section -->\n        <section class=\"section timeline\">\n            <div class=\"container\">\n                <h2 class=\"section-title\">Key Milestones</h2>\n                <div class=\"timeline-container\">\n                    <div class=\"timeline-line\"></div>\n                    \n                    <div class=\"timeline-item\">\n                        <div class=\"timeline-content\">\n                            <div class=\"timeline-date\">{{ $json.output.timeline[0].duration }}</div>\n                            <h3 class=\"timeline-title\">{{ $json.output.timeline[0].title }}</h3>\n                            <p class=\"timeline-description\">{{ $json.output.timeline[0].description }}</p>\n                        </div>\n                        <div class=\"timeline-dot\"></div>\n                    </div>\n\n                    <div class=\"timeline-item\">\n                        <div class=\"timeline-content\">\n                            <div class=\"timeline-date\">{{ $json.output.timeline[1].duration }}</div>\n                            <h3 class=\"timeline-title\">{{ $json.output.timeline[1].title }}</h3>\n                            <p class=\"timeline-description\">{{ $json.output.timeline[1].description }}</p>\n                        </div>\n                        <div class=\"timeline-dot\"></div>\n                    </div>\n\n                    <div class=\"timeline-item\">\n                        <div class=\"timeline-content\">\n                            <div class=\"timeline-date\">{{ $json.output.timeline[2].duration }}</div>\n                            <h3 class=\"timeline-title\">{{ $json.output.timeline[2].title }}</h3>\n                            <p class=\"timeline-description\">{{ $json.output.timeline[2].description }}</p>\n                        </div>\n                        <div class=\"timeline-dot\"></div>\n                    </div>\n                </div>\n            </div>\n        </section>\n\n        <!-- Deliverables Section -->\n        <section class=\"section deliverables\">\n            <div class=\"container\">\n                <h2 class=\"section-title\">Key Deliverables</h2>\n                <div class=\"deliverables-grid\">\n                    <div class=\"deliverable-card\">\n                        <div class=\"deliverable-icon\">\ud83d\udd0d</div>\n                        <h3 class=\"deliverable-title\">{{ $json.output.deliverables[0].title }}</h3>\n                        <p class=\"deliverable-description\">{{ $json.output.deliverables[0].description }}</p>\n                    </div>\n\n                    <div class=\"deliverable-card\">\n                        <div class=\"deliverable-icon\">\ud83d\udcca</div>\n                        <h3 class=\"deliverable-title\">{{ $json.output.deliverables[1].title }}</h3>\n                        <p class=\"deliverable-description\">{{ $json.output.deliverables[1].description }}</p>\n                    </div>\n\n                    <div class=\"deliverable-card\">\n                        <div class=\"deliverable-icon\">\ud83d\udcf1</div>\n                        <h3 class=\"deliverable-title\">{{ $json.output.deliverables[2].title }}</h3>\n                        <p class=\"deliverable-description\">{{ $json.output.deliverables[2].description }}</p>\n                    </div>\n                </div>\n            </div>\n        </section>\n\n        <!-- CTA Section -->\n        <section class=\"cta-section\">\n            <div class=\"container\">\n                <div class=\"cta-content\">\n                    <h2>Ready to Transform Your Business with AI?</h2>\n                    <p>Let Interlinked help you navigate the AI revolution with integrity and empathy.</p>\n                    <a href={{ $json.output.ctaLink }} class=\"cta-button\">Learn More About This Case</a>\n                </div>\n            </div>\n        </section>\n    </main>\n\n    <!-- Footer -->\n    <footer>\n        <div class=\"footer-content\">\n            <p>&copy; Custom HTML. All rights reserved.</p>\n            <p>Empowering Possibilities, Humanly AI-Ligned.</p>\n        </div>\n    </footer>\n\n    <script>\n        // Smooth scroll for anchor links\n        document.querySelectorAll('a[href^=\"#\"]').forEach(anchor => {\n            anchor.addEventListener('click', function (e) {\n                e.preventDefault();\n                const target = document.querySelector(this.getAttribute('href'));\n                if (target) {\n                    target.scrollIntoView({\n                        behavior: 'smooth',\n                        block: 'start'\n                    });\n                }\n            });\n        });\n\n        // Add scroll animations\n        const observerOptions = {\n            threshold: 0.1,\n            rootMargin: '0px 0px -100px 0px'\n        };\n\n        const observer = new IntersectionObserver((entries) => {\n            entries.forEach(entry => {\n                if (entry.isIntersecting) {\n                    entry.target.style.animation = 'fadeInUp 0.8s ease-out forwards';\n                }\n            });\n        }, observerOptions);\n\n        // Observe elements for animation\n        document.querySelectorAll('.phase-card, .timeline-item, .deliverable-card').forEach(el => {\n            observer.observe(el);\n        });\n    </script>\n</body>\n</html>"
      },
      "typeVersion": 1.2
    },
    {
      "id": "a03ad7bd-cbe9-40a5-9ce6-7faf5fa3e811",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        288,
        -32
      ],
      "parameters": {
        "options": {
          "systemMessage": "YOU are a researcher finding the outputs based on the connected JSON inputs, ensure a comprehensive understanding."
        },
        "hasOutputParser": true
      },
      "typeVersion": 2.1
    },
    {
      "id": "b16ee4f2-91c2-4f17-8a9e-1a29fe644ad3",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        560,
        176
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"companyName\": \"[CLIENT_COMPANY_NAME]\",\n  \"industry\": \"[CLIENT_INDUSTRY]\",\n  \"duration\": \"[PROJECT_DURATION]\",\n  \"investment\": \"[INVESTMENT_RANGE]\",\n  \"description\": \"[CLIENT_DESCRIPTION_AND_CHALLENGES]\",\n  \"phases\": [\n    {\n      \"number\": 1,\n      \"title\": \"[PHASE_1_TITLE]\",\n      \"description\": \"[PHASE_1_DESCRIPTION]\",\n      \"details\": [\n        {\n          \"label\": \"Duration\",\n          \"value\": \"[PHASE_1_DURATION]\"\n        },\n        {\n          \"label\": \"Key Activities\",\n          \"value\": \"[PHASE_1_ACTIVITIES]\"\n        },\n        {\n          \"label\": \"Outcome\",\n          \"value\": \"[PHASE_1_OUTCOME]\"\n        }\n      ]\n    },\n    {\n      \"number\": 2,\n      \"title\": \"[PHASE_2_TITLE]\",\n      \"description\": \"[PHASE_2_DESCRIPTION]\",\n      \"details\": [\n        {\n          \"label\": \"Duration\",\n          \"value\": \"[PHASE_2_DURATION]\"\n        },\n        {\n          \"label\": \"Key Activities\",\n          \"value\": \"[PHASE_2_ACTIVITIES]\"\n        },\n        {\n          \"label\": \"Outcome\",\n          \"value\": \"[PHASE_2_OUTCOME]\"\n        }\n      ]\n    },\n    {\n      \"number\": 3,\n      \"title\": \"[PHASE_3_TITLE]\",\n      \"description\": \"[PHASE_3_DESCRIPTION]\",\n      \"details\": [\n        {\n          \"label\": \"Duration\",\n          \"value\": \"[PHASE_3_DURATION]\"\n        },\n        {\n          \"label\": \"Key Activities\",\n          \"value\": \"[PHASE_3_ACTIVITIES]\"\n        },\n        {\n          \"label\": \"Outcome\",\n          \"value\": \"[PHASE_3_OUTCOME]\"\n        }\n      ]\n    },\n    {\n      \"number\": 4,\n      \"title\": \"[PHASE_4_TITLE]\",\n      \"description\": \"[PHASE_4_DESCRIPTION]\",\n      \"details\": [\n        {\n          \"label\": \"Duration\",\n          \"value\": \"[PHASE_4_DURATION]\"\n        },\n        {\n          \"label\": \"Key Activities\",\n          \"value\": \"[PHASE_4_ACTIVITIES]\"\n        },\n        {\n          \"label\": \"Outcome\",\n          \"value\": \"[PHASE_4_OUTCOME]\"\n        }\n      ]\n    }\n  ],\n  \"timeline\": [\n    {\n      \"title\": \"[TIMELINE_1_TITLE]\",\n      \"duration\": \"[TIMELINE_1_DURATION]\",\n      \"description\": \"[TIMELINE_1_DESCRIPTION]\"\n    },\n    {\n      \"title\": \"[TIMELINE_2_TITLE]\",\n      \"duration\": \"[TIMELINE_2_DURATION]\",\n      \"description\": \"[TIMELINE_2_DESCRIPTION]\"\n    },\n    {\n      \"title\": \"[TIMELINE_3_TITLE]\",\n      \"duration\": \"[TIMELINE_3_DURATION]\",\n      \"description\": \"[TIMELINE_3_DESCRIPTION]\"\n    },\n    {\n      \"title\": \"[TIMELINE_4_TITLE]\",\n      \"duration\": \"[TIMELINE_4_DURATION]\",\n      \"description\": \"[TIMELINE_4_DESCRIPTION]\"\n    },\n    {\n      \"title\": \"[TIMELINE_5_TITLE]\",\n      \"duration\": \"[TIMELINE_5_DURATION]\",\n      \"description\": \"[TIMELINE_5_DESCRIPTION]\"\n    },\n    {\n      \"title\": \"[TIMELINE_6_TITLE]\",\n      \"duration\": \"[TIMELINE_6_DURATION]\",\n      \"description\": \"[TIMELINE_6_DESCRIPTION]\"\n    }\n  ],\n  \"deliverables\": [\n    {\n      \"title\": \"[DELIVERABLE_1_TITLE]\",\n      \"description\": \"[DELIVERABLE_1_DESCRIPTION]\"\n    },\n    {\n      \"title\": \"[DELIVERABLE_2_TITLE]\",\n      \"description\": \"[DELIVERABLE_2_DESCRIPTION]\"\n    },\n    {\n      \"title\": \"[DELIVERABLE_3_TITLE]\",\n      \"description\": \"[DELIVERABLE_3_DESCRIPTION]\"\n    },\n    {\n      \"title\": \"[DELIVERABLE_4_TITLE]\",\n      \"description\": \"[DELIVERABLE_4_DESCRIPTION]\"\n    },\n    {\n      \"title\": \"[DELIVERABLE_5_TITLE]\",\n      \"description\": \"[DELIVERABLE_5_DESCRIPTION]\"\n    },\n    {\n      \"title\": \"[DELIVERABLE_6_TITLE]\",\n      \"description\": \"[DELIVERABLE_6_DESCRIPTION]\"\n    }\n  ],\n  \"ctaLink\": \"[CONSULTATION_BOOKING_LINK]\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "b52071e4-6c90-471c-bbec-5f00a5565c4e",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        208,
        176
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "62bd86f5-824e-4cbd-b3f6-5403d11a43c5",
      "name": "When chat message received",
      "type": "@n8n/n8n-nodes-langchain.chatTrigger",
      "position": [
        64,
        -96
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.1
    },
    {
      "id": "0c947c9a-8509-4fd4-b6f7-530bac41a46a",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        656,
        -320
      ],
      "parameters": {
        "color": 6,
        "width": 208,
        "height": 400,
        "content": "## HTML Preset\nUses **JSON** prefill's to dynamically change and produce HTML docs. Perfect for document creation and internet posts."
      },
      "typeVersion": 1
    },
    {
      "id": "469976df-2f3b-4148-bbc6-cb634d9cd7df",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        512,
        128
      ],
      "parameters": {
        "color": 6,
        "width": 176,
        "height": 480,
        "content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Changeable JSON\nThe **Structured Output** forces the AI model to complete based on your topic/input\n\n\"Ask an AI Model to create based on the HTML Blueprint\"\n"
      },
      "typeVersion": 1
    },
    {
      "id": "9bb987ff-7009-4b8d-b409-ef54c7cc87ae",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        16,
        -320
      ],
      "parameters": {
        "color": 6,
        "width": 208,
        "height": 384,
        "content": "## Simple Input\nAllow for a small **(one word to one sentence)** input for dynamic connection to other flows.\n\nFeel free to connect to a schedule for regular reports/document.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "0240213a-e40c-479c-9a1c-abdd488aa6e3",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        960,
        -400
      ],
      "parameters": {
        "color": 6,
        "width": 192,
        "height": 336,
        "content": "## Community PDF Transfer\nUse's a community node to transform the HTML into pdf"
      },
      "typeVersion": 1
    },
    {
      "id": "8ced81eb-5ac3-4579-b906-3c1b0726f722",
      "name": "PDFco Api",
      "type": "n8n-nodes-pdfco.PDFco Api",
      "position": [
        1008,
        -240
      ],
      "parameters": {
        "html": "={{ $json.html }}",
        "operation": "URL/HTML to PDF",
        "convertType": "htmlToPDF",
        "advancedOptions": {}
      },
      "credentials": {
        "pdfcoApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "3864ba3d-9d8c-4d8a-b82b-5336aa96afe5",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        960,
        0
      ],
      "parameters": {
        "color": 6,
        "width": 192,
        "height": 368,
        "content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Amazon Call\nInvoke a Amazon function to transform HTML to desired formats with greater control"
      },
      "typeVersion": 1
    },
    {
      "id": "567f203c-5e6d-44c3-8910-49bbcadf1181",
      "name": "AWS Upload",
      "type": "n8n-nodes-base.awsS3",
      "position": [
        1008,
        32
      ],
      "parameters": {
        "fileName": "={{ $('When chat message received').item.json.chatInput }}",
        "operation": "upload",
        "binaryData": false,
        "bucketName": "interlinkedhtmlhosting",
        "fileContent": "={{ $json.html }}",
        "additionalFields": {}
      },
      "credentials": {
        "aws": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "1ffd74fa-0bc4-4bba-876a-d60df2359693",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -416,
        -336
      ],
      "parameters": {
        "width": 352,
        "height": 864,
        "content": "# Read Me First!\n**This template generates HTML based on predefined JSON inputs**\n\nUse cases are many: You could use this to automate blog post in your chosen HTML structure or even serve clients a custom document via HTTP.\n\nThe real value of this workflow though, is in its inspirational spirit, imagine the documents and branding that could be quickly generated!!\n\n**How It Works**\n+ The chat trigger is designed to accomodate a small amount of text. The chat is a placeholder for another input of yours in which triggers the generation of the JSON output\n+ A LLM of your choice takes the input and comes up with the responses\n+ The output parser is the crux of this flow. The AI Agent is forced to output its response as a JSON in which can be dynamically changed meaning the HTML can be frequently iterated on.\n+ The HTML Preset is used as a static base for your document/blog. This JSON inputs are embedded within the code.\n+The community PDF transfer or AWS upload are entirely for visualisation. The HTML can be pushed and served via AWS or simply downloaded using PDFco\n\n**How to use**\n+ Simple type \"Google\" into the chat or connect your other triggers/outputs\n\n**Requirements**\n+ HTML Preset with interchangeable JSON inputs\n+ PDFco or AWS Account\n\n\n"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "HTML": {
      "main": [
        [
          {
            "node": "PDFco Api",
            "type": "main",
            "index": 0
          },
          {
            "node": "AWS Upload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "AI Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "When chat message received": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow contains community nodes that are only compatible with the self-hosted version of n8n.

Source: https://n8n.io/workflows/7003/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

[](https://www.youtube.com/watch?v=o1x8Tw_7FwQ)

Chat Trigger, Agent Tool, Output Parser Structured +6
AI & RAG

This n8n template provides a powerful AI-powered chatbot that acts as your personal Spotify DJ. Simply tell the chatbot what kind of music you're in the mood for, and it will intelligently create a cu

OpenAI Chat, Spotify, Chain Llm +7
AI & RAG

This workflow researches prospects using MadKudu MCP, generates personalized emails with OpenAI, and syncs them to Outreach with automatic sequence enrollment. Its for SDRs and sales teams who want to

HTTP Request, Mcp Client Tool, Chat Trigger +4
AI & RAG

ModelRouter. Uses chatTrigger, agent, modelSelector, httpRequest. Chat trigger; 28 nodes.

Chat Trigger, Agent, Model Selector +8
AI & RAG

This powerful workflow can take hours of difficult research attempting to identify the perfect product to buy and condense it into a few short minutes. Simply typing the name of an item you wish to pu

Chat Trigger, OpenAI Chat, Memory Buffer Window +3