[{"data":1,"prerenderedAt":1326},["ShallowReactive",2],{"work-\u002Fwork\u002Fpdf-to-platform-automation":3},{"id":4,"title":5,"body":6,"date":1309,"description":1310,"extension":1311,"externalUrl":1312,"featured":1313,"kind":1314,"meta":1315,"navigation":226,"path":1317,"seo":1318,"stem":1319,"tags":1320,"__hash__":1325},"work\u002Fwork\u002Fpdf-to-platform-automation.md","PDF to digital: automated compliance forms",{"type":7,"value":8,"toc":1298},"minimark",[9,14,19,23,32,36,39,55,58,62,67,95,99,106,109,405,408,419,426,768,771,785,792,1110,1113,1127,1131,1138,1149,1160,1163,1174,1181,1184,1198,1205,1208,1222,1226,1276,1280,1283,1286,1289,1294],[10,11,13],"h1",{"id":12},"automating-pdf-form-digitization-with-llms","Automating PDF form digitization with LLMs",[15,16,18],"h2",{"id":17},"context","Context",[20,21,22],"p",{},"While working on partnership development for our compliance platform, we identified an opportunity to demonstrate value to a potential enterprise partner. They had comprehensive compliance templates (QM10 and QM20) available only as PDFs. Instead of traditional sales outreach, I proposed building their templates directly on our platform as a proof of concept.",[24,25,26],"blockquote",{},[20,27,28],{},[29,30,31],"em",{},"Note: While the specific partner and compliance details are kept confidential, this case study focuses on the technical approach to solving a common enterprise challenge: converting unstructured PDF forms into interactive digital workflows.",[15,33,35],{"id":34},"what-i-built","What I Built",[20,37,38],{},"I developed an automated pipeline that could:",[40,41,42,46,49,52],"ol",{},[43,44,45],"li",{},"Extract structured data from complex PDF compliance forms",[43,47,48],{},"Transform the data into a standardized format",[43,50,51],{},"Automatically generate digital workflows through our platform's GraphQL API",[43,53,54],{},"Create a complete, interactive compliance assessment ready for immediate use",[20,56,57],{},"The end result was a fully-functional digital version of their compliance workflow that we could demonstrate during partnership discussions.",[15,59,61],{"id":60},"technical-breakdown","Technical Breakdown",[63,64,66],"h3",{"id":65},"stack-tools","Stack & Tools",[68,69,70,77,83,89],"ul",{},[43,71,72,76],{},[73,74,75],"strong",{},"TypeScript\u002FNode.js",": Core implementation",[43,78,79,82],{},[73,80,81],{},"OpenAI GPT API",": PDF content extraction and structuring",[43,84,85,88],{},[73,86,87],{},"GraphQL",": Platform API integration",[43,90,91,94],{},[73,92,93],{},"PDF Processing",": Initial exploration with PDF parsing libraries",[63,96,98],{"id":97},"key-architecture-decisions","Key Architecture Decisions",[40,100,101],{},[43,102,103],{},[73,104,105],{},"LLM-Based Data Extraction",[20,107,108],{},"After initially exploring traditional PDF parsing libraries, I pivoted to using OpenAI's GPT for data extraction. Here's why:",[110,111,116],"pre",{"className":112,"code":113,"language":114,"meta":115,"style":115},"language-typescript shiki shiki-themes material-theme-lighter github-light github-dark","\u002F\u002F Example of the structured data format we achieved\ninterface ComplianceSection {\n  title: string;\n  informationText: string;\n  goal: string;\n  booleanQuestions: string[];\n  mappingIndication: string[];\n}\n\n\u002F\u002F Sample of extracted and structured data\nconst extractedData = [\n  {\n    title: \"1.2 Informatiebeveiligingsbeleid en bestuurlijke goedkeuring\",\n    informationText: \"Het management van de organisatie dient...\",\n    goal: \"Voorkomen dat er informatiebeveiligingsincidenten...\",\n    booleanQuestions: [\n      \"Heeft de organisatie een gedetailleerd informatiebeveiligingsbeleid...?\",\n      \u002F\u002F More questions...\n    ],\n    mappingIndication: [\n      \"ISO 27001: A.5.1 – Information security policies\",\n      \u002F\u002F More mappings...\n    ],\n  },\n  \u002F\u002F More sections...\n];\n","typescript","",[117,118,119,128,143,161,173,185,201,215,221,228,234,250,256,279,296,313,323,336,342,350,360,372,378,385,391,397],"code",{"__ignoreMap":115},[120,121,124],"span",{"class":122,"line":123},"line",1,[120,125,127],{"class":126},"sutJx","\u002F\u002F Example of the structured data format we achieved\n",[120,129,131,135,139],{"class":122,"line":130},2,[120,132,134],{"class":133},"sbsja","interface",[120,136,138],{"class":137},"sbgvK"," ComplianceSection",[120,140,142],{"class":141},"sP7_E"," {\n",[120,144,146,150,154,158],{"class":122,"line":145},3,[120,147,149],{"class":148},"sucvu","  title",[120,151,153],{"class":152},"smGrS",":",[120,155,157],{"class":156},"sZMiF"," string",[120,159,160],{"class":141},";\n",[120,162,164,167,169,171],{"class":122,"line":163},4,[120,165,166],{"class":148},"  informationText",[120,168,153],{"class":152},[120,170,157],{"class":156},[120,172,160],{"class":141},[120,174,176,179,181,183],{"class":122,"line":175},5,[120,177,178],{"class":148},"  goal",[120,180,153],{"class":152},[120,182,157],{"class":156},[120,184,160],{"class":141},[120,186,188,191,193,195,199],{"class":122,"line":187},6,[120,189,190],{"class":148},"  booleanQuestions",[120,192,153],{"class":152},[120,194,157],{"class":156},[120,196,198],{"class":197},"su5hD","[]",[120,200,160],{"class":141},[120,202,204,207,209,211,213],{"class":122,"line":203},7,[120,205,206],{"class":148},"  mappingIndication",[120,208,153],{"class":152},[120,210,157],{"class":156},[120,212,198],{"class":197},[120,214,160],{"class":141},[120,216,218],{"class":122,"line":217},8,[120,219,220],{"class":141},"}\n",[120,222,224],{"class":122,"line":223},9,[120,225,227],{"emptyLinePlaceholder":226},true,"\n",[120,229,231],{"class":122,"line":230},10,[120,232,233],{"class":126},"\u002F\u002F Sample of extracted and structured data\n",[120,235,237,240,244,247],{"class":122,"line":236},11,[120,238,239],{"class":133},"const",[120,241,243],{"class":242},"s_hVV"," extractedData",[120,245,246],{"class":152}," =",[120,248,249],{"class":197}," [\n",[120,251,253],{"class":122,"line":252},12,[120,254,255],{"class":141},"  {\n",[120,257,259,263,265,269,273,276],{"class":122,"line":258},13,[120,260,262],{"class":261},"skxfh","    title",[120,264,153],{"class":141},[120,266,268],{"class":267},"sjJ54"," \"",[120,270,272],{"class":271},"s_sjI","1.2 Informatiebeveiligingsbeleid en bestuurlijke goedkeuring",[120,274,275],{"class":267},"\"",[120,277,278],{"class":141},",\n",[120,280,282,285,287,289,292,294],{"class":122,"line":281},14,[120,283,284],{"class":261},"    informationText",[120,286,153],{"class":141},[120,288,268],{"class":267},[120,290,291],{"class":271},"Het management van de organisatie dient...",[120,293,275],{"class":267},[120,295,278],{"class":141},[120,297,299,302,304,306,309,311],{"class":122,"line":298},15,[120,300,301],{"class":261},"    goal",[120,303,153],{"class":141},[120,305,268],{"class":267},[120,307,308],{"class":271},"Voorkomen dat er informatiebeveiligingsincidenten...",[120,310,275],{"class":267},[120,312,278],{"class":141},[120,314,316,319,321],{"class":122,"line":315},16,[120,317,318],{"class":261},"    booleanQuestions",[120,320,153],{"class":141},[120,322,249],{"class":197},[120,324,326,329,332,334],{"class":122,"line":325},17,[120,327,328],{"class":267},"      \"",[120,330,331],{"class":271},"Heeft de organisatie een gedetailleerd informatiebeveiligingsbeleid...?",[120,333,275],{"class":267},[120,335,278],{"class":141},[120,337,339],{"class":122,"line":338},18,[120,340,341],{"class":126},"      \u002F\u002F More questions...\n",[120,343,345,348],{"class":122,"line":344},19,[120,346,347],{"class":197},"    ]",[120,349,278],{"class":141},[120,351,353,356,358],{"class":122,"line":352},20,[120,354,355],{"class":261},"    mappingIndication",[120,357,153],{"class":141},[120,359,249],{"class":197},[120,361,363,365,368,370],{"class":122,"line":362},21,[120,364,328],{"class":267},[120,366,367],{"class":271},"ISO 27001: A.5.1 – Information security policies",[120,369,275],{"class":267},[120,371,278],{"class":141},[120,373,375],{"class":122,"line":374},22,[120,376,377],{"class":126},"      \u002F\u002F More mappings...\n",[120,379,381,383],{"class":122,"line":380},23,[120,382,347],{"class":197},[120,384,278],{"class":141},[120,386,388],{"class":122,"line":387},24,[120,389,390],{"class":141},"  },\n",[120,392,394],{"class":122,"line":393},25,[120,395,396],{"class":126},"  \u002F\u002F More sections...\n",[120,398,400,403],{"class":122,"line":399},26,[120,401,402],{"class":197},"]",[120,404,160],{"class":141},[20,406,407],{},"This approach provided superior results compared to traditional PDF parsing because:",[68,409,410,413,416],{},[43,411,412],{},"PDFs contained complex formatting and tables",[43,414,415],{},"LLM could understand context and relationships between elements",[43,417,418],{},"Structured output was more reliable and required less cleanup",[40,420,421],{"start":130},[43,422,423],{},[73,424,425],{},"Automated Form Generation Pipeline",[110,427,429],{"className":112,"code":428,"language":114,"meta":115,"style":115},"async function main() {\n  \u002F\u002F Authentication\n  await signIn(baseUrl, process.env.USERNAME, process.env.PASSWORD);\n\n  \u002F\u002F Create base form structure\n  const formCollection = await createFormCollection({\n    tenantId: tenant.id,\n    data: { name: \"QM20 Assessment Form\" },\n  });\n\n  \u002F\u002F Process each section from extracted data\n  for (const section of extractedData) {\n    const formSection = await createFormSection({\n      tenantId: tenant.id,\n      formId: formId,\n      data: {\n        title: section.title,\n        description: section.informationText,\n      },\n    });\n\n    \u002F\u002F Create dynamic form fields\n    await createFormFields(tenant.id, formSection.id, section);\n  }\n}\n",[117,430,431,448,453,503,507,512,533,550,575,584,588,593,616,635,650,662,671,687,703,708,717,721,726,759,764],{"__ignoreMap":115},[120,432,433,436,439,443,446],{"class":122,"line":123},[120,434,435],{"class":133},"async",[120,437,438],{"class":133}," function",[120,440,442],{"class":441},"sGLFI"," main",[120,444,445],{"class":141},"()",[120,447,142],{"class":141},[120,449,450],{"class":122,"line":130},[120,451,452],{"class":126},"  \u002F\u002F Authentication\n",[120,454,455,459,462,465,468,471,474,477,480,482,485,487,489,491,493,495,498,501],{"class":122,"line":145},[120,456,458],{"class":457},"sVHd0","  await",[120,460,461],{"class":441}," signIn",[120,463,464],{"class":261},"(",[120,466,467],{"class":197},"baseUrl",[120,469,470],{"class":141},",",[120,472,473],{"class":197}," process",[120,475,476],{"class":141},".",[120,478,479],{"class":197},"env",[120,481,476],{"class":141},[120,483,484],{"class":242},"USERNAME",[120,486,470],{"class":141},[120,488,473],{"class":197},[120,490,476],{"class":141},[120,492,479],{"class":197},[120,494,476],{"class":141},[120,496,497],{"class":242},"PASSWORD",[120,499,500],{"class":261},")",[120,502,160],{"class":141},[120,504,505],{"class":122,"line":163},[120,506,227],{"emptyLinePlaceholder":226},[120,508,509],{"class":122,"line":175},[120,510,511],{"class":126},"  \u002F\u002F Create base form structure\n",[120,513,514,517,520,522,525,528,530],{"class":122,"line":187},[120,515,516],{"class":133},"  const",[120,518,519],{"class":242}," formCollection",[120,521,246],{"class":152},[120,523,524],{"class":457}," await",[120,526,527],{"class":441}," createFormCollection",[120,529,464],{"class":261},[120,531,532],{"class":141},"{\n",[120,534,535,538,540,543,545,548],{"class":122,"line":203},[120,536,537],{"class":261},"    tenantId",[120,539,153],{"class":141},[120,541,542],{"class":197}," tenant",[120,544,476],{"class":141},[120,546,547],{"class":197},"id",[120,549,278],{"class":141},[120,551,552,555,557,560,563,565,567,570,572],{"class":122,"line":217},[120,553,554],{"class":261},"    data",[120,556,153],{"class":141},[120,558,559],{"class":141}," {",[120,561,562],{"class":261}," name",[120,564,153],{"class":141},[120,566,268],{"class":267},[120,568,569],{"class":271},"QM20 Assessment Form",[120,571,275],{"class":267},[120,573,574],{"class":141}," },\n",[120,576,577,580,582],{"class":122,"line":223},[120,578,579],{"class":141},"  }",[120,581,500],{"class":261},[120,583,160],{"class":141},[120,585,586],{"class":122,"line":230},[120,587,227],{"emptyLinePlaceholder":226},[120,589,590],{"class":122,"line":236},[120,591,592],{"class":126},"  \u002F\u002F Process each section from extracted data\n",[120,594,595,598,601,603,606,609,611,614],{"class":122,"line":252},[120,596,597],{"class":457},"  for",[120,599,600],{"class":261}," (",[120,602,239],{"class":133},[120,604,605],{"class":242}," section",[120,607,608],{"class":152}," of",[120,610,243],{"class":197},[120,612,613],{"class":261},") ",[120,615,532],{"class":141},[120,617,618,621,624,626,628,631,633],{"class":122,"line":258},[120,619,620],{"class":133},"    const",[120,622,623],{"class":242}," formSection",[120,625,246],{"class":152},[120,627,524],{"class":457},[120,629,630],{"class":441}," createFormSection",[120,632,464],{"class":261},[120,634,532],{"class":141},[120,636,637,640,642,644,646,648],{"class":122,"line":281},[120,638,639],{"class":261},"      tenantId",[120,641,153],{"class":141},[120,643,542],{"class":197},[120,645,476],{"class":141},[120,647,547],{"class":197},[120,649,278],{"class":141},[120,651,652,655,657,660],{"class":122,"line":298},[120,653,654],{"class":261},"      formId",[120,656,153],{"class":141},[120,658,659],{"class":197}," formId",[120,661,278],{"class":141},[120,663,664,667,669],{"class":122,"line":315},[120,665,666],{"class":261},"      data",[120,668,153],{"class":141},[120,670,142],{"class":141},[120,672,673,676,678,680,682,685],{"class":122,"line":325},[120,674,675],{"class":261},"        title",[120,677,153],{"class":141},[120,679,605],{"class":197},[120,681,476],{"class":141},[120,683,684],{"class":197},"title",[120,686,278],{"class":141},[120,688,689,692,694,696,698,701],{"class":122,"line":338},[120,690,691],{"class":261},"        description",[120,693,153],{"class":141},[120,695,605],{"class":197},[120,697,476],{"class":141},[120,699,700],{"class":197},"informationText",[120,702,278],{"class":141},[120,704,705],{"class":122,"line":344},[120,706,707],{"class":141},"      },\n",[120,709,710,713,715],{"class":122,"line":352},[120,711,712],{"class":141},"    }",[120,714,500],{"class":261},[120,716,160],{"class":141},[120,718,719],{"class":122,"line":362},[120,720,227],{"emptyLinePlaceholder":226},[120,722,723],{"class":122,"line":374},[120,724,725],{"class":126},"    \u002F\u002F Create dynamic form fields\n",[120,727,728,731,734,736,739,741,743,745,747,749,751,753,755,757],{"class":122,"line":380},[120,729,730],{"class":457},"    await",[120,732,733],{"class":441}," createFormFields",[120,735,464],{"class":261},[120,737,738],{"class":197},"tenant",[120,740,476],{"class":141},[120,742,547],{"class":197},[120,744,470],{"class":141},[120,746,623],{"class":197},[120,748,476],{"class":141},[120,750,547],{"class":197},[120,752,470],{"class":141},[120,754,605],{"class":197},[120,756,500],{"class":261},[120,758,160],{"class":141},[120,760,761],{"class":122,"line":387},[120,762,763],{"class":141},"  }\n",[120,765,766],{"class":122,"line":393},[120,767,220],{"class":141},[20,769,770],{},"The pipeline handles:",[68,772,773,776,779,782],{},[43,774,775],{},"Authentication and session management",[43,777,778],{},"Hierarchical form creation (collections → sections → fields)",[43,780,781],{},"Dynamic field generation based on question types",[43,783,784],{},"Metadata and mapping preservation",[40,786,787],{"start":145},[43,788,789],{},[73,790,791],{},"Error Handling and Validation",[110,793,795],{"className":112,"code":794,"language":114,"meta":115,"style":115},"const createFormField = async ({\n  tenantId,\n  formSectionId,\n  type,\n  initialTitle,\n}) => {\n  try {\n    const field = await createField(\u002F* ... *\u002F);\n    await updateFormField(tenant.id, field.id, {\n      richDescription: \"\",\n      richTitle: initialTitle,\n      disabled: false,\n      metadata: {\n        validation: {\n          required: false,\n          formats: [\"PDF\", \"DOC\", \"DOCX\" \u002F* ... *\u002F],\n        },\n      },\n    });\n    return field;\n  } catch (error) {\n    console.error(`Failed to create field: ${initialTitle}`);\n    throw error;\n  }\n};\n",[117,796,797,814,821,828,835,842,854,861,884,911,923,935,948,957,966,977,1019,1024,1028,1036,1045,1061,1091,1101,1105],{"__ignoreMap":115},[120,798,799,801,805,807,810,812],{"class":122,"line":123},[120,800,239],{"class":133},[120,802,804],{"class":803},"sfCm-"," createFormField",[120,806,246],{"class":152},[120,808,809],{"class":133}," async",[120,811,600],{"class":197},[120,813,532],{"class":141},[120,815,816,819],{"class":122,"line":130},[120,817,818],{"class":197},"  tenantId",[120,820,278],{"class":141},[120,822,823,826],{"class":122,"line":145},[120,824,825],{"class":197},"  formSectionId",[120,827,278],{"class":141},[120,829,830,833],{"class":122,"line":163},[120,831,832],{"class":197},"  type",[120,834,278],{"class":141},[120,836,837,840],{"class":122,"line":175},[120,838,839],{"class":197},"  initialTitle",[120,841,278],{"class":141},[120,843,844,847,849,852],{"class":122,"line":187},[120,845,846],{"class":141},"}",[120,848,613],{"class":197},[120,850,851],{"class":133},"=>",[120,853,142],{"class":141},[120,855,856,859],{"class":122,"line":203},[120,857,858],{"class":457},"  try",[120,860,142],{"class":141},[120,862,863,865,868,870,872,875,877,880,882],{"class":122,"line":217},[120,864,620],{"class":133},[120,866,867],{"class":242}," field",[120,869,246],{"class":152},[120,871,524],{"class":457},[120,873,874],{"class":441}," createField",[120,876,464],{"class":261},[120,878,879],{"class":126},"\u002F* ... *\u002F",[120,881,500],{"class":261},[120,883,160],{"class":141},[120,885,886,888,891,893,895,897,899,901,903,905,907,909],{"class":122,"line":223},[120,887,730],{"class":457},[120,889,890],{"class":441}," updateFormField",[120,892,464],{"class":261},[120,894,738],{"class":197},[120,896,476],{"class":141},[120,898,547],{"class":197},[120,900,470],{"class":141},[120,902,867],{"class":197},[120,904,476],{"class":141},[120,906,547],{"class":197},[120,908,470],{"class":141},[120,910,142],{"class":141},[120,912,913,916,918,921],{"class":122,"line":230},[120,914,915],{"class":261},"      richDescription",[120,917,153],{"class":141},[120,919,920],{"class":267}," \"\"",[120,922,278],{"class":141},[120,924,925,928,930,933],{"class":122,"line":236},[120,926,927],{"class":261},"      richTitle",[120,929,153],{"class":141},[120,931,932],{"class":197}," initialTitle",[120,934,278],{"class":141},[120,936,937,940,942,946],{"class":122,"line":252},[120,938,939],{"class":261},"      disabled",[120,941,153],{"class":141},[120,943,945],{"class":944},"syTEX"," false",[120,947,278],{"class":141},[120,949,950,953,955],{"class":122,"line":258},[120,951,952],{"class":261},"      metadata",[120,954,153],{"class":141},[120,956,142],{"class":141},[120,958,959,962,964],{"class":122,"line":281},[120,960,961],{"class":261},"        validation",[120,963,153],{"class":141},[120,965,142],{"class":141},[120,967,968,971,973,975],{"class":122,"line":298},[120,969,970],{"class":261},"          required",[120,972,153],{"class":141},[120,974,945],{"class":944},[120,976,278],{"class":141},[120,978,979,982,984,987,989,992,994,996,998,1001,1003,1005,1007,1010,1012,1015,1017],{"class":122,"line":315},[120,980,981],{"class":261},"          formats",[120,983,153],{"class":141},[120,985,986],{"class":261}," [",[120,988,275],{"class":267},[120,990,991],{"class":271},"PDF",[120,993,275],{"class":267},[120,995,470],{"class":141},[120,997,268],{"class":267},[120,999,1000],{"class":271},"DOC",[120,1002,275],{"class":267},[120,1004,470],{"class":141},[120,1006,268],{"class":267},[120,1008,1009],{"class":271},"DOCX",[120,1011,275],{"class":267},[120,1013,1014],{"class":126}," \u002F* ... *\u002F",[120,1016,402],{"class":261},[120,1018,278],{"class":141},[120,1020,1021],{"class":122,"line":325},[120,1022,1023],{"class":141},"        },\n",[120,1025,1026],{"class":122,"line":338},[120,1027,707],{"class":141},[120,1029,1030,1032,1034],{"class":122,"line":344},[120,1031,712],{"class":141},[120,1033,500],{"class":261},[120,1035,160],{"class":141},[120,1037,1038,1041,1043],{"class":122,"line":352},[120,1039,1040],{"class":457},"    return",[120,1042,867],{"class":197},[120,1044,160],{"class":141},[120,1046,1047,1049,1052,1054,1057,1059],{"class":122,"line":362},[120,1048,579],{"class":141},[120,1050,1051],{"class":457}," catch",[120,1053,600],{"class":261},[120,1055,1056],{"class":197},"error",[120,1058,613],{"class":261},[120,1060,532],{"class":141},[120,1062,1063,1066,1068,1070,1072,1075,1078,1081,1084,1087,1089],{"class":122,"line":374},[120,1064,1065],{"class":197},"    console",[120,1067,476],{"class":141},[120,1069,1056],{"class":441},[120,1071,464],{"class":261},[120,1073,1074],{"class":267},"`",[120,1076,1077],{"class":271},"Failed to create field: ",[120,1079,1080],{"class":267},"${",[120,1082,1083],{"class":197},"initialTitle",[120,1085,1086],{"class":267},"}`",[120,1088,500],{"class":261},[120,1090,160],{"class":141},[120,1092,1093,1096,1099],{"class":122,"line":380},[120,1094,1095],{"class":457},"    throw",[120,1097,1098],{"class":197}," error",[120,1100,160],{"class":141},[120,1102,1103],{"class":122,"line":387},[120,1104,763],{"class":141},[120,1106,1107],{"class":122,"line":393},[120,1108,1109],{"class":141},"};\n",[20,1111,1112],{},"Built-in safeguards include:",[68,1114,1115,1118,1121,1124],{},[43,1116,1117],{},"Proper error handling for API calls",[43,1119,1120],{},"Field validation rules",[43,1122,1123],{},"File format restrictions",[43,1125,1126],{},"Rich text support for complex content",[15,1128,1130],{"id":1129},"what-i-learned","What I Learned",[40,1132,1133],{},[43,1134,1135],{},[73,1136,1137],{},"PDF Data Extraction Strategy",[20,1139,1140,1141,1144,1145,1148],{},"The initial approach using PDF parsing libraries like ",[117,1142,1143],{},"pdf-parse"," or ",[117,1146,1147],{},"pdf2json"," proved challenging due to:",[68,1150,1151,1154,1157],{},[43,1152,1153],{},"Inconsistent text extraction",[43,1155,1156],{},"Loss of formatting and structure",[43,1158,1159],{},"Difficulty handling tables and layouts",[20,1161,1162],{},"LLMs provided a more elegant solution by:",[68,1164,1165,1168,1171],{},[43,1166,1167],{},"Understanding document context",[43,1169,1170],{},"Maintaining relationships between elements",[43,1172,1173],{},"Producing clean, structured output",[40,1175,1176],{"start":130},[43,1177,1178],{},[73,1179,1180],{},"GraphQL API Orchestration",[20,1182,1183],{},"Managing multiple dependent API calls required careful orchestration:",[68,1185,1186,1189,1192,1195],{},[43,1187,1188],{},"Sequential processing for proper parent-child relationships",[43,1190,1191],{},"Error handling with appropriate rollbacks",[43,1193,1194],{},"Rate limiting consideration",[43,1196,1197],{},"Progress tracking for long-running operations",[40,1199,1200],{"start":145},[43,1201,1202],{},[73,1203,1204],{},"Business Process Automation",[20,1206,1207],{},"The project highlighted how technical solutions can directly impact business development:",[68,1209,1210,1213,1216,1219],{},[43,1211,1212],{},"Reduced sales cycle by providing immediate value",[43,1214,1215],{},"Demonstrated platform capabilities effectively",[43,1217,1218],{},"Saved significant manual work for the CSM team",[43,1220,1221],{},"Created reusable automation patterns",[15,1223,1225],{"id":1224},"whats-next","What's Next?",[40,1227,1228,1244,1260],{},[43,1229,1230,1233],{},[73,1231,1232],{},"Scalability Improvements",[68,1234,1235,1238,1241],{},[43,1236,1237],{},"Batch processing for multiple PDFs",[43,1239,1240],{},"Parallel processing where possible",[43,1242,1243],{},"Caching for improved performance",[43,1245,1246,1249],{},[73,1247,1248],{},"Enhanced Extraction",[68,1250,1251,1254,1257],{},[43,1252,1253],{},"Support for more complex PDF layouts",[43,1255,1256],{},"Additional compliance template types",[43,1258,1259],{},"Multi-language support",[43,1261,1262,1265],{},[73,1263,1264],{},"Integration Enhancements",[68,1266,1267,1270,1273],{},[43,1268,1269],{},"Automated testing for generated forms",[43,1271,1272],{},"Version control for templates",[43,1274,1275],{},"Change tracking and diff generation",[15,1277,1279],{"id":1278},"key-takeaways","Key Takeaways",[20,1281,1282],{},"I learned the power of combining modern AI tools with traditional automation to solve real business challenges. By thinking creatively about PDF data extraction and leveraging LLMs, I turned what could have been weeks of manual work into an automated process.",[20,1284,1285],{},"The solution saved immediate time and resources + created a repeatable pattern for future partner onboarding. Most importantly, it transformed a traditional sales approach into a value-first demonstration which resonated with our potential partner.",[1287,1288],"hr",{},[20,1290,1291],{},[29,1292,1293],{},"Note: This case study focuses on the technical implementation while respecting confidentiality around specific partner details and compliance requirements.",[1295,1296,1297],"style",{},"html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sucvu, html code.shiki .sucvu{--shiki-light:#E53935;--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .sfCm-, html code.shiki .sfCm-{--shiki-light:#90A4AE;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .syTEX, html code.shiki .syTEX{--shiki-light:#FF5370;--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":115,"searchDepth":130,"depth":130,"links":1299},[1300,1301,1302,1306,1307,1308],{"id":17,"depth":130,"text":18},{"id":34,"depth":130,"text":35},{"id":60,"depth":130,"text":61,"children":1303},[1304,1305],{"id":65,"depth":145,"text":66},{"id":97,"depth":145,"text":98},{"id":1129,"depth":130,"text":1130},{"id":1224,"depth":130,"text":1225},{"id":1278,"depth":130,"text":1279},"2025-01-20","Built an automated pipeline to transform complex PDF compliance forms into digital workflows, leveraging LLMs for structured data extraction and GraphQL for platform integration.","md",null,false,"case-study",{"slug":1316},"pdf-to-platform-automation","\u002Fwork\u002Fpdf-to-platform-automation",{"title":5,"description":1310},"work\u002Fpdf-to-platform-automation",[1321,1322,1323,87,1324],"TypeScript","OpenAI","ETL","Automation","SYRiH8RVDeh3lQyrdBXhGlg40Y-Mx4zEc2Mk9-o-lR8",1780955296664]