<https://docs.linkeddatahub.com/user-guide/change-model/#content>
        a       <https://w3id.org/atomgraph/linkeddatahub#XHTML>;
        <http://www.w3.org/1999/02/22-rdf-syntax-ns#value>
                "<div xmlns=\"http://www.w3.org/1999/xhtml\">\n    <p class=\"ldh-body-lg\">Define classes, attach SPIN constructors that drive create forms, and add constraints that validate instances</p>\n    <div>\n        <p>To manage instances, you first need <a href=\"../../reference/administration/ontologies/#classes\" target=\"_blank\">classes</a> that represent them in your dataspace's <a href=\"../../reference/administration/ontologies/\" target=\"_blank\">model</a>. Not only will they serve as RDF types of the instances, but they will also have <a href=\"../../reference/administration/ontologies/#constructors\" target=\"_blank\">constructors</a> attached that define the default properties and their (data)types for that class.</p>\n        <p>The model is managed in the <a href=\"../../reference/dataspace/#admin\" target=\"_blank\">administration dataspace</a> of a dataspace. Head there by clicking the <span class=\"ac-iconbtn sz-lg in-neutral ap-ghost\"><span aria-hidden=\"true\" class=\"msi outline sm\">settings</span></span> in the <a href=\"../../reference/user-interface/#nav-bar\" target=\"_blank\">navigation bar</a> and then choosing <samp>Administration</samp>.</p>\n        <div class=\"ac-alert va-informative\" role=\"status\">\n            <span class=\"ac-alert-ic\"><span aria-hidden=\"true\" class=\"msi outline\">info</span></span>\n            <div class=\"ac-alert-body\">\n                <p class=\"ac-alert-text\">In order to manage the <a href=\"../../reference/administration/acl/\" target=\"_blank\">access control</a>, or the <a href=\"../../reference/administration/ontologies/\" target=\"_blank\">model</a> of a dataspace,\n                the agent needs to be a member of the <a href=\"../../reference/administration/acl/#groups\" target=\"_blank\">owners group</a>.</p>\n            </div>\n        </div>\n        <p>This guide uses the Northwind Traders model and its <samp>schema:Product</samp> class as the example — the demo app ships\n            exactly this constructor and constraint in its namespace ontology, so the finished result can be compared against\n            <a href=\"https://github.com/AtomGraph/LinkedDataHub-Apps/blob/master/demo/northwind-traders/admin/model/ns.ttl\" target=\"_blank\"><samp>admin/model/ns.ttl</samp></a>.</p>\n    </div>\n    <div>\n        <h2 id=\"create-constructor\">Create a constructor</h2>\n        <p>Use the following SPARQL <code>CONSTRUCT</code> query as a <a href=\"../../reference/administration/ontologies/#constructors\" target=\"_blank\">constructor</a> for the <samp>Product</samp> class. The typed blank nodes tell the form which control to render: a string input for the name and identifier, resource typeaheads for the category and supplier.</p>\n        <pre>PREFIX schema: &lt;https://schema.org/&gt;\nPREFIX xsd:    &lt;http://www.w3.org/2001/XMLSchema#&gt;\n\nCONSTRUCT\n{\n  $this schema:name [ a xsd:string ] ;\n    schema:identifier [ a xsd:string ] ;\n    schema:category [ a schema:ProductGroup ] ;\n    schema:provider [ a schema:Corporation ] .\n}\nWHERE {}</pre>\n        <div class=\"ac-tabs or-horizontal\">\n            <div class=\"ac-tablist sz-md va-line\" role=\"tablist\">\n                <button aria-controls=\"user-interface-pane\" aria-selected=\"true\" class=\"ac-tab is-on\" id=\"user-interface-tab\" role=\"tab\" type=\"button\"><span class=\"ac-tab-lbl\">User interface</span></button>\n                <button aria-controls=\"command-line-interface-pane\" aria-selected=\"false\" class=\"ac-tab\" id=\"command-line-interface-tab\" role=\"tab\" type=\"button\"><span class=\"ac-tab-lbl\">Command line interface</span></button>\n            </div>\n            <div aria-labelledby=\"user-interface-tab\" class=\"ac-tabpanel\" id=\"user-interface-pane\" role=\"tabpanel\">\n                    <div>\n                        <p>In the administration dataspace, follow these steps:</p>\n                        <ol>\n                            <li>Click the <span class=\"ac-btn in-primary ap-solid sz-md\">Create <span aria-hidden=\"true\" class=\"msi caret\">expand_more</span></span> dropdown at the bottom of the page</li>\n                            <li>Click on <samp>CONSTRUCT</samp> in the dropdown list that appears</li>\n                            <li>Switch the <samp>Blank node</samp> dropdown to <samp>URI</samp> and enter <samp>https://localhost:4443/ns#ProductConstructor</samp></li>\n                            <li>Fill out the mandatory fields in the form:\n                                <dl>\n                                    <dt>Label</dt>\n                                    <dd>Enter <samp>Product constructor</samp></dd>\n                                    <dt>IsDefinedBy</dt>\n                                    <dd>Select <samp>Namespace</samp> from the list — the dataspace’s namespace ontology, in which the query is defined</dd>\n                                    <dt>Text</dt>\n                                    <dd>Enter the SPARQL <code>CONSTRUCT</code> query string</dd>\n                                </dl>\n                            </li>\n                            <li>Click <span class=\"ac-btn in-primary ap-solid sz-sm\">Save</span></li>\n                        </ol>\n                    </div>\n                </div>\n            <div aria-labelledby=\"command-line-interface-tab\" class=\"ac-tabpanel\" hidden=\"hidden\" id=\"command-line-interface-pane\" role=\"tabpanel\">\n                    <div>\n                        <p>Save the query in a file, e.g. <samp>queries/construct-product.rq</samp>. With the <a href=\"../../reference/command-line-interface/\">CLI</a> installed and the <samp>LDH_*</samp> variables set:</p>\n                        <pre>base=\"https://localhost:4443/\"\nadmin_base=\"https://admin.localhost:4443/\"\n\nldh admin add constructor \\\n  -b \"$admin_base\" \\\n  --uri \"${base}ns#ProductConstructor\" \\\n  --label \"Product constructor\" \\\n  --query-file queries/construct-product.rq \\\n  \"${admin_base}ontologies/namespace/\"</pre>\n                        <p>The model lives in the administration dataspace, whose origin is the dataspace origin with an <samp>admin.</samp> prefix — so <code>-b</code> (overriding the <samp>LDH_BASE</samp> default) and the target document URL both use <samp>$admin_base</samp>, because admin commands target the admin app's base URI, while the ontology terms being defined keep the end-user origin.</p>\n                    </div>\n                </div>\n        </div>\n        <p>Follow the same steps for <samp>Category</samp> (<samp>schema:ProductGroup</samp>) if you want its instances to be creatable too.</p>\n        <p class=\"ldh-body-lg\"><a href=\"../../reference/administration/ontologies/#constructors\" target=\"_blank\">Read more about constructors.</a></p>\n    </div>\n    <div>\n        <h2 id=\"create-constraint\">Create a constraint</h2>\n        <p>To control data quality, you may want to make some of the instance properties mandatory. For example, a <samp>schema:Product</samp> instance should always have a <code>schema:name</code> value.</p>\n        <div class=\"ac-tabs or-horizontal\">\n            <div class=\"ac-tablist sz-md va-line\" role=\"tablist\">\n                <button aria-controls=\"user-interface-2-pane\" aria-selected=\"true\" class=\"ac-tab is-on\" id=\"user-interface-2-tab\" role=\"tab\" type=\"button\"><span class=\"ac-tab-lbl\">User interface</span></button>\n                <button aria-controls=\"command-line-interface-2-pane\" aria-selected=\"false\" class=\"ac-tab\" id=\"command-line-interface-2-tab\" role=\"tab\" type=\"button\"><span class=\"ac-tab-lbl\">Command line interface</span></button>\n            </div>\n            <div aria-labelledby=\"user-interface-2-tab\" class=\"ac-tabpanel\" id=\"user-interface-2-pane\" role=\"tabpanel\">\n                    <div>\n                        <p>In the administration dataspace, follow these steps:</p>\n                        <ol>\n                            <li>Click the <span class=\"ac-btn in-primary ap-solid sz-md\">Create <span aria-hidden=\"true\" class=\"msi caret\">expand_more</span></span> dropdown at the bottom of the page</li>\n                            <li>Click on <samp>Missing property value</samp> in the dropdown list that appears</li>\n                            <li>Fill out the fields in the form:\n                                <dl>\n                                    <dt>Label</dt>\n                                    <dd>Enter <samp>Missing schema:name</samp></dd>\n                                    <dt>IsDefinedBy</dt>\n                                    <dd>Type <samp>Namespace</samp> into the input (which provides autocomplete)</dd>\n                                    <dd>Select <samp>Namespace</samp> from the list — the dataspace’s namespace ontology, in which the query is defined</dd>\n                                    <dt>Arg1</dt>\n                                    <dd>Enter <samp>https://schema.org/name</samp></dd>\n                                </dl>\n                            </li>\n                            <li>Click <span class=\"ac-btn in-primary ap-solid sz-sm\">Save</span></li>\n                        </ol>\n                    </div>\n                </div>\n            <div aria-labelledby=\"command-line-interface-2-tab\" class=\"ac-tabpanel\" hidden=\"hidden\" id=\"command-line-interface-2-pane\" role=\"tabpanel\">\n                    <div>\n                        <pre>ldh admin add property-constraint \\\n  -b \"$admin_base\" \\\n  --uri \"${base}ns#MissingName\" \\\n  --label \"Missing schema:name\" \\\n  --property \"https://schema.org/name\" \\\n  \"${admin_base}ontologies/namespace/\"</pre>\n                    </div>\n                </div>\n        </div>\n        <p class=\"ldh-body-lg\"><a href=\"../../reference/administration/ontologies/#constraints\" target=\"_blank\">Read more about constraints.</a></p>\n    </div>\n    <div>\n        <h2 id=\"create-classes\">Create classes</h2>\n        <div class=\"ac-tabs or-horizontal\">\n            <div class=\"ac-tablist sz-md va-line\" role=\"tablist\">\n                <button aria-controls=\"user-interface-3-pane\" aria-selected=\"true\" class=\"ac-tab is-on\" id=\"user-interface-3-tab\" role=\"tab\" type=\"button\"><span class=\"ac-tab-lbl\">User interface</span></button>\n                <button aria-controls=\"command-line-interface-3-pane\" aria-selected=\"false\" class=\"ac-tab\" id=\"command-line-interface-3-tab\" role=\"tab\" type=\"button\"><span class=\"ac-tab-lbl\">Command line interface</span></button>\n            </div>\n            <div aria-labelledby=\"user-interface-3-tab\" class=\"ac-tabpanel\" id=\"user-interface-3-pane\" role=\"tabpanel\">\n                    <div>\n                        <p>In the administration dataspace, follow these steps to create the product class:</p>\n                        <ol>\n                            <li>Click the <span class=\"ac-btn in-primary ap-solid sz-md\">Create <span aria-hidden=\"true\" class=\"msi caret\">expand_more</span></span> dropdown at the bottom of the page</li>\n                            <li>Click on <samp>Class</samp> in the dropdown list that appears</li>\n                            <li>Switch the <samp>Blank node</samp> dropdown to <samp>URI</samp> and enter <samp>https://schema.org/Product</samp> — reusing the schema.org term rather than minting your own</li>\n                            <li>Fill out the mandatory fields in the form:\n                                <dl>\n                                    <dt>Label</dt>\n                                    <dd>Enter <samp>Product</samp></dd>\n                                    <dt>IsDefinedBy</dt>\n                                    <dd>Select <samp>Namespace</samp> from the list — the dataspace’s namespace ontology, in which the class is defined</dd>\n                                    <dt>Constructor</dt>\n                                    <dd>Type <samp>Product constructor</samp> into the input (which provides autocomplete)</dd>\n                                    <dd>Select <samp>Product constructor</samp> from the list — this is the query you created beforehand</dd>\n                                </dl>\n                            </li>\n                            <li>Click <span class=\"ac-btn in-primary ap-solid sz-sm\">Save</span></li>\n                        </ol>\n                    </div>\n                </div>\n            <div aria-labelledby=\"command-line-interface-3-tab\" class=\"ac-tabpanel\" hidden=\"hidden\" id=\"command-line-interface-3-pane\" role=\"tabpanel\">\n                    <div>\n                        <pre>ldh admin add class \\\n  -b \"$admin_base\" \\\n  --uri \"https://schema.org/Product\" \\\n  --label \"Product\" \\\n  --constructor \"${base}ns#ProductConstructor\" \\\n  --constraint \"${base}ns#MissingName\" \\\n  \"${admin_base}ontologies/namespace/\"</pre>\n                    </div>\n                </div>\n        </div>\n        <p class=\"ldh-body-lg\"><a href=\"../../reference/administration/ontologies/#classes\" target=\"_blank\">Read more about classes.</a></p>\n    </div>\n    <div>\n        <h2 id=\"result\">What ended up in the model</h2>\n        <p>The three steps added the following description to the namespace ontology document — the same wiring the demo app ships:</p>\n        <pre>schema:Product spin:constructor &lt;https://localhost:4443/ns#ProductConstructor&gt; ;\n    spin:constraint &lt;https://localhost:4443/ns#MissingName&gt; ;\n    rdfs:label \"Product\" .\n\n&lt;https://localhost:4443/ns#ProductConstructor&gt; a ldh:Constructor ;\n    rdfs:label \"Product constructor\" ;\n    sp:text \"CONSTRUCT { $this schema:name [ a xsd:string ] ; … } WHERE {}\" .\n\n&lt;https://localhost:4443/ns#MissingName&gt; a ldh:MissingPropertyValue ;\n    rdfs:label \"Missing schema:name\" ;\n    sp:arg1 schema:name .</pre>\n        <p>From now on, <samp>Product</samp> can be chosen as the <samp>Type</samp> of a new <samp>Instance</samp> created from the <span class=\"ac-btn in-primary ap-solid sz-md\">Create <span aria-hidden=\"true\" class=\"msi caret\">expand_more</span></span> dropdown of the\n            end-user dataspace, and its form is then generated from the constructor, offering title, name, identifier, description, category, supplier and offer controls. A submission without a name is rejected with\n            <samp>422 Unprocessable Entity</samp>, carrying the <a href=\"../../reference/administration/ontologies/#constraints\" target=\"_blank\">constraint violation</a>.</p>\n        <img alt=\"The generated Product create form, with the Missing schema:name violation shown after an empty submit\" src=\"/uploads/0b1eff7cc17e50c53ffc079f65568f71317e1a1f\"></img>\n    </div>\n</div>"^^<http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral> .

<https://docs.linkeddatahub.com/user-guide/change-model/>
        a       <https://w3id.org/atomgraph/linkeddatahub/document-hierarchy#Item>;
        <http://www.w3.org/1999/02/22-rdf-syntax-ns#_1>
                <https://docs.linkeddatahub.com/user-guide/change-model/#content>;
        <http://purl.org/dc/terms/created>
                "2026-09-29T09:52:51.549Z"^^<http://www.w3.org/2001/XMLSchema#dateTime>;
        <http://purl.org/dc/terms/creator>
                <https://admin.linkeddatahub.com/acl/agents/5ba81960-d511-4a3b-8b9a-cb5bb278dd95/#this>;
        <http://purl.org/dc/terms/description>
                "Define classes, attach SPIN constructors that drive create forms, and add constraints that validate instances";
        <http://purl.org/dc/terms/title>
                "Change model";
        <http://rdfs.org/sioc/ns#has_container>
                <https://docs.linkeddatahub.com/user-guide/>;
        <http://www.w3.org/ns/auth/acl#owner>
                <https://admin.linkeddatahub.com/acl/agents/5ba81960-d511-4a3b-8b9a-cb5bb278dd95/#this> .
