<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Maciej Śnieżyński</title>
    <description>The latest articles on DEV Community by Maciej Śnieżyński (@maciej_nieyski_1a71389).</description>
    <link>https://dev.to/maciej_nieyski_1a71389</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4111380%2F82338cd5-23af-49fb-adab-0a7df0315fad.png</url>
      <title>DEV Community: Maciej Śnieżyński</title>
      <link>https://dev.to/maciej_nieyski_1a71389</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maciej_nieyski_1a71389"/>
    <language>en</language>
    <item>
      <title>Fill Existing PDF Forms from n8n Without Rebuilding the Template</title>
      <dc:creator>Maciej Śnieżyński</dc:creator>
      <pubDate>Sat, 05 Sep 2026 16:57:20 +0000</pubDate>
      <link>https://dev.to/maciej_nieyski_1a71389/fill-existing-pdf-forms-from-n8n-without-rebuilding-the-template-4khb</link>
      <guid>https://dev.to/maciej_nieyski_1a71389/fill-existing-pdf-forms-from-n8n-without-rebuilding-the-template-4khb</guid>
      <description>&lt;p&gt;An earlier version of this n8n workflow had a bad fallback: when it couldn't find an exact PDF field name, it tried a partial match. For example, an input called &lt;code&gt;total&lt;/code&gt; could match a field called &lt;code&gt;subtotal&lt;/code&gt; if there was no exact match.&lt;/p&gt;

&lt;p&gt;The PDF would still be generated. The number would just be in the wrong box.&lt;/p&gt;

&lt;p&gt;That fallback is gone in the current version. Below is the corrected workflow, a three-field PDF you can test it with, and what the latest test actually covered. I build JustFill, the PDF service used here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where the mapping went wrong
&lt;/h3&gt;

&lt;p&gt;The old mapping node used &lt;code&gt;find()&lt;/code&gt; with a substring fallback. It also stripped everything outside &lt;code&gt;a-z&lt;/code&gt; and &lt;code&gt;0-9&lt;/code&gt; when comparing names, which lost non-ASCII letters.&lt;/p&gt;

&lt;p&gt;The replacement keeps Unicode letters and requires an exact match after normalization. This is the matching part of the Code node, not the complete node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;norm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;NFC&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[^\p&lt;/span&gt;&lt;span class="sr"&gt;{L}&lt;/span&gt;&lt;span class="se"&gt;\p&lt;/span&gt;&lt;span class="sr"&gt;{M}&lt;/span&gt;&lt;span class="se"&gt;\p&lt;/span&gt;&lt;span class="sr"&gt;{N}&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;+/gu&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;norm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;matches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;norm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;nk&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So &lt;code&gt;Company Name&lt;/code&gt; and &lt;code&gt;company_name&lt;/code&gt; match; &lt;code&gt;total&lt;/code&gt; and &lt;code&gt;subtotal&lt;/code&gt; don't. If normalization gives two PDF fields the same name, the workflow rejects the ambiguity rather than choosing the first one.&lt;/p&gt;

&lt;p&gt;The rest of the node rejects unknown input keys, two keys targeting one field, arrays, and nested objects. &lt;code&gt;null&lt;/code&gt; writes a blank value. A PDF field left out of the input is optional; this code doesn't decide which fields your business process requires.&lt;/p&gt;

&lt;p&gt;This still depends on the template being right. A correctly named field in the wrong place will produce a correctly matched value in the wrong place. Review the boxes once for each PDF version and save that layout before using it for recurring documents.&lt;/p&gt;

&lt;h3&gt;
  
  
  Try it with a supplier-intake PDF
&lt;/h3&gt;

&lt;p&gt;Download the current &lt;a href="https://github.com/mrmaciej1/justfill-mcp/blob/main/examples/n8n/fill-pdf-workflow.json" rel="noopener noreferrer"&gt;workflow JSON from GitHub&lt;/a&gt; and use &lt;strong&gt;Workflows → Import from File&lt;/strong&gt; in n8n. The catalog update was submitted for review on September 5, 2026. While the n8n listing is temporarily unavailable, use the repository file for this example.&lt;/p&gt;

&lt;p&gt;The workflow fills the PDF you upload. It doesn't rebuild the document from HTML. It uses HTTP Request and Code nodes, so you don't need to install a community node or configure an LLM key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Form Trigger (PDF + JSON)
  → request a one-time upload URL
  → POST the PDF binary
  → open_pdf
  → map field names
  → fill_pdf
  → redirect to the download URL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a JustFill key under &lt;strong&gt;Account → API keys&lt;/strong&gt; and put it in the Config node for the test. That node stores the key in the workflow definition: don't share an export with the key inside it. For production, move it to an n8n credential or environment variable. The requests go to &lt;code&gt;https://justfill.app/api/mcp&lt;/code&gt; as JSON-RPC over HTTP; the imported nodes already build the request bodies.&lt;/p&gt;

&lt;p&gt;Open the form trigger's test URL, upload the &lt;a href="https://github.com/mrmaciej1/justfill-mcp/blob/main/examples/n8n/reviewer-sample-supplier-intake.pdf" rel="noopener noreferrer"&gt;sample supplier-intake PDF&lt;/a&gt;, and paste:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"company_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Northwind LLC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"vendor_reference"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"V-1042"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"remittance_email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ap@northwind.example"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This sample has three named AcroForm fields, so it doesn't need a separate template-preparation step. All values are synthetic. In the output, check the company, reference, and email boxes individually, then try adding &lt;code&gt;unknown_field&lt;/code&gt; to the JSON. That second run should stop before filling.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foyztldkcabvy88cv1j8r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foyztldkcabvy88cv1j8r.png" alt="Supplier-intake PDF with the company, reference, and email filled in" width="800" height="1035"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Historical watermarked example showing the three field positions, not the clean output from the September 5 test.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What has actually been tested
&lt;/h3&gt;

&lt;p&gt;The September 5, 2026 check ran the workflow's actual mapping code against production MCP upload, open, and fill responses. All three values appeared in the expected boxes in a clean PDF, which was also checked visually. An extra unknown key was rejected before filling. The temporary workspace and credential were removed afterward.&lt;/p&gt;

&lt;p&gt;That was an HTTP-plus-Code-node test, &lt;strong&gt;not a new run inside the n8n engine&lt;/strong&gt;. The cover image is from the earlier full workflow run on n8n 2.28.6, on July 20; it is not evidence of the September strict-mapping update.&lt;/p&gt;

&lt;p&gt;You can run the mapping regression tests without n8n or an API key. From a checkout of the public &lt;code&gt;justfill-mcp&lt;/code&gt; repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;--test&lt;/span&gt; examples/n8n/test-deterministic-mapping.mjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The three-field test doesn't establish that a dense, multipage form will be laid out correctly. Test your actual PDF with synthetic values, including long text and any checkboxes, before connecting customer data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Connecting your own data
&lt;/h3&gt;

&lt;p&gt;For a recurring supplier form, replace the Form Trigger with your procurement webhook and construct just the three fields the PDF needs. Don't feed the mapper a whole supplier record: extra keys will now fail the run deliberately.&lt;/p&gt;

&lt;p&gt;Replace the final redirect with your delivery step. Check &lt;code&gt;output_mode&lt;/code&gt; before sending anything: it can be &lt;code&gt;clean&lt;/code&gt; or &lt;code&gt;watermarked&lt;/code&gt;. The download link is temporary, so if you need an archive, fetch the PDF and store it in your own destination.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://justfill.app/integrations/n8n-fill-pdf-forms?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=b2b_pdf_automation_2026q3&amp;amp;utm_content=n8n_existing_pdf_article" rel="noopener noreferrer"&gt;n8n setup guide&lt;/a&gt; collects the import files and template instructions. If your data is already a spreadsheet and you don't need n8n around it, the &lt;a href="https://justfill.app/solutions/fill-pdf-from-excel?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=b2b_pdf_automation_2026q3&amp;amp;utm_content=n8n_article_excel_batch" rel="noopener noreferrer"&gt;five-row Excel/CSV browser sample&lt;/a&gt; is a shorter way to check whether your PDF works.&lt;/p&gt;

&lt;p&gt;Disclosure: I am the solo developer of JustFill.&lt;/p&gt;

&lt;p&gt;AI disclosure: AI coding agents drafted and revised this article and ran the code checks described above.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>pdf</category>
      <category>mcp</category>
      <category>n8n</category>
    </item>
  </channel>
</rss>
