import os import csv import requests from bs4 import BeautifulSoup from fpdf import FPDF # ------------------------------------------------------------------------- # CODE & CANVAS BRAND DESIGN TOKENS # ------------------------------------------------------------------------- COLOR_LINEN = (250, 248, 245) # #FAF8F5 - Default background canvas COLOR_NAVY = (26, 35, 50) # #1A2332 - Deep structural base color COLOR_TERRACOTTA = (211, 107, 77) # #D36B4D - Primary visual accents COLOR_CHARCOAL = (43, 43, 43) # #2B2B2B - High-legibility body text COLOR_BORDER = (229, 222, 201) # #E5DEC9 - Thin muted gridlines LOCAL_CSV_PATH = "RepoDatabase.csv" REMOTE_CSV_URL = "https://raw.githubusercontent.com/CodeAndCanvas728/repobase/refs/heads/main/RepoDatabase.csv" class CodeCanvasCarousel(FPDF): def __init__(self): # Initialize in Landscape mode ('L') using millimeters, explicitly custom sizing (A5 Landscape) super().__init__(orientation='L', unit='mm', format='A5') self.set_margins(20, 25, 20) self.set_auto_page_break(False) def draw_brand_canvas(self): """Fills background with Linen Canvas and draws the minimal header framework.""" self.set_fill_color(*COLOR_LINEN) self.rect(0, 0, 210, 148, 'F') # A5 Landscape boundary dimensions # Thin editorial top rule self.set_draw_color(*COLOR_BORDER) self.set_line_width(0.4) self.line(20, 15, 190, 15) # Standalone Ampersand Shorthand as visual anchor self.set_text_color(*COLOR_TERRACOTTA) self.set_font("Times", "I", 16) self.text(20, 24, "&") # Sans-serif technical meta-tag self.set_text_color(*COLOR_NAVY) self.set_font("Helvetica", "B", 7) self.text(28, 22, "CODE & CANVAS | INSIGHTS") def draw_footer(self, current_slide, total_slides): """Draws page numbering following clean, minimal layout scales.""" self.set_text_color(*COLOR_CHARCOAL) self.set_font("Helvetica", "", 8) self.text(180, 138, f"{current_slide} / {total_slides}") def clean_typography(text): """Enforces absolute micro-styling purity: completely strips out em-dashes.""" return text.replace("—", " : ").replace("--", " - ") def fetch_and_update_subject(): rows = [] selected_subject = None file_exists_locally = os.path.exists(LOCAL_CSV_PATH) if file_exists_locally: with open(LOCAL_CSV_PATH, mode='r', newline='', encoding='utf-8') as f: reader = csv.DictReader(f) fieldnames = reader.fieldnames for row in reader: if not selected_subject and row.get('Used', '').strip().lower() == 'no': row['Used'] = 'yes' selected_subject = { "title": row['Title'], "desc": row['Description'], "points": [row['Point1'], row['Point2'], row['Point3']], "url": row.get('URL', f"https://github.com/search?q={row['Title']}") } rows.append(row) if selected_subject and file_exists_locally: with open(LOCAL_CSV_PATH, mode='w', newline='', encoding='utf-8') as f: writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() writer.writerows(rows) return selected_subject # Ultimate fallback logic if CSV down or empty return { "title": "Model Context Protocol", "desc": "An open standard enabling secure, structured data communication layers between local environments and generative applications.", "points": ["Eliminates custom integration glue code", "Maintains clean architectural boundaries", "Built for cross-tool interoperability"], "url": "https://github.com/modelcontextprotocol" } def generate_assets(): data = fetch_and_update_subject() title = clean_typography(data['title']) desc = clean_typography(data['desc']) points = [clean_typography(p) for p in data['points']] os.makedirs("_drafts", exist_ok=True) TOTAL_SLIDES = 4 pdf = CodeCanvasCarousel() # ------------------------------------------------------------------------- # SLIDE 1: DISPLAY TITLE CARD # ------------------------------------------------------------------------- pdf.add_page() pdf.draw_brand_canvas() pdf.set_y(45) pdf.set_text_color(*COLOR_NAVY) pdf.set_font("Times", "", 32) # Editorial high-contrast serif display pdf.multi_cell(170, 14, title) pdf.set_y(pdf.get_y() + 6) pdf.set_text_color(*COLOR_CHARCOAL) pdf.set_font("Helvetica", "", 12) # Sans-serif structural subtitle pdf.multi_cell(170, 6, "An architectural breakdown of engineering utility and integration footprints.") pdf.draw_footer(1, TOTAL_SLIDES) # ------------------------------------------------------------------------- # SLIDE 2: THE CORE PROBLEMATIQUE / OVERVIEW # ------------------------------------------------------------------------- pdf.add_page() pdf.draw_brand_canvas() pdf.set_y(40) pdf.set_text_color(*COLOR_NAVY) pdf.set_font("Times", "", 18) pdf.cell(170, 8, "Core Structural Objective", ln=True) # Subtle geometric divider line pdf.set_draw_color(*COLOR_BORDER) pdf.line(20, pdf.get_y() + 2, 60, pdf.get_y() + 2) pdf.set_y(pdf.get_y() + 12) pdf.set_text_color(*COLOR_CHARCOAL) pdf.set_font("Helvetica", "", 11) pdf.multi_cell(170, 7, desc) pdf.draw_footer(2, TOTAL_SLIDES) # ------------------------------------------------------------------------- # SLIDE 3: TECHNICAL CONSIDERATIONS (GRID BLOCK) # ------------------------------------------------------------------------- pdf.add_page() pdf.draw_brand_canvas() pdf.set_y(38) pdf.set_text_color(*COLOR_NAVY) pdf.set_font("Times", "", 18) pdf.cell(170, 8, "Key Architecture Vectors", ln=True) start_y = pdf.get_y() + 8 for idx, pt in enumerate(points): current_item_y = start_y + (idx * 22) # Structural card containers using thin borders pdf.set_draw_color(*COLOR_BORDER) pdf.set_fill_color(*COLOR_LINEN) pdf.rect(20, current_item_y, 170, 16, 'DF') # Terracotta index anchor points pdf.set_y(current_item_y + 4) pdf.set_x(24) pdf.set_text_color(*COLOR_TERRACOTTA) pdf.set_font("Times", "I", 11) pdf.cell(10, 8, f"0{idx+1}") # Clean structural sans body text pdf.set_x(36) pdf.set_text_color(*COLOR_CHARCOAL) pdf.set_font("Helvetica", "", 10) pdf.cell(150, 8, pt) pdf.draw_footer(3, TOTAL_SLIDES) # ------------------------------------------------------------------------- # SLIDE 4: THE CALL TO ACTION / ARCHITECTURE ROOT # ------------------------------------------------------------------------- pdf.add_page() pdf.draw_brand_canvas() pdf.set_y(45) pdf.set_text_color(*COLOR_NAVY) pdf.set_font("Times", "", 24) pdf.multi_cell(170, 10, f"Explore the Open-Source Blueprint") pdf.set_y(pdf.get_y() + 10) pdf.set_text_color(*COLOR_CHARCOAL) pdf.set_font("Helvetica", "", 11) pdf.multi_cell(170, 6, "Review the configuration patterns, track the baseline execution logs, and implement the layout block directly into your development container environments.") # High-contrast action footer block pdf.set_y(pdf.get_y() + 12) pdf.set_text_color(*COLOR_TERRACOTTA) pdf.set_font("Helvetica", "B", 10) pdf.cell(170, 6, f"Source Index: {data['url']}", ln=True) pdf.draw_footer(4, TOTAL_SLIDES) # Output file generation paths pdf.output("_drafts/weekly-draft.pdf") # ------------------------------------------------------------------------- # GENERATE MARKDOWN TEXT FILE # ------------------------------------------------------------------------- post_copy = f"""💡 Weekly AI Architecture Breakdown Looking closely at modern workflows, complexity often hides in plain sight. Today we are looking at {title}. What it is: {desc} Key Architecture Considerations: • {points[0]} • {points[1]} • {points[2]} The complete visual documentation is attached below as an editorial carousel blueprint. Repository Link: {data['url']} #SoftwareArchitecture #DeveloperTools #TechInsights #CodeAndCanvas""" with open("_drafts/weekly-draft.md", mode='w', encoding='utf-8') as f: f.write(post_copy) if __name__ == "__main__": generate_assets()