Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -282,4 +282,8 @@ MIT License — see [LICENSE](LICENSE) for details.

Made with ❤️ by [Krish](https://github.com/ykrishhh) | [Portfolio](https://harrydev.one) | [Twitter](https://x.com/ykrishhh)

</div>
</div>

## Architecture

Explore interactive diagrams of this project's architecture: [docs/architecture.html](docs/architecture.html).
124 changes: 124 additions & 0 deletions docs/architecture.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>HarryPanel – Architecture</title>
<style>
:root{ --paper:#050510; --paper-2:#0d0d1a; --ink:#eaeaea; --muted:#8a8a9e;
--rule:rgba(234,234,234,0.12); --accent:#00d4aa; --link:#6a95d8; }
*{ box-sizing:border-box; margin:0; padding:0; }
body{ background:var(--paper); color:var(--ink);
font-family:'Geist',system-ui,-apple-system,sans-serif;
padding:2rem; line-height:1.5; }
h1{ font-family:'Instrument Serif',serif; font-size:2rem;
letter-spacing:-0.02em; margin-bottom:.5rem; }
.meta{ font-family:'Geist Mono',monospace; font-size:11px;
color:var(--muted); margin-bottom:1rem; }
.grid{ display:grid; grid-template-columns:repeat(auto-fit,minmax(360px,1fr));
gap:1.2rem; margin-top:1.5rem; }
.card{ background:var(--paper-2); border:1px solid var(--rule);
border-radius:4px; padding:1rem; }
.card h2{ font-size:1rem; margin-bottom:.75rem; color:var(--accent);
font-family:'Geist Mono',monospace; text-transform:uppercase;
letter-spacing:.1em; }
.card svg{ width:100%; height:auto; }
dialog{ background:var(--paper-2); color:var(--ink);
border:1px solid var(--accent); border-radius:6px;
padding:1.5rem; max-width:480px; }
dialog::backdrop{ background:rgba(0,0,0,0.7); }
dialog h3{ color:var(--accent); margin-bottom:.5rem;
font-family:'Geist Mono',monospace; }
dialog p{ font-size:14px; color:var(--muted); }
dialog button{ background:var(--accent); color:var(--paper);
border:0; padding:.5rem 1rem; border-radius:3px;
font-family:'Geist Mono',monospace; margin-top:1rem; cursor:pointer; }
a.back{ color:var(--muted); text-decoration:none;
font-family:'Geist Mono',monospace; font-size:11px; }
.node{ cursor:pointer; transition:filter .2s ease; }
.node:hover{ filter:drop-shadow(0 0 8px var(--accent)); }
.node text{ font-family:'Geist',sans-serif; fill:var(--ink); }
.node-label{ font-family:'Geist Mono',monospace; font-size:9px;
fill:var(--muted); }
</style>
</head>
<body>
<a class="back" href="../../README.md">← Back to README</a>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fix the README backlink path

When this page is opened from docs/architecture.html, ../../README.md resolves two directories up, outside the repository path (or to the site root on GitHub Pages), so the “Back to README” link lands on a missing file instead of the project README. Since the README now directs users to this page, the backlink should only go up one level, e.g. ../README.md.

Useful? React with 👍 / 👎.

<h1>HarryPanel – Architecture</h1>
<div class="meta">★ 1 · Procfile, Python, HTML, Dockerfile · created 2026-07-02 · updated 2026-07-19</div>
<p>Web hosting control panel: server management, database admin, file manager, and deployment tools</p>
<div class="grid">
<div class="card"><h2>Architecture</h2><svg viewBox="0 0 940 460" xmlns="http://www.w3.org/2000/svg">
<title>Architecture</title>
<defs><marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"><path d="M0 0 L10 5 L0 10 Z" fill="rgba(234,234,234,0.45)"/></marker></defs>
<rect width="940" height="460" fill="transparent"/>
<line x1="470" y1="90" x2="470" y2="130" stroke="rgba(234,234,234,0.25)" stroke-width="1" marker-end="url(#arr)"/>
<line x1="470" y1="90" x2="470" y2="240" stroke="rgba(234,234,234,0.25)" stroke-width="1" marker-end="url(#arr)"/>
<line x1="470" y1="200" x2="470" y2="240" stroke="rgba(234,234,234,0.25)" stroke-width="1" marker-end="url(#arr)"/>
<g class="node" data-node data-title="Input" data-desc="User / API Entry"><rect x="310" y="20" width="320" height="70" rx="4" ry="4" fill="rgba(0,212,170,0.06)" stroke="#00d4aa" stroke-width="1.2"/><text x="470" y="48" text-anchor="middle" font-size="13" font-weight="600" fill="#eaeaea">Input</text><text x="470" y="68" text-anchor="middle" font-size="10" fill="#8a8a9e" class="node-label">User / API Entry</text></g>
<g class="node" data-node data-title="Core Engine" data-desc="HarryPanel logic"><rect x="310" y="130" width="320" height="70" rx="4" ry="4" fill="rgba(0,212,170,0.06)" stroke="#6a95d8" stroke-width="1.2"/><text x="470" y="158" text-anchor="middle" font-size="13" font-weight="600" fill="#eaeaea">Core Engine</text><text x="470" y="178" text-anchor="middle" font-size="10" fill="#8a8a9e" class="node-label">HarryPanel logic</text></g>
<g class="node" data-node data-title="Output" data-desc="Reports / Artifacts"><rect x="310" y="240" width="320" height="70" rx="4" ry="4" fill="rgba(0,212,170,0.06)" stroke="#d3ad7a" stroke-width="1.2"/><text x="470" y="268" text-anchor="middle" font-size="13" font-weight="600" fill="#eaeaea">Output</text><text x="470" y="288" text-anchor="middle" font-size="10" fill="#8a8a9e" class="node-label">Reports / Artifacts</text></g>
</svg></div>
<div class="card"><h2>Components</h2><svg viewBox="0 0 940 460" xmlns="http://www.w3.org/2000/svg">
<title>Components</title>
<defs><marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"><path d="M0 0 L10 5 L0 10 Z" fill="rgba(234,234,234,0.45)"/></marker></defs>
<rect width="940" height="460" fill="transparent"/>
<line x1="300" y1="90" x2="300" y2="130" stroke="rgba(234,234,234,0.25)" stroke-width="1" marker-end="url(#arr)"/>
<line x1="300" y1="90" x2="300" y2="240" stroke="rgba(234,234,234,0.25)" stroke-width="1" marker-end="url(#arr)"/>
<line x1="640" y1="90" x2="640" y2="130" stroke="rgba(234,234,234,0.25)" stroke-width="1" marker-end="url(#arr)"/>
<line x1="640" y1="90" x2="640" y2="240" stroke="rgba(234,234,234,0.25)" stroke-width="1" marker-end="url(#arr)"/>
<line x1="300" y1="200" x2="300" y2="240" stroke="rgba(234,234,234,0.25)" stroke-width="1" marker-end="url(#arr)"/>
<line x1="640" y1="200" x2="640" y2="240" stroke="rgba(234,234,234,0.25)" stroke-width="1" marker-end="url(#arr)"/>
<g class="node" data-node data-title="CLI" data-desc="Entry"><rect x="140" y="20" width="320" height="70" rx="4" ry="4" fill="rgba(0,212,170,0.06)" stroke="#00d4aa" stroke-width="1.2"/><text x="300" y="48" text-anchor="middle" font-size="13" font-weight="600" fill="#eaeaea">CLI</text><text x="300" y="68" text-anchor="middle" font-size="10" fill="#8a8a9e" class="node-label">Entry</text></g>
<g class="node" data-node data-title="Config" data-desc="YAML/JSON"><rect x="480" y="20" width="320" height="70" rx="4" ry="4" fill="rgba(0,212,170,0.06)" stroke="#00d4aa" stroke-width="1.2"/><text x="640" y="48" text-anchor="middle" font-size="13" font-weight="600" fill="#eaeaea">Config</text><text x="640" y="68" text-anchor="middle" font-size="10" fill="#8a8a9e" class="node-label">YAML/JSON</text></g>
<g class="node" data-node data-title="Parser" data-desc="Load input"><rect x="140" y="130" width="320" height="70" rx="4" ry="4" fill="rgba(0,212,170,0.06)" stroke="#6a95d8" stroke-width="1.2"/><text x="300" y="158" text-anchor="middle" font-size="13" font-weight="600" fill="#eaeaea">Parser</text><text x="300" y="178" text-anchor="middle" font-size="10" fill="#8a8a9e" class="node-label">Load input</text></g>
<g class="node" data-node data-title="Logic" data-desc="Web hosting control panel"><rect x="480" y="130" width="320" height="70" rx="4" ry="4" fill="rgba(0,212,170,0.06)" stroke="#6a95d8" stroke-width="1.2"/><text x="640" y="158" text-anchor="middle" font-size="13" font-weight="600" fill="#eaeaea">Logic</text><text x="640" y="178" text-anchor="middle" font-size="10" fill="#8a8a9e" class="node-label">Web hosting control panel</text></g>
<g class="node" data-node data-title="Storage" data-desc="Cache/DB"><rect x="140" y="240" width="320" height="70" rx="4" ry="4" fill="rgba(0,212,170,0.06)" stroke="#d3ad7a" stroke-width="1.2"/><text x="300" y="268" text-anchor="middle" font-size="13" font-weight="600" fill="#eaeaea">Storage</text><text x="300" y="288" text-anchor="middle" font-size="10" fill="#8a8a9e" class="node-label">Cache/DB</text></g>
<g class="node" data-node data-title="Logger" data-desc="Audit trail"><rect x="480" y="240" width="320" height="70" rx="4" ry="4" fill="rgba(0,212,170,0.06)" stroke="#d3ad7a" stroke-width="1.2"/><text x="640" y="268" text-anchor="middle" font-size="13" font-weight="600" fill="#eaeaea">Logger</text><text x="640" y="288" text-anchor="middle" font-size="10" fill="#8a8a9e" class="node-label">Audit trail</text></g>
</svg></div>
<div class="card"><h2>Data Flow</h2><svg viewBox="0 0 940 460" xmlns="http://www.w3.org/2000/svg">
<title>Data Flow</title>
<defs><marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"><path d="M0 0 L10 5 L0 10 Z" fill="rgba(234,234,234,0.45)"/></marker></defs>
<rect width="940" height="460" fill="transparent"/>
<line x1="470" y1="90" x2="300" y2="130" stroke="rgba(234,234,234,0.25)" stroke-width="1" marker-end="url(#arr)"/>
<line x1="470" y1="90" x2="640" y2="130" stroke="rgba(234,234,234,0.25)" stroke-width="1" marker-end="url(#arr)"/>
<line x1="470" y1="90" x2="470" y2="240" stroke="rgba(234,234,234,0.25)" stroke-width="1" marker-end="url(#arr)"/>
<line x1="300" y1="200" x2="470" y2="240" stroke="rgba(234,234,234,0.25)" stroke-width="1" marker-end="url(#arr)"/>
<line x1="640" y1="200" x2="470" y2="240" stroke="rgba(234,234,234,0.25)" stroke-width="1" marker-end="url(#arr)"/>
<g class="node" data-node data-title="Start" data-desc="Init"><rect x="310" y="20" width="320" height="70" rx="4" ry="4" fill="rgba(0,212,170,0.06)" stroke="#00d4aa" stroke-width="1.2"/><text x="470" y="48" text-anchor="middle" font-size="13" font-weight="600" fill="#eaeaea">Start</text><text x="470" y="68" text-anchor="middle" font-size="10" fill="#8a8a9e" class="node-label">Init</text></g>
<g class="node" data-node data-title="Read" data-desc="Input"><rect x="140" y="130" width="320" height="70" rx="4" ry="4" fill="rgba(0,212,170,0.06)" stroke="#6a95d8" stroke-width="1.2"/><text x="300" y="158" text-anchor="middle" font-size="13" font-weight="600" fill="#eaeaea">Read</text><text x="300" y="178" text-anchor="middle" font-size="10" fill="#8a8a9e" class="node-label">Input</text></g>
<g class="node" data-node data-title="Process" data-desc="HarryPanel Procfile"><rect x="480" y="130" width="320" height="70" rx="4" ry="4" fill="rgba(0,212,170,0.06)" stroke="#d3ad7a" stroke-width="1.2"/><text x="640" y="158" text-anchor="middle" font-size="13" font-weight="600" fill="#eaeaea">Process</text><text x="640" y="178" text-anchor="middle" font-size="10" fill="#8a8a9e" class="node-label">HarryPanel Procfile</text></g>
<g class="node" data-node data-title="Emit" data-desc="Result"><rect x="310" y="240" width="320" height="70" rx="4" ry="4" fill="rgba(0,212,170,0.06)" stroke="#d3ad7a" stroke-width="1.2"/><text x="470" y="268" text-anchor="middle" font-size="13" font-weight="600" fill="#eaeaea">Emit</text><text x="470" y="288" text-anchor="middle" font-size="10" fill="#8a8a9e" class="node-label">Result</text></g>
</svg></div>
<div class="card"><h2>Hybrid</h2><svg viewBox="0 0 940 460" xmlns="http://www.w3.org/2000/svg">
<title>Hybrid</title>
<defs><marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"><path d="M0 0 L10 5 L0 10 Z" fill="rgba(234,234,234,0.45)"/></marker></defs>
<rect width="940" height="460" fill="transparent"/>
<line x1="470" y1="90" x2="470" y2="130" stroke="rgba(234,234,234,0.25)" stroke-width="1" marker-end="url(#arr)"/>
<line x1="470" y1="90" x2="300" y2="240" stroke="rgba(234,234,234,0.25)" stroke-width="1" marker-end="url(#arr)"/>
<line x1="470" y1="90" x2="640" y2="240" stroke="rgba(234,234,234,0.25)" stroke-width="1" marker-end="url(#arr)"/>
<line x1="130" y1="200" x2="300" y2="240" stroke="rgba(234,234,234,0.25)" stroke-width="1" marker-end="url(#arr)"/>
<line x1="470" y1="200" x2="300" y2="240" stroke="rgba(234,234,234,0.25)" stroke-width="1" marker-end="url(#arr)"/>
<line x1="470" y1="200" x2="640" y2="240" stroke="rgba(234,234,234,0.25)" stroke-width="1" marker-end="url(#arr)"/>
<line x1="810" y1="200" x2="640" y2="240" stroke="rgba(234,234,234,0.25)" stroke-width="1" marker-end="url(#arr)"/>
<g class="node" data-node data-title="User" data-desc="Operator"><rect x="310" y="20" width="320" height="70" rx="4" ry="4" fill="rgba(0,212,170,0.06)" stroke="#00d4aa" stroke-width="1.2"/><text x="470" y="48" text-anchor="middle" font-size="13" font-weight="600" fill="#eaeaea">User</text><text x="470" y="68" text-anchor="middle" font-size="10" fill="#8a8a9e" class="node-label">Operator</text></g>
<g class="node" data-node data-title="Auth" data-desc="Session"><rect x="-30" y="130" width="320" height="70" rx="4" ry="4" fill="rgba(0,212,170,0.06)" stroke="#00d4aa" stroke-width="1.2"/><text x="130" y="158" text-anchor="middle" font-size="13" font-weight="600" fill="#eaeaea">Auth</text><text x="130" y="178" text-anchor="middle" font-size="10" fill="#8a8a9e" class="node-label">Session</text></g>
<g class="node" data-node data-title="Logic" data-desc="Main"><rect x="310" y="130" width="320" height="70" rx="4" ry="4" fill="rgba(0,212,170,0.06)" stroke="#6a95d8" stroke-width="1.2"/><text x="470" y="158" text-anchor="middle" font-size="13" font-weight="600" fill="#eaeaea">Logic</text><text x="470" y="178" text-anchor="middle" font-size="10" fill="#8a8a9e" class="node-label">Main</text></g>
<g class="node" data-node data-title="DB" data-desc="State"><rect x="650" y="130" width="320" height="70" rx="4" ry="4" fill="rgba(0,212,170,0.06)" stroke="#6a95d8" stroke-width="1.2"/><text x="810" y="158" text-anchor="middle" font-size="13" font-weight="600" fill="#eaeaea">DB</text><text x="810" y="178" text-anchor="middle" font-size="10" fill="#8a8a9e" class="node-label">State</text></g>
<g class="node" data-node data-title="Report" data-desc="Output"><rect x="140" y="240" width="320" height="70" rx="4" ry="4" fill="rgba(0,212,170,0.06)" stroke="#d3ad7a" stroke-width="1.2"/><text x="300" y="268" text-anchor="middle" font-size="13" font-weight="600" fill="#eaeaea">Report</text><text x="300" y="288" text-anchor="middle" font-size="10" fill="#8a8a9e" class="node-label">Output</text></g>
<g class="node" data-node data-title="Audit" data-desc="Log"><rect x="480" y="240" width="320" height="70" rx="4" ry="4" fill="rgba(0,212,170,0.06)" stroke="#d3ad7a" stroke-width="1.2"/><text x="640" y="268" text-anchor="middle" font-size="13" font-weight="600" fill="#eaeaea">Audit</text><text x="640" y="288" text-anchor="middle" font-size="10" fill="#8a8a9e" class="node-label">Log</text></g>
</svg></div>
</div>
<dialog id="node-modal"><h3 id="modal-title"></h3><p id="modal-desc"></p><button onclick="document.getElementById('node-modal').close()">Close</button></dialog>
<script>
function showNode(title, desc){
document.getElementById('modal-title').textContent = title;
document.getElementById('modal-desc').textContent = desc;
document.getElementById('node-modal').showModal();
}
document.querySelectorAll('[data-node]').forEach(n=>{
n.addEventListener('click', ()=>showNode(n.dataset.title, n.dataset.desc));
});
</script>
</body>
</html>