# Quickstart

Create your first form in minutes

Canonical URL: https://docs.paradoc.dev/quickstart/

Let's build a simple purchase agreement to grasp the basics of Paradoc. We'll define the agreement, populate it with data, validate it, and render the output.

## Install the Packages

Let's make a new project and install the SDK and filesystem resolver. The SDK includes the default renderer.

**npm**

```bash
mkdir quickstart && cd quickstart
npm init -y
npm install @paradoc/sdk @paradoc/resolvers
```

**pnpm**

```bash
mkdir quickstart && cd quickstart
pnpm init
pnpm add @paradoc/sdk @paradoc/resolvers
```

**yarn**

```bash
mkdir quickstart && cd quickstart
yarn init -y
yarn add @paradoc/sdk @paradoc/resolvers
```

**bun**

```bash
mkdir quickstart && cd quickstart
bun init -y
bun add @paradoc/sdk @paradoc/resolvers
```

The examples use ES modules and top-level `await`. Set `"type": "module"` in `package.json`, put the code from each step in one `index.ts` file, and run it with `npx tsx index.ts`.

## Define the Form

Let's define a simple purchase agreement with 2 parties and 3 fields. It will have a single layer that is a Markdown file.

The `markdown` layer is file-backed, so its bytes come from a resolver. Bind
one when you build the form — every instance you derive from it later
(`fill`, `render`, and so on) carries it.

```ts
import { p } from '@paradoc/sdk'
import { createFsResolver } from '@paradoc/resolvers/fs'

const resolver = createFsResolver({ root: process.cwd() })

const purchaseAgreement = p
  .form()
  .name('purchase-agreement') // required
  .title('Purchase Agreement')
  .version('1.0.0')
  .parties({
    buyer: p.party().label('Buyer').partyType('person').signature({ required: true }),
    seller: p.party().label('Seller').partyType('person').signature({ required: true }),
  })
  .fields({
    quantity: p.field.number().label('Quantity').required(),
    price: p.field.money().label('Price').required(),
    date: p.field.date().label('Date').required(),
  })
  .layers({
    markdown: p.layer().file().mimeType('text/markdown').path('purchase-agreement.md'),
  })
  .defaultLayer('markdown')
  .build({ resolver })
```

In this Quickstart, we're using the fluent builder pattern to define the form. You can also use the object pattern if you prefer.

## Create the Layer

Next, let's create the layer. Paradoc's deterministic template syntax maps the
form parties and fields into the layer.

```md title="purchase-agreement.md"
# Purchase Agreement

{{parties.buyer.name}} agrees to purchase {{fields.quantity}} units at {{fields.price}} each.
{{parties.seller.name}} agrees to deliver by {{fields.date}}.
```

Paradoc is agnostic to the rendering engine and file format you choose. You can use any rendering engine and file format you want.

## Populate

Let's populate the form with data by using the `.fill()` method.

```ts
const draft = purchaseAgreement.fill({
  fields: {
    quantity: 100,
    price: { amount: 25, currency: 'USD' },
    date: '2025-03-01',
  },
  parties: {
    buyer: { name: 'Alice Johnson' },
    seller: { name: 'Bob Smith' },
  },
})
```

## Validate

Next, let's check that the data is valid by using the `.isValid()` method.

```ts
if (draft.isValid()) {
  console.log('Purchase agreement is valid')
} else {
  console.log('Errors:', draft.validate().errors)
}
```

## Render

Let's render the purchase agreement with the data using the `.render()` method. The resolver we bound when building the form travels with `draft`, so we don't pass it again.

```ts
const output = await draft.render({ layer: 'markdown' })

console.log(output)
// # Purchase Agreement
//
// Alice Johnson agrees to purchase 100 units at $25.00 each.
// Bob Smith agrees to deliver by Mar 1, 2025.
```

## Save Artifact

If we want to save our form for future use, we can either save it as a typescript file, or we can serialize it to JSON/YAML for future loading.

**JSON**

```ts
import { writeFileSync } from 'node:fs'

writeFileSync('purchase-agreement.json', JSON.stringify(purchaseAgreement.toJSON(), null, 2))
```

**YAML**

```ts
import { writeFileSync } from 'node:fs'

writeFileSync('purchase-agreement.yaml', purchaseAgreement.toYAML())
```

**JSON**

```json
{
  "$schema": "https://schema.paradoc.dev/2026-10-02.json",
  "name": "purchase-agreement",
  "version": "1.0.0",
  "title": "Purchase Agreement",
  "metadata": {},
  "kind": "form",
  "fields": {
    "quantity": {
      "label": "Quantity",
      "required": true,
      "type": "number"
    },
    "price": {
      "label": "Price",
      "required": true,
      "type": "money"
    },
    "date": {
      "label": "Date",
      "required": true,
      "type": "date"
    }
  },
  "layers": {
    "markdown": {
      "mimeType": "text/markdown",
      "kind": "file",
      "path": "purchase-agreement.md"
    }
  },
  "defaultLayer": "markdown",
  "parties": {
    "buyer": {
      "label": "Buyer",
      "partyType": "person",
      "signature": {
        "required": true
      }
    },
    "seller": {
      "label": "Seller",
      "partyType": "person",
      "signature": {
        "required": true
      }
    }
  }
}
```

**YAML**

```yaml
# yaml-language-server: $schema=https://schema.paradoc.dev/2026-10-02.json
$schema: https://schema.paradoc.dev/2026-10-02.json
name: purchase-agreement
version: 1.0.0
title: Purchase Agreement
metadata: {}
kind: form
fields:
  quantity:
    label: Quantity
    required: true
    type: number
  price:
    label: Price
    required: true
    type: money
  date:
    label: Date
    required: true
    type: date
layers:
  markdown:
    mimeType: text/markdown
    kind: file
    path: purchase-agreement.md
defaultLayer: markdown
parties:
  buyer:
    label: Buyer
    partyType: person
    signature:
      required: true
  seller:
    label: Seller
    partyType: person
    signature:
      required: true
```

That's it! You've created a basic form that shows how Paradoc works at design time (defining the schema) and runtime (filling and rendering). As a next step, explore the concepts section or jump into the guides to learn more.

## Next Steps

* [Concepts](/concepts) — learn about the core concepts
* [Guides](/guides) — step-by-step tutorials
