Zum Inhalt springen

HandlebarsPDF

Gegenseitiges NDA mit nummerierten Klauseln

Eine zweiseitige Vereinbarung mit laufender Kopfzeile, einer Fußzeile für Paraphen und Seitenzahlen und Klauseln, die CSS-Zähler nummerieren; die optionale Abwerbeklausel nummeriert also alles danach neu. Die Laufzeit schreibt numToWords aus: „two (2) years“.

Kostenloser Plan, keine Kreditkarte. Sie erhalten eine eigene Kopie im Editor, veröffentlicht und bereit für die API.

Gerendertes Ergebnis

PDF · 2 Seiten · 147 KB ↓ herunterladen

Was dieses Beispiel zeigt

  • Die Klauselnummern sind CSS-Zähler (counter-increment: clause), kein Text in der Vorlage: Entfällt die optionale Klausel, nummeriert sich alles danach neu.
  • {{#if agreement.non_solicitation_months}} nimmt die Abwerbeklausel nur auf, wenn die Daten ihr eine Dauer geben.
  • numToWords agreement.term_years "en" schreibt die Laufzeit, wie Verträge es tun, „two (2) years“, und dateAdd ergibt das Enddatum, den 1. Oktober 2028.
  • Die Kopfzeile nennt auf jeder Seite beide Parteien, die Fußzeile hat Linien für Paraphen neben „Page 1 of 2“; beides sind Chromium-Templates im Rand, wo der Text nie hinläuft.
  • Der Unterschriftsblock hat break-inside: avoid, eine Unterschriftslinie landet also nie ohne ihren Namen auf einer Seite. Das Beispiel zeigt die Mechanik; lassen Sie den Wortlaut vor dem Einsatz juristisch prüfen.

Verwendete Helfer

Mehr zu diesem Anwendungsfall: Verträge und Vereinbarungen als PDF →

Vorlagenordner

templates/mutual-nda/template.htmlHandlebars
<h1>Mutual Non-Disclosure Agreement</h1>
<p>This agreement is dated {{date agreement.date "d MMMM yyyy"}} and made between:</p>
<ol class="parties">
  <li><strong>{{party_a.name}}</strong>, a company registered in {{party_a.jurisdiction}} under number {{party_a.number}}, whose registered office is at {{party_a.address}}; and</li>
  <li><strong>{{party_b.name}}</strong>, a company registered in {{party_b.jurisdiction}} under number {{party_b.number}}, whose registered office is at {{party_b.address}},</li>
</ol>
<p>each a “Party” and together the “Parties”. The Parties intend to discuss {{agreement.purpose}} (the “Purpose”) and will share confidential information for the Purpose only.</p>

<ol class="clauses">
  <li>
    <h2>Confidential Information</h2>
    <p>“Confidential Information” means any information that one Party (the “Discloser”) discloses to the other (the “Recipient”) in connection with the Purpose, in any form, including {{join agreement.includes ", "}}, and any other information that a reasonable person would understand to be confidential.</p>
  </li>
  <li>
    <h2>Obligations</h2>
    <p>The Recipient shall use the Confidential Information only for the Purpose; keep it confidential and protect it with at least the care it applies to its own confidential information, and no less than reasonable care; and disclose it only to those of its employees, officers and professional advisers who need to know it for the Purpose and are bound by duties of confidentiality no less strict than these.</p>
  </li>
  <li>
    <h2>Exceptions</h2>
    <p>The obligations above do not apply to information that is or becomes public other than through a breach of this agreement, that the Recipient held without restriction before it was disclosed, that the Recipient receives lawfully from a third party without restriction, or that the Recipient develops independently. The Recipient may disclose Confidential Information where the law or a court requires it, giving the Discloser prompt notice where it is allowed to.</p>
  </li>
  <li>
    <h2>Term</h2>
    <p>This agreement starts on {{date agreement.effective "d MMMM yyyy"}} and lasts {{numToWords agreement.term_years "en"}} ({{agreement.term_years}}) years, until {{date (dateAdd agreement.effective agreement.term_years "years") "d MMMM yyyy"}}. The duty to keep information confidential continues for {{numToWords agreement.survival_years "en"}} ({{agreement.survival_years}}) years after it ends.</p>
  </li>
  <li>
    <h2>Return and destruction</h2>
    <p>On the Discloser’s written request, the Recipient shall promptly return or destroy the Confidential Information it holds, except copies it must keep by law or that sit in routine back-up systems, which remain subject to this agreement.</p>
  </li>
  {{#if agreement.non_solicitation_months}}
  <li>
    <h2>Non-solicitation</h2>
    <p>During the term and for {{numToWords agreement.non_solicitation_months "en"}} ({{agreement.non_solicitation_months}}) months after it, neither Party shall solicit for employment an employee of the other Party with whom it dealt in connection with the Purpose. General advertisements not aimed at such employees do not break this clause.</p>
  </li>
  {{/if}}
  <li>
    <h2>No licence, no obligation</h2>
    <p>Confidential Information remains the property of the Discloser. Nothing in this agreement grants a licence to it or obliges either Party to enter into any further agreement.</p>
  </li>
  <li>
    <h2>Governing law</h2>
    <p>This agreement and any dispute arising from it are governed by the law of {{agreement.governing_law}}, and the courts of {{agreement.governing_law}} have exclusive jurisdiction.</p>
  </li>
</ol>

<section class="signatures">
  {{#each signatories}}
  <div>
    <p>Signed for and on behalf of<br><strong>{{party}}</strong></p>
    <span class="line"></span>
    <p>{{name}}, {{title}}</p>
    <span class="line"></span>
    <p>Date</p>
  </div>
  {{/each}}
</section>
templates/mutual-nda/style.cssCSS
body { font-family: 'Source Serif 4', serif; font-size: 10.5pt; line-height: 1.5; color: #1e293b; }
h1 { margin: 0 0 6mm; font-size: 19pt; font-weight: 600; }
p { margin: 0 0 3mm; }
ol.parties { margin: 0 0 3mm; padding-left: 7mm; }
ol.parties li { margin-bottom: 1.5mm; }
ol.clauses { margin: 6mm 0 0; padding: 0; list-style: none; counter-reset: clause; }
ol.clauses > li { counter-increment: clause; margin-bottom: 4mm; }
ol.clauses h2 { margin: 0 0 1mm; font-size: 10.5pt; font-weight: 600; break-after: avoid; }
ol.clauses h2::before { content: counter(clause) ". "; }
.signatures { display: flex; gap: 14mm; margin-top: 12mm; break-inside: avoid; }
.signatures div { flex: 1; }
.signatures p { margin: 0; font-size: 9.5pt; }
.signatures .line { display: block; height: 12mm; border-bottom: 1px solid #1e293b; margin-bottom: 1.5mm; }
templates/mutual-nda/head.htmlHTML
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Source+Serif+4:opsz,wght@8..60,400;8..60,600&display=swap">
templates/mutual-nda/footer.htmlHandlebars
<div style="width:100%;display:flex;justify-content:space-between;font-size:7.5px;color:#64748b">
  <span>Initials ________ ________</span>
  <span>Page <span class="pageNumber"></span> of <span class="totalPages"></span></span>
</div>
templates/mutual-nda/settings.jsonJSON
{
  "pdf": {
    "metadata": {
      "title": "Mutual Non-Disclosure Agreement"
    }
  },
  "paper": {
    "format": "A4"
  },
  "margin": {
    "top": "26mm",
    "right": "22mm",
    "bottom": "26mm",
    "left": "22mm"
  },
  "header": {
    "height": "14mm",
    "padding": "0 22mm",
    "html": "<div style=\"width:100%;display:flex;justify-content:space-between;font-size:7.5px;color:#64748b\">\n  <span>Mutual non-disclosure agreement</span>\n  <span>{{party_a.name}} · {{party_b.name}}</span>\n</div>"
  },
  "locale": "en-GB",
  "timezone": "Europe/London",
  "footer": {
    "height": "14mm"
  }
}
templates/mutual-nda/data/default.jsonJSON
{
  "agreement": {
    "date": "2026-09-28",
    "effective": "2026-10-01",
    "purpose": "a joint catalogue of lighting products for the 2027 season",
    "includes": [
      "product designs and drawings",
      "prices and margins",
      "customer and supplier lists",
      "business plans"
    ],
    "term_years": 2,
    "survival_years": 3,
    "non_solicitation_months": 12,
    "governing_law": "England and Wales"
  },
  "party_a": {
    "name": "Fennlor Studio Ltd",
    "jurisdiction": "England and Wales",
    "number": "00000000",
    "address": "1 Example Street, Exampletown"
  },
  "party_b": {
    "name": "Olvarest Ltd",
    "jurisdiction": "England and Wales",
    "number": "00000000",
    "address": "2 Example Road, Exampleville"
  },
  "signatories": [
    {
      "party": "Fennlor Studio Ltd",
      "name": "Jane Doe",
      "title": "Director"
    },
    {
      "party": "Olvarest Ltd",
      "name": "John Doe",
      "title": "Managing Director"
    }
  ]
}

Über die API rendern

Speichern Sie die Beispieldaten als data.json und senden Sie sie mit dem Namen der Vorlage. TypeScript und Python nutzen die SDKs; jede andere Sprache schickt dasselbe JSON mit ihrer Standardbibliothek an die REST-API. Renderings mit einem Schlüssel, der mit ff_test_ beginnt, werden nicht gezählt; im Free-Tarif tragen sie ein kleines Wasserzeichen.

render.shShell
jq '{template: "mutual-nda", data: ., filename: "mutual-nda-2026-09-28.pdf"}' data.json \
  | curl https://api-eu.formfeed.dev/v1/renders \
      -H "Authorization: Bearer ff_test_..." \
      -H "Content-Type: application/json" \
      --data-binary @-
render.tsTypeScript
import { Formfeed } from '@formfeed/sdk';
import data from './data.json' with { type: 'json' };

const formfeed = new Formfeed({ apiKey: process.env.FORMFEED_API_KEY! });

const render = await formfeed.renders.create({
  template: 'mutual-nda',
  data,
  filename: 'mutual-nda-2026-09-28.pdf',
});
console.log(render.status, render.download_url);
render.pyPython
import json
import os

from formfeed import Formfeed

formfeed = Formfeed(api_key=os.environ["FORMFEED_API_KEY"])

with open("data.json", encoding="utf-8") as file:
    data = json.load(file)

render = formfeed.renders.create(
    template="mutual-nda",
    data=data,
    filename="mutual-nda-2026-09-28.pdf",
)
print(render.status, render.download_url)
render.phpPHP
<?php
$body = [
    'template' => 'mutual-nda',
    'data' => json_decode(file_get_contents('data.json'), true),
    'filename' => 'mutual-nda-2026-09-28.pdf',
];

$curl = curl_init('https://api-eu.formfeed.dev/v1/renders');
curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('FORMFEED_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($body),
]);
$render = json_decode(curl_exec($curl), true);

echo $render['status'], ' ', $render['download_url'], PHP_EOL;
main.goGo
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
)

func main() {
	data, err := os.ReadFile("data.json")
	if err != nil {
		panic(err)
	}
	body, _ := json.Marshal(map[string]any{
		"template": "mutual-nda",
		"data":     json.RawMessage(data),
		"filename": "mutual-nda-2026-09-28.pdf",
	})

	request, _ := http.NewRequest("POST", "https://api-eu.formfeed.dev/v1/renders", bytes.NewReader(body))
	request.Header.Set("Authorization", "Bearer "+os.Getenv("FORMFEED_API_KEY"))
	request.Header.Set("Content-Type", "application/json")

	response, err := http.DefaultClient.Do(request)
	if err != nil {
		panic(err)
	}
	defer response.Body.Close()

	var render struct {
		Status      string `json:"status"`
		DownloadURL string `json:"download_url"`
	}
	json.NewDecoder(response.Body).Decode(&render)
	fmt.Println(render.Status, render.DownloadURL)
}
Program.csC#
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json;

var body = new
{
    template = "mutual-nda",
    data = JsonDocument.Parse(File.ReadAllText("data.json")).RootElement,
    filename = "mutual-nda-2026-09-28.pdf",
};

using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("FORMFEED_API_KEY"));

var response = await http.PostAsJsonAsync("https://api-eu.formfeed.dev/v1/renders", body);
var render = await response.Content.ReadFromJsonAsync<JsonElement>();

Console.WriteLine($"{render.GetProperty("status")} {render.GetProperty("download_url")}");
Render.javaJava
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Path;

public class Render {
  public static void main(String[] args) throws Exception {
    String data = Files.readString(Path.of("data.json"));
    String body = """
        {
          "template": "mutual-nda",
          "filename": "mutual-nda-2026-09-28.pdf",
          "data": %s
        }
        """.formatted(data);

    HttpRequest request = HttpRequest.newBuilder(URI.create("https://api-eu.formfeed.dev/v1/renders"))
        .header("Authorization", "Bearer " + System.getenv("FORMFEED_API_KEY"))
        .header("Content-Type", "application/json")
        .POST(HttpRequest.BodyPublishers.ofString(body))
        .build();

    HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
    System.out.println(response.body()); // status, download_url, page_count, units …
  }
}
render.rbRuby
require "json"
require "net/http"

body = {
  template: "mutual-nda",
  data: JSON.parse(File.read("data.json")),
  filename: "mutual-nda-2026-09-28.pdf",
}

response = Net::HTTP.post(
  URI("https://api-eu.formfeed.dev/v1/renders"),
  JSON.generate(body),
  "Authorization" => "Bearer #{ENV.fetch("FORMFEED_API_KEY")}",
  "Content-Type" => "application/json"
)
render = JSON.parse(response.body)

puts render["status"], render["download_url"]

Heute mit dem Rendern beginnen

Der kostenlose Plan enthält 100 Einheiten im Monat und kostenlose Testrenderings. Wechseln Sie den Plan, wenn Sie mehr brauchen.