Creating new docly files

Pitfall By design
New .docly and .json files must be written atomically — build the complete content in a temp folder on a separate drive and copy it into the Docly drive. Direct writes from external tools produce unregistered file stubs and burn the filename.

What you'll see

An AI coding agent (Claude Code, Cursor, Copilot, etc.) writes a new .docly file directly into the WebDAV-mounted Docly drive. The write appears to succeed, but the document either does not open in Docly, shows up without the .docly suffix in directory listings, or appears on the drive as a 2-byte stub. Re-trying with the same filename fails the same way — the filename is burned with an incorrect schema binding cached.

What's actually happening

When a new .docly file appears at a target path, the Docly drive parses the JSON, looks up the schema reference, and registers the file as a schema-bound document. If the file at registration time is incomplete or does not match a known schema, the drive falls back to registering it as a generic uploaded file with no schema binding. That fallback is then cached for the filename — deleting and re-writing the same path does not clear it. The filename is effectively burned until cleared manually through the Docly UI.

A .docly file is a JSON envelope with a fixed shape: top-level Document, EmbeddedFiles, Schema, Tags, Modified, Created. The Schema block — { "Name": ... } — is what ties the file to a registered schema and triggers the binding; the name must reference a real schema in the workspace. The Document block contains the schema-specific content and varies entirely by schema type.

Direct writes from external tools (text editors, scripts, AI agents) typically trigger this fallback. The drive registers the file based on what it sees during the first observation of the path; if that observation catches an empty stub or a partial write, the fallback locks in.

The same atomicity rule applies to .json files: writes are rejected unless the saved content parses as valid JSON. And Move-Item (or mv) makes the situation worse, not better — the drive pre-creates a 2-byte placeholder at the destination as soon as the move begins, then refuses the move itself with The file exists.

What to do

Build the complete file in a temp folder outside the Docly drive (any local drive — typically $env:TEMP on C:), then Copy-Item (not Move-Item) it into place as a single operation. The drive sees a complete file appear at a .docly path, parses it, looks up the schema, and registers the binding atomically.

# PowerShell
$temp = "$env:TEMP\My new doc.docly"
Set-Content -LiteralPath $temp -Value $jsonContent -Encoding UTF8

Copy-Item -LiteralPath $temp `
          -Destination "L:\Site\folder\My new doc.docly"

Remove-Item -LiteralPath $temp

Minimum file envelope (regardless of schema):

{
  "Document": { /* fields defined by your target schema */ },
  "EmbeddedFiles": [],
  "Schema": { "Name": "<schema-name>" },
  "Tags": [],
  "Modified": "2026-05-15T12:00:00.0000000+02:00",
  "Created": "2026-05-15T12:00:00.0000000+02:00"
}

The drive overwrites Modified and Created with real timestamps on successful registration — placeholders are fine. ROWIDs inside form chapters are standard UUIDs with dashes; Docly generates them on save, but supplying fresh ones in a programmatically-built file is harmless.

Structural traps that misregister or break a file:

  • Missing or wrong Schema block — file registers as a generic upload and the filename is burned.
  • Field names in Document not matching the schema's form fields (case-sensitive).
  • Enum values stored as user-facing labels instead of internal values (e.g. "By design" instead of "ByDesign"). Internal values come from the schema's Options[].Value, not Options[].Label.
  • Form Chapters expected to nest as sub-objects — they flatten. Fields inside a Chapter sit alongside the other Document properties, with one Expand boolean and one ROWID UUID per Chapter added.
  • Radio-group fields missing the FieldName__docly_radiogroup duplicate next to FieldName; both carry the same internal value.
  • Rich-text fields written as markdown — they are HTML strings, so escape " as \" inside the JSON.
  • Hand-rolling the count fields (OKCount, TotalCount, etc.). Docly maintains these on form save; start at "0" or copy from an existing instance.

Verify registration succeeded: the destination file should be a few hundred bytes larger than the source — the drive adds metadata on successful binding. A destination of 2 bytes means registration failed; pick a different filename and retry.

If a filename is already burned: open the workspace in the Docly UI, locate the misregistered file, and remove it from there — not from the mapped drive. The mapped drive cannot clear the cached binding.

If the drive returns The file cannot be accessed by the system for every new write to a specific folder, even with valid content: the folder may have a configuration state that blocks WebDAV-creation of new documents (suspected Docly drive issue). The filename is not burned in this case — the file never reaches the registration step. Fall back to creating the document through the Docly UI, then editing the content via WebDAV with normal in-place edits.

For the full reference, see Editing Docly documents programmatically.