= Forms
This NIP provides a way to implement forms on Nostr using parametrized replaceable events. They can be used for surveys, voting, product/service purchases, job applications, grants, or other formal applications.
== Form Definition
Event kind 30168 describes a form as a parametrized replaceable event, with field tags that contain the description of each form field.
{
"kind": 30168,
"content": "",
"tags": [
["d", "<form identifier>"],
["name", "Name of the form"],
["description", "Detailed description of what this form is for"],
["c", "application"],
["t", "job"],
["t", "developer"],
["t", "remote"],
["settings", JSON.stringify({
"description": "Additional form settings and metadata"
})],
["field", "age", "text", "What is your age?", "", JSON.stringify({
"required": true,
"type": "number"
})],
["field", "experience", "option", "Years of experience",
JSON.stringify([
["junior", "0-2 years"],
["mid", "2-5 years"],
["senior", "5+ years"]
]),
JSON.stringify({
"required": true
})
]
],
"pubkey": "<Author of the form>"
}
The form event uses the following tags:
-
d: Unique identifier for the form, used to make the event replaceable -
name: Display name of the form (for backward compatibility) -
description: Detailed explanation of the form’s purpose and context -
c: Category of the form (poll, purchase, or application) -
t: Topic tags for categorizing and searching forms -
settings: JSON object containing form-wide settings and metadata -
field: One or more field definitions (see Field Tag Structure below)
== Form Response
Event kind 1069 is used to submit responses to a form. The response references the original form using an a tag and contains the submitted data in response tags.
{
"kind": 1069,
"content": "",
"tags": [
["a", "30168:form-author:form-identifier", "wss://relay.example.com"],
["p", "form-author-pubkey", "wss://relay.example.com"],
["response", "age", "28", "{}"],
["response", "experience", "mid", "{}"],
["response", "motivation", "I have been following the project for a while and would love to contribute to its development. I have experience with similar technologies and am excited about the opportunity to work with the team.", "{}"],
["response", "skills", "javascript;typescript;react", "{}"],
["response", "availability", "full-time", "{}"],
["response", "timezone", "UTC+1", "{}"],
["response", "portfolio", "https://github.com/username", "{}"],
["response", "references", "{\"name\":\"John Smith\",\"role\":\"Previous Team Lead\",\"contact\":\"john@example.com\"}", "{}"]
],
"pubkey": "Author of Response"
}
For multiple-choice fields, the response values are delimited by semicolons. For complex objects like references, the value is stringified JSON.
== Field Tag Structure
A field tag is described as: ["field", FieldId, InputType, Label, Options, Field Settings]
-
FieldId: Alphanumeric identifier for the field -
InputType: One of “text”, “option”, “label” -
Label: Description or question for the field -
Options: Stringified array of options for option-type fields -
Field Settings: Stringified JSON with field metadata (required, prerequisites, etc.)
== Options Structure
For option-type fields, the options array is stringified and contains option tags in the format:
[OptionId, Label, OptionalConfig]
== Categories
The c tag specifies the form category. For example:
-
poll: For surveys and voting -
purchase: For product/service purchases with additional fields -
application: For job applications, grants, or other formal applications
== Client Behavior
- Clients SHOULD validate form submissions against the field definitions
- Clients SHOULD respect field settings like “required” and “prerequisites”
- Clients MAY implement additional input types by extending the text type
Comments
Public conversation about this article.
No comments yet.
Article metadata
About this entry
Event Id
Raw event
Other authors
No one else has published this topic yet.
