ER diagram

Read this page in the documentation

ER diagram Every model in one picture, with the foreign keys drawn between them. The one to reach for when explaining a schema to someone. The code What it produces Generated by running the snippet above — this is the generator's real output, rebuilt by scripts/build-diagram-examples.mjs, not a picture of it. <div class="diagram-example"> <!-- Generated by ts-prorm-orm ERDiagram --> <svg xmlns="http://www.w3.org/2000/svg" width="1364" height="358" viewBox="0 0 1364 358"><rect width="1364" height="358" fill="#ffffff"/><g opacity="0.5"><line x1="0" y1="60" x2="0" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="40" y1="60" x2="40" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="80" y1="60" x2="80" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="120" y1="60" x2="120" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="160" y1="60" x2="160" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="200" y1="60" x2="200" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="240" y1="60" x2="240" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="280" y1="60" x2="280" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="320" y1="60" x2="320" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="360" y1="60" x2="360" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="400" y1="60" x2="400" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="440" y1="60" x2="440" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="480" y1="60" x2="480" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="520" y1="60" x2="520" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="560" y1="60" x2="560" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="600" y1="60" x2="600" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="640" y1="60" x2="640" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="680" y1="60" x2="680" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="720" y1="60" x2="720" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="760" y1="60" x2="760" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="800" y1="60" x2="800" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="840" y1="60" x2="840" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="880" y1="60" x2="880" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="920" y1="60" x2="920" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="960" y1="60" x2="960" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="1000" y1="60" x2="1000" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="1040" y1="60" x2="1040" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="1080" y1="60" x2="1080" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="1120" y1="60" x2="1120" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="1160" y1="60" x2="1160" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="1200" y1="60" x2="1200" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="1240" y1="60" x2="1240" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="1280" y1="60" x2="1280" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="1320" y1="60" x2="1320" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="1360" y1="60" x2="1360" y2="358" stroke="#f0f0f0" stroke-width="1"/><line x1="0" y1="60" x2="1364" y2="60" stroke="#f0f0f0" stroke-width="1"/><line x1="0" y1="100" x2="1364" y2="100" stroke="#f0f0f0" stroke-width="1"/><line x1="0" y1="140" x2="1364" y2="140" stroke="#f0f0f0" stroke-width="1"/><line x1="0" y1="180" x2="1364" y2="180" stroke="#f0f0f0" stroke-width="1"/><line x1="0" y1="220" x2="1364" y2="220" stroke="#f0f0f0" stroke-width="1"/><line x1="0" y1="260" x2="1364" y2="260" stroke="#f0f0f0" stroke-width="1"/><line x1="0" y1="300" x2="1364" y2="300" stroke="#f0f0f0" stroke-width="1"/><line x1="0" y1="340" x2="1364" y2="340" stroke="#f0f0f0" stroke-width="1"/></g><rect width="1364" height="60" fill="#f0f0f0" stroke="#000000" stroke-width="1"/><text x="24" y="30" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="26" font-weight="bold" fill="#000000">Blog schema</text><text x="24" y="48" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="12" fill="#666666">3 entities, generated 2026-09-07</text><text x="1344" y="30" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="12" font-weight="bold" letter-spacing="1.4" fill="#666666" text-anchor="end">ER DIAGRAM</text><rect x="48" y="108" width="270" height="172" fill="#ffffff" stroke="#000000" stroke-width="1"/><rect x="48" y="108" width="270" height="42" fill="#f0f0f0" stroke="#000000" stroke-width="1"/><text x="60" y="128" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#000000">User</text><text x="60" y="143" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="8" fill="#666666">users</text><rect x="48" y="150" width="270" height="26" fill="#ffffff"/><rect x="48" y="150" width="3" height="26" fill="#000000"/><text x="60" y="167" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="8" font-weight="bold" fill="#000000">PK</text><text x="78" y="167" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="11" font-weight="bold" fill="#000000">id</text><text x="310" y="167" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="8" fill="#666666" text-anchor="end">INTEGER</text><line x1="48" y1="176" x2="318" y2="176" stroke="#000000" stroke-width="1"/><rect x="48" y="176" width="270" height="26" fill="#f0f0f0"/><circle cx="63" cy="189" r="2" fill="#666666"/><text x="78" y="193" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="11" font-weight="normal" fill="#000000">email</text><text x="310" y="193" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="8" fill="#666666" text-anchor="end">VARCHAR(255)</text><line x1="48" y1="202" x2="318" y2="202" stroke="#000000" stroke-width="1"/><rect x="48" y="202" width="270" height="26" fill="#ffffff"/><circle cx="63" cy="215" r="2" fill="#666666"/><text x="78" y="219" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="11" font-weight="normal" fill="#000000">name</text><text x="310" y="219" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="8" fill="#666666" text-anchor="end">VARCHAR(100)</text><line x1="48" y1="228" x2="318" y2="228" stroke="#000000" stroke-width="1"/><rect x="48" y="228" width="270" height="26" fill="#f0f0f0"/><circle cx="63" cy="241" r="2" fill="#666666"/><text x="78" y="245" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="11" font-weight="normal" fill="#000000">createdAt</text><text x="310" y="245" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="8" fill="#666666" text-anchor="end">DATETIME</text><line x1="48" y1="254" x2="318" y2="254" stroke="#000000" stroke-width="1"/><rect x="48" y="254" width="270" height="26" fill="#f0f0f0"/><line x1="48" y1="254" x2="318" y2="254" stroke="#000000" stroke-width="1"/><text x="60" y="271" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="8" fill="#666666">4 fields</text><rect x="408" y="108" width="270" height="172" fill="#ffffff" stroke="#000000" stroke-width="1"/><rect x="408" y="108" width="270" height="42" fill="#f0f0f0" stroke="#000000" stroke-width="1"/><text x="420" y="128" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#000000">Post</text><text x="420" y="143" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="8" fill="#666666">posts</text><rect x="408" y="150" width="270" height="26" fill="#ffffff"/><rect x="408" y="150" width="3" height="26" fill="#000000"/><text x="420" y="167" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="8" font-weight="bold" fill="#000000">PK</text><text x="438" y="167" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="11" font-weight="bold" fill="#000000">id</text><text x="670" y="167" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="8" fill="#666666" text-anchor="end">INTEGER</text><line x1="408" y1="176" x2="678" y2="176" stroke="#000000" stroke-width="1"/><rect x="408" y="176" width="270" height="26" fill="#f0f0f0"/><circle cx="423" cy="189" r="2" fill="#666666"/><text x="438" y="193" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="11" font-weight="normal" fill="#000000">title</text><text x="670" y="193" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="8" fill="#666666" text-anchor="end">VARCHAR(200)</text><line x1="408" y1="202" x2="678" y2="202" stroke="#000000" stroke-width="1"/><rect x="408" y="202" width="270" height="26" fill="#ffffff"/><circle cx="423" cy="215" r="2" fill="#666666"/><text x="438" y="219" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="11" font-weight="normal" fill="#000000">body</text><text x="670" y="219" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="8" fill="#666666" text-anchor="end">TEXT</text><line x1="408" y1="228" x2="678" y2="228" stroke="#000000" stroke-width="1"/><rect x="408" y="228" width="270" height="26" fill="#f0f0f0"/><rect x="408" y="228" width="3" height="26" fill="#000000"/><text x="420" y="245" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="8" font-weight="bold" fill="#000000">FK</text><text x="438" y="245" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="11" font-weight="bold" fill="#000000">authorId</text><text x="670" y="245" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="8" fill="#666666" text-anchor="end">INTEGER</text><line x1="408" y1="254" x2="678" y2="254" stroke="#000000" stroke-width="1"/><rect x="408" y="254" width="270" height="26" fill="#f0f0f0"/><line x1="408" y1="254" x2="678" y2="254" stroke="#000000" stroke-width="1"/><text x="420" y="271" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="8" fill="#666666">4 fields</text><rect x="768" y="134" width="270" height="120" fill="#ffffff" stroke="#000000" stroke-width="1"/><rect x="768" y="134" width="270" height="42" fill="#f0f0f0" stroke="#000000" stroke-width="1"/><text x="780" y="154" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="17" font-weight="bold" fill="#000000">Tag</text><text x="780" y="169" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="8" fill="#666666">tags</text><rect x="768" y="176" width="270" height="26" fill="#ffffff"/><rect x="768" y="176" width="3" height="26" fill="#000000"/><text x="780" y="193" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="8" font-weight="bold" fill="#000000">PK</text><text x="798" y="193" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="11" font-weight="bold" fill="#000000">id</text><text x="1030" y="193" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="8" fill="#666666" text-anchor="end">INTEGER</text><line x1="768" y1="202" x2="1038" y2="202" stroke="#000000" stroke-width="1"/><rect x="768" y="202" width="270" height="26" fill="#f0f0f0"/><circle cx="783" cy="215" r="2" fill="#666666"/><text x="798" y="219" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="11" font-weight="normal" fill="#000000">slug</text><text x="1030" y="219" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="8" fill="#666666" text-anchor="end">VARCHAR(60)</text><line x1="768" y1="228" x2="1038" y2="228" stroke="#000000" stroke-width="1"/><rect x="768" y="228" width="270" height="26" fill="#f0f0f0"/><line x1="768" y1="228" x2="1038" y2="228" stroke="#000000" stroke-width="1"/><text x="780" y="245" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="8" fill="#666666">2 fields</text><rect x="1106" y="108" width="210" height="212" fill="#ffffff" stroke="#000000" stroke-width="1"/><rect x="1106" y="108" width="210" height="30" fill="#f0f0f0" stroke="#000000" stroke-width="1"/><text x="1122" y="128" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="13" font-weight="bold" letter-spacing="1" fill="#000000">LEGEND</text><rect x="1122" y="158" width="34" height="18" fill="#f0f0f0" stroke="#000000" stroke-width="1"/><text x="1139" y="171" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="8" font-weight="bold" fill="#000000" text-anchor="middle">1:1</text><line x1="1164" y1="167" x2="1186" y2="167" stroke="#000000" stroke-width="1"/><text x="1194" y="171" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="12" fill="#000000">Has One</text><rect x="1122" y="186" width="34" height="18" fill="#f0f0f0" stroke="#000000" stroke-width="1"/><text x="1139" y="199" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="8" font-weight="bold" fill="#000000" text-anchor="middle">1:N</text><line x1="1164" y1="195" x2="1186" y2="195" stroke="#000000" stroke-width="1"/><text x="1194" y="199" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="12" fill="#000000">Has Many</text><rect x="1122" y="214" width="34" height="18" fill="#f0f0f0" stroke="#000000" stroke-width="1"/><text x="1139" y="227" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="8" font-weight="bold" fill="#000000" text-anchor="middle">N:1</text><line x1="1164" y1="223" x2="1186" y2="223" stroke="#000000" stroke-width="1"/><text x="1194" y="227" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="12" fill="#000000">Belongs To</text><rect x="1122" y="242" width="34" height="18" fill="#f0f0f0" stroke="#000000" stroke-width="1"/><text x="1139" y="255" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="8" font-weight="bold" fill="#000000" text-anchor="middle">N:N</text><line x1="1164" y1="251" x2="1186" y2="251" stroke="#000000" stroke-width="1"/><text x="1194" y="255" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="12" fill="#000000">Belongs To Many</text><line x1="1122" y1="276" x2="1166" y2="276" stroke="#000000" stroke-width="1"/><text x="1122" y="292" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="8" font-weight="bold" fill="#000000">PK</text><text x="1144" y="292" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="11" fill="#666666">Primary Key</text><text x="1122" y="308" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="8" font-weight="bold" fill="#000000">FK</text><text x="1144" y="308" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="11" fill="#666666">Foreign Key</text></svg> </div> Takes the same shape as define(), so you can generate one from the model definitions you already have. columns controls the grid width. Saving it generate() returns the SVG as a string; save(path) writes it straight to disk. Related reading Diagram generators — every generator and its options Models — the definitions these are drawn from