@eltonssouza/development-utility-kit 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/.claude/agents/README.md +24 -0
  2. package/.claude/agents/analyst.md +198 -0
  3. package/.claude/agents/backend-developer.md +126 -0
  4. package/.claude/agents/brain-keeper.md +229 -0
  5. package/.claude/agents/code-reviewer.md +181 -0
  6. package/.claude/agents/database-engineer.md +94 -0
  7. package/.claude/agents/devops-engineer.md +141 -0
  8. package/.claude/agents/frontend-developer.md +97 -0
  9. package/.claude/agents/gate-keeper.md +118 -0
  10. package/.claude/agents/migrator.md +291 -0
  11. package/.claude/agents/mobile-developer.md +80 -0
  12. package/.claude/agents/n8n-specialist.md +94 -0
  13. package/.claude/agents/product-owner.md +115 -0
  14. package/.claude/agents/qa-engineer.md +232 -0
  15. package/.claude/agents/release-engineer.md +204 -0
  16. package/.claude/agents/scaffold.md +87 -0
  17. package/.claude/agents/security-engineer.md +199 -0
  18. package/.claude/agents/sprint-runner.md +46 -0
  19. package/.claude/agents/stack-resolver.md +104 -0
  20. package/.claude/agents/tech-lead.md +182 -0
  21. package/.claude/agents/update-template.md +54 -0
  22. package/.claude/agents/ux-designer.md +118 -0
  23. package/.claude/hooks/flow-guard.js +261 -0
  24. package/.claude/hooks/flow-state.js +197 -0
  25. package/.claude/local/CLAUDE.md +71 -0
  26. package/.claude/settings.json +55 -0
  27. package/.claude/skills/README.md +331 -0
  28. package/.claude/skills/active-project/SKILL.md +131 -0
  29. package/.claude/skills/api-integration-test/SKILL.md +84 -0
  30. package/.claude/skills/auto-test-guard/SKILL.md +239 -0
  31. package/.claude/skills/auto-test-guard/resources/backend-tests.md +20 -0
  32. package/.claude/skills/auto-test-guard/resources/e2e-tests.md +24 -0
  33. package/.claude/skills/auto-test-guard/resources/execution-report.md +49 -0
  34. package/.claude/skills/auto-test-guard/resources/frontend-tests.md +18 -0
  35. package/.claude/skills/auto-test-guard/resources/initial-setup.md +108 -0
  36. package/.claude/skills/auto-test-guard/resources/run-suite.md +48 -0
  37. package/.claude/skills/auto-test-guard/resources/senior-gate.md +19 -0
  38. package/.claude/skills/brain-keeper/SKILL.md +62 -0
  39. package/.claude/skills/brain-keeper/obsidian/app.json +9 -0
  40. package/.claude/skills/brain-keeper/obsidian/appearance.json +4 -0
  41. package/.claude/skills/brain-keeper/obsidian/core-plugins.json +20 -0
  42. package/.claude/skills/brain-keeper/obsidian/daily-notes.json +5 -0
  43. package/.claude/skills/brain-keeper/obsidian/graph.json +32 -0
  44. package/.claude/skills/brain-keeper/obsidian/snippets/folder-colors.css +90 -0
  45. package/.claude/skills/brain-keeper/obsidian/templates.json +5 -0
  46. package/.claude/skills/brain-keeper/templates/README.md +51 -0
  47. package/.claude/skills/brain-keeper/templates/adr.md +40 -0
  48. package/.claude/skills/brain-keeper/templates/bug.md +35 -0
  49. package/.claude/skills/brain-keeper/templates/daily.md +38 -0
  50. package/.claude/skills/brain-keeper/templates/feature.md +62 -0
  51. package/.claude/skills/brain-keeper/templates/meeting.md +34 -0
  52. package/.claude/skills/brain-keeper/templates/tech-debt.md +21 -0
  53. package/.claude/skills/caveman/SKILL.md +189 -0
  54. package/.claude/skills/create-stack-pack/SKILL.md +281 -0
  55. package/.claude/skills/grill-me/SKILL.md +80 -0
  56. package/.claude/skills/pair-debug/SKILL.md +288 -0
  57. package/.claude/skills/prd-ready-check/SKILL.md +86 -0
  58. package/.claude/skills/project-manager/SKILL.md +334 -0
  59. package/.claude/skills/quality-standards/SKILL.md +203 -0
  60. package/.claude/skills/quick-feature/SKILL.md +266 -0
  61. package/.claude/skills/run-sprint/SKILL.md +41 -0
  62. package/.claude/skills/scaffold/SKILL.md +60 -0
  63. package/.claude/skills/stack-discovery/SKILL.md +161 -0
  64. package/.claude/skills/test-coverage-auditor/SKILL.md +87 -0
  65. package/.claude/skills/to-issues/SKILL.md +163 -0
  66. package/.claude/skills/to-prd/SKILL.md +130 -0
  67. package/.claude/skills/update-template/SKILL.md +256 -0
  68. package/.claude/stacks/CODEOWNERS +30 -0
  69. package/.claude/stacks/README.md +97 -0
  70. package/.claude/stacks/_template.md +116 -0
  71. package/.claude/stacks/dotnet/aspire-9.md +528 -0
  72. package/.claude/stacks/go/gin-1.10.md +570 -0
  73. package/.claude/stacks/java/spring-boot-3.md +376 -0
  74. package/.claude/stacks/java/spring-boot-4.md +438 -0
  75. package/.claude/stacks/node/express-5.md +538 -0
  76. package/.claude/stacks/python/django-5.md +483 -0
  77. package/.claude/stacks/python/fastapi-0.115.md +522 -0
  78. package/.claude/stacks/typescript/angular-18.md +420 -0
  79. package/.claude/stacks/typescript/angular-19.md +397 -0
  80. package/.claude/stacks/typescript/angular-21.md +494 -0
  81. package/CLAUDE.md +472 -0
  82. package/README.md +412 -0
  83. package/bin/cli.js +848 -0
  84. package/bin/lib/adr.js +146 -0
  85. package/bin/lib/backup.js +62 -0
  86. package/bin/lib/detect-stack.js +476 -0
  87. package/bin/lib/doctor.js +527 -0
  88. package/bin/lib/help.js +328 -0
  89. package/bin/lib/identity.js +108 -0
  90. package/bin/lib/lint-allowlist.json +15 -0
  91. package/bin/lib/lint.js +798 -0
  92. package/bin/lib/local-dir.js +68 -0
  93. package/bin/lib/manifest.js +236 -0
  94. package/bin/lib/sync-all.js +394 -0
  95. package/bin/lib/version-check.js +398 -0
  96. package/dashboard/db.js +321 -0
  97. package/dashboard/package.json +22 -0
  98. package/dashboard/public/app.js +853 -0
  99. package/dashboard/public/content/docs/agents-reference.en.md +911 -0
  100. package/dashboard/public/content/docs/architecture-overview.en.md +252 -0
  101. package/dashboard/public/content/docs/autonomy-matrix.en.md +186 -0
  102. package/dashboard/public/content/docs/cli-reference.en.md +538 -0
  103. package/dashboard/public/content/docs/git-flow.en.md +525 -0
  104. package/dashboard/public/content/docs/honcho-memory.en.md +394 -0
  105. package/dashboard/public/content/docs/hooks-reference.en.md +404 -0
  106. package/dashboard/public/content/docs/pipeline.en.md +414 -0
  107. package/dashboard/public/content/docs/plugins.en.md +289 -0
  108. package/dashboard/public/content/docs/quality-gate.en.md +315 -0
  109. package/dashboard/public/content/docs/skills-reference.en.md +484 -0
  110. package/dashboard/public/content/docs/stack-rules.en.md +362 -0
  111. package/dashboard/public/content/docs/troubleshooting.en.md +565 -0
  112. package/dashboard/public/content/manifest.json +114 -0
  113. package/dashboard/public/content/manual/backend.en.md +1053 -0
  114. package/dashboard/public/content/manual/existing-project.en.md +848 -0
  115. package/dashboard/public/content/manual/frontend.en.md +1008 -0
  116. package/dashboard/public/content/manual/fullstack.en.md +1459 -0
  117. package/dashboard/public/content/manual/mobile.en.md +837 -0
  118. package/dashboard/public/content/manual/quickstart.en.md +169 -0
  119. package/dashboard/public/index.html +217 -0
  120. package/dashboard/public/style.css +857 -0
  121. package/dashboard/public/vendor/marked.min.js +69 -0
  122. package/dashboard/rtk.js +143 -0
  123. package/dashboard/server-app.js +421 -0
  124. package/dashboard/server.js +104 -0
  125. package/dashboard/test/sprint1.test.js +406 -0
  126. package/dashboard/test/sprint2.test.js +571 -0
  127. package/dashboard/test/sprint3.test.js +560 -0
  128. package/package.json +33 -0
  129. package/scripts/hooks/subagent-telemetry.sh +14 -0
  130. package/scripts/hooks/telemetry-writer.js +250 -0
  131. package/scripts/latest-versions.json +56 -0
@@ -0,0 +1,169 @@
1
+ # Quickstart — 5 minutes to first value
2
+
3
+ Goal: from zero installation to a useful response from `duk` in 5 minutes. No prior knowledge of the harness's internals required.
4
+
5
+ If you are evaluating whether `duk` fits your workflow, this is the right starting point. Architecture, ADRs, and stack packs come later.
6
+
7
+ ---
8
+
9
+ ## Prerequisites (30 seconds to verify)
10
+
11
+ ```bash
12
+ node --version # need >= 18
13
+ git --version # any recent version
14
+ ```
15
+
16
+ If both pass, you are ready. If not, install Node 18+ and Git first.
17
+
18
+ You also need either **Claude Code** (CLI) or **Cowork** (the conversational desktop app). They are how the harness gets its work done. The harness itself is just installable skills and agents that live in your project — there is no `duk run` command that talks to an LLM. The LLM client (Claude Code / Cowork) reads the skills and invokes the agents.
19
+
20
+ ---
21
+
22
+ ## Path A — Brand new project (1 minute)
23
+
24
+ ```bash
25
+ cd C:/development/source/projects # or wherever you keep projects
26
+
27
+ npx @eltonssouza/development-utility-kit new my-app
28
+ cd my-app
29
+ ```
30
+
31
+ What just happened:
32
+
33
+ - A folder `my-app/` was created
34
+ - `git init -q` initialized a fresh repo
35
+ - The harness was injected: `.claude/` (skills + agents + stacks), `CLAUDE.md` (template), `.claude/local/` placeholder
36
+ - The Project Identity block in `CLAUDE.md` is empty, waiting for you to declare your stack
37
+
38
+ Open the folder in Cowork or Claude Code, then type in chat:
39
+
40
+ ```
41
+ sabatina pra projeto novo
42
+ ```
43
+
44
+ (or in English: `stack discovery`)
45
+
46
+ The `stack-discovery` skill walks you through 5–8 questions about your stack (language, framework, version, database, UI lib, domain). Each question comes with a recommended answer — you just confirm. At the end, your `Project Identity` is filled and you can scaffold.
47
+
48
+ ---
49
+
50
+ ## Path B — Existing project (2 minutes)
51
+
52
+ ```bash
53
+ cd path/to/existing-project
54
+
55
+ npx @eltonssouza/development-utility-kit install
56
+ ```
57
+
58
+ What just happened:
59
+
60
+ - The CLI scanned `pom.xml`, `package.json`, `pyproject.toml`, `go.mod`, etc. to detect your stack
61
+ - It injected `.claude/` and `CLAUDE.md` into the project
62
+ - A `.claude/.MANIFEST` file was written (sha256 per file) — future installs will detect any local drift and refuse to overwrite without `--force`
63
+ - Your existing `CLAUDE.md` is preserved if present (the `## Project Identity` block in particular)
64
+
65
+ Open the folder in Cowork or Claude Code. The harness is ready.
66
+
67
+ ---
68
+
69
+ ## Your first useful prompt
70
+
71
+ In chat, try one of these:
72
+
73
+ | You say | What happens |
74
+ |---|---|
75
+ | `"scaffold the project"` | `scaffold` skill reads your Project Identity and generates the appropriate skeleton (backend / frontend / fullstack monorepo). |
76
+ | `"cria endpoint POST /api/v1/users"` | `project-manager` routes to `backend-developer` agent, which writes controller + service + DTO + test, following your stack pack's conventions. |
77
+ | `"audita seguranca do projeto"` | `project-manager` routes to `security-engineer` agent, which runs an OWASP/LGPD scan and reports findings. |
78
+ | `"grill me about authentication"` | `grill-me` skill starts a discovery interview — one decision at a time — and persists conclusions to `docs/discovery/DISCOVERY_authentication.md`. |
79
+ | `"executa Sprint 1 do PLAN_users.md"` | `run-sprint` skill executes the sprint with TDD, dispatching `qa-engineer`, `backend-developer`, `frontend-developer`, and `gate-keeper` in parallel. |
80
+
81
+ Each prompt triggers the right skill via keyword match (declarations in `.claude/skills/<name>/SKILL.md` frontmatter `description`). You do not need to memorize them — just describe what you want.
82
+
83
+ ---
84
+
85
+ ## Inspect what is running — duk dashboard
86
+
87
+ ```bash
88
+ duk dashboard
89
+ ```
90
+
91
+ Opens a local web UI at `http://localhost:4242` (or next free port) with:
92
+
93
+ - **Telemetry**: which subagent was invoked, when, how long
94
+ - **Model breakdown**: how much Opus vs Sonnet vs Haiku you have used
95
+ - **RTK savings**: if you have RTK on PATH, real token savings from the proxy
96
+ - **Manuals + Tech Docs tabs**: this very page (quickstart), architecture overview, skills reference, agents reference, plugins, ADR catalog
97
+
98
+ The dashboard reads from `~/.claude/telemetry.db` (SQLite, populated by the `SubagentStop` hook). It is read-only — nothing you do in the UI changes your project.
99
+
100
+ ---
101
+
102
+ ## Validate everything is OK — duk doctor
103
+
104
+ ```bash
105
+ duk doctor
106
+ ```
107
+
108
+ Mechanical health check. No LLM, no API call. Validates:
109
+
110
+ - Node ≥18, git, npx, python presence
111
+ - Harness `.claude/` structure is complete
112
+ - `~/.claude/settings.json` is valid JSON; hooks point to existing files
113
+ - Stack packs are available
114
+ - Credentials file exists (for VPS-aware skills)
115
+ - If you are inside an adopted project: `MANIFEST` exists and Project Identity is filled
116
+
117
+ Returns exit code `0` if all PASS. Use `--strict` to fail on WARNs too. Use `--json` for CI parsing.
118
+
119
+ ```bash
120
+ duk doctor --strict
121
+ duk doctor --json | jq .summary
122
+ ```
123
+
124
+ ---
125
+
126
+ ## What to read next
127
+
128
+ You just installed the harness, scaffolded or adopted a project, ran your first prompt, and verified the environment. From here, three reading paths depending on your goal:
129
+
130
+ | Goal | Read |
131
+ |---|---|
132
+ | "How do skills know when to fire?" | [architecture-overview](../docs/architecture-overview) — 3-layer model, keyword matching, agent dispatch |
133
+ | "What skill should I use for X?" | [skills-reference](../docs/skills-reference) — full catalog, per-skill triggers, when NOT to use |
134
+ | "Which agent does what?" | [agents-reference](../docs/agents-reference) — 25 agents grouped by domain authority |
135
+ | "What is the discovery → delivery pipeline?" | [pipeline](../docs/pipeline) — full canonical flow + shortcuts for small features |
136
+ | "Who decides what, when do I get interrupted?" | [autonomy-matrix](../docs/autonomy-matrix) — the master rule |
137
+ | "Why these external plugins?" | [plugins](../docs/plugins) — selection rationale for grill-me, caveman, impeccable, rtk |
138
+ | "What CLI commands exist?" | [cli-reference](../docs/cli-reference) — all `duk` commands with flags, examples, exit codes |
139
+ | "Java + Spring Boot specifics" | [Fullstack manual](fullstack) |
140
+ | "Angular specifics" | [Frontend manual](frontend) |
141
+ | "Spring Boot backend only" | [Backend manual](backend) |
142
+ | "React Native mobile" | [Mobile manual](mobile) |
143
+
144
+ If you adopt the harness on a real project and ship something with it, please consider contributing an entry to `docs/EVIDENCE.md` — real metrics from real projects are what move the harness forward.
145
+
146
+ ---
147
+
148
+ ## Troubleshooting
149
+
150
+ | Symptom | Likely cause | Fix |
151
+ |---|---|---|
152
+ | `duk doctor` reports Node < 18 | Old Node installed | Install Node 18+ from nodejs.org or your package manager |
153
+ | `duk install` aborts with "drift detected" | You modified `.claude/` after the previous install | Move your changes to `.claude/local/` (preserved across installs) OR run `duk install --force` (overwrite + backup) |
154
+ | Chat does not seem to trigger any skill | Keywords do not match any skill's `description` | Try a more explicit phrasing OR fall through to `project-manager` (catch-all) by phrasing as a normal dev request like "create endpoint POST /api/v1/foo" |
155
+ | `duk dashboard` says "port 4242 in use" | Another process holds the port | Pass `--port 5000` (or any free port) |
156
+ | RTK widget shows no data | RTK not on PATH (intentional fallback) | Install rtk separately if you want the metric; otherwise ignore |
157
+ | `duk lint` reports ERRORs in skills you did not touch | Frontmatter incomplete in the harness | Open an issue with the lint output — likely a regression |
158
+
159
+ For deeper problems: [troubleshooting](../docs/troubleshooting).
160
+
161
+ ---
162
+
163
+ ## What this guide skipped on purpose
164
+
165
+ - The 8-stage canonical pipeline (`grill-me → to-prd → to-issues → analyst → architect → tech-lead → sprint-runner → gate-keeper → code-reviewer → tech-lead → brain-keeper`). For 99% of tasks you do not invoke it directly — `project-manager` handles routing. Read [pipeline](../docs/pipeline) when you need the formal flow.
166
+ - 34 ADRs. They explain why each architectural choice was made. Read them when you are evaluating whether to adopt the harness for a serious project, or when you propose a change. Not required for daily use.
167
+ - The senior+ quality gate thresholds (coverage ≥85%, mutation ≥70%, a11y, Lighthouse). They run when `gate-keeper` is invoked — you do not need to memorize them.
168
+
169
+ If after 5 minutes you got the value above and want to go deeper, all of this is one click away in the dashboard. Welcome.
@@ -0,0 +1,217 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>development-utility-kit dashboard</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet" />
10
+ <link rel="stylesheet" href="style.css" />
11
+ <script src="https://cdn.jsdelivr.net/npm/chart.js@4/dist/chart.umd.min.js"></script>
12
+ <script
13
+ src="https://cdn.jsdelivr.net/npm/marked@15/marked.min.js"
14
+ onerror="(function(){var s=document.createElement('script');s.src='vendor/marked.min.js';document.head.appendChild(s);})()"
15
+ ></script>
16
+ </head>
17
+ <body>
18
+
19
+ <!-- LOADING SCREEN -->
20
+ <div class="loader" id="loader">
21
+ <div style="text-align:center">
22
+ <div class="loader-ring-wrap">
23
+ <div class="loader-ring"></div>
24
+ <div class="loader-ring"></div>
25
+ <div class="loader-ring"></div>
26
+ </div>
27
+ <div class="loader-text">INITIALIZING</div>
28
+ </div>
29
+ </div>
30
+
31
+ <!-- NEURAL NETWORK BACKGROUND -->
32
+ <canvas id="neuralCanvas"></canvas>
33
+
34
+ <header class="app-header">
35
+ <h1>development-utility-kit</h1>
36
+ <span class="badge">dashboard</span>
37
+ <span class="badge" id="last-updated">loading…</span>
38
+
39
+ <nav class="tab-nav" role="tablist">
40
+ <button class="tab-btn active" data-tab="dashboard" role="tab" aria-selected="true">Dashboard</button>
41
+ <button class="tab-btn" data-tab="manual" role="tab" aria-selected="false">Manual</button>
42
+ <button class="tab-btn" data-tab="docs" role="tab" aria-selected="false">Tech Docs</button>
43
+ </nav>
44
+
45
+ </header>
46
+
47
+ <!-- Panel: Dashboard (existing telemetry) -->
48
+ <section id="panel-dashboard" class="tab-panel active" role="tabpanel">
49
+ <main class="grid">
50
+
51
+ <!-- Card: Projects -->
52
+ <section class="card" id="projects-card">
53
+ <h2 class="card-title">Projects (last 30 days)</h2>
54
+ <ul class="project-list" id="project-list">
55
+ <li class="empty-state">Loading…</li>
56
+ </ul>
57
+ </section>
58
+
59
+ <!-- Card: Models -->
60
+ <section class="card" id="models-card">
61
+ <h2 class="card-title">Model Breakdown</h2>
62
+ <div class="chart-wrap">
63
+ <canvas id="models-chart"></canvas>
64
+ </div>
65
+ </section>
66
+
67
+ <!-- Card: RTK Token Savings -->
68
+ <section class="card" id="rtk-card">
69
+ <h2 class="card-title">RTK Token Savings</h2>
70
+ <div class="rtk-summary" id="rtk-summary">
71
+ <div class="rtk-stat">
72
+ <span class="value" id="rtk-tokens">—</span>
73
+ <span class="label">tokens saved</span>
74
+ </div>
75
+ <div class="rtk-stat">
76
+ <span class="value" id="rtk-pct">—</span>
77
+ <span class="label">savings %</span>
78
+ </div>
79
+ </div>
80
+ <div class="chart-wrap">
81
+ <canvas id="rtk-chart"></canvas>
82
+ </div>
83
+ </section>
84
+
85
+ </main>
86
+
87
+ <!-- Processes panel: shown when a project is selected from the list -->
88
+ <section id="processes-panel" class="processes-panel" hidden aria-live="polite">
89
+ <div class="processes-header">
90
+ <h2 class="processes-title">Processes — <span id="processes-project-name"></span></h2>
91
+ <button class="processes-close" id="processes-close" aria-label="Close processes panel">&times;</button>
92
+ </div>
93
+ <div id="processes-list" class="processes-list">
94
+ <p class="empty-state">Loading…</p>
95
+ </div>
96
+ </section>
97
+ </section>
98
+
99
+ <!-- Panel: Manual -->
100
+ <section id="panel-manual" class="tab-panel" role="tabpanel" hidden>
101
+ <div class="panel-layout">
102
+ <aside class="toc-sidebar" id="toc-manual" aria-label="Table of contents"></aside>
103
+ <div class="panel-content">
104
+ <div class="scenario-selector" id="manual-scenario-selector">
105
+ <!-- Scenario buttons rendered by app.js from manifest -->
106
+ </div>
107
+ <div id="translation-banner-manual" class="translation-banner" hidden>
108
+ </div>
109
+ <div class="content-body" id="manual-content-body">
110
+ <p class="empty-state">Select a scenario above.</p>
111
+ </div>
112
+ </div>
113
+ </div>
114
+ </section>
115
+
116
+ <!-- Panel: Tech Docs -->
117
+ <section id="panel-docs" class="tab-panel" role="tabpanel" hidden>
118
+ <div class="panel-layout">
119
+ <aside class="toc-sidebar" id="toc-docs" aria-label="Table of contents"></aside>
120
+ <div class="panel-content">
121
+ <div id="translation-banner-docs" class="translation-banner" hidden>
122
+ </div>
123
+ <div class="content-body" id="docs-content-body">
124
+ <p class="empty-state">Select a section.</p>
125
+ </div>
126
+ </div>
127
+ </div>
128
+ </section>
129
+
130
+ <footer class="status-bar">
131
+ <span><span class="dot"></span>live — polling every 5 s</span>
132
+ <span id="status-msg">connecting…</span>
133
+ </footer>
134
+
135
+ <!-- Neural canvas + loader dismiss -->
136
+ <script>
137
+ (function () {
138
+ var canvas = document.getElementById('neuralCanvas');
139
+ var ctx = canvas.getContext('2d');
140
+ var particles = [];
141
+
142
+ function resize() {
143
+ canvas.width = window.innerWidth;
144
+ canvas.height = window.innerHeight;
145
+ }
146
+ resize();
147
+ window.addEventListener('resize', resize);
148
+
149
+ function Particle() {
150
+ this.reset();
151
+ }
152
+ Particle.prototype.reset = function () {
153
+ this.x = Math.random() * canvas.width;
154
+ this.y = Math.random() * canvas.height;
155
+ this.size = Math.random() * 1.4 + 0.4;
156
+ this.vx = (Math.random() - 0.5) * 0.35;
157
+ this.vy = (Math.random() - 0.5) * 0.35;
158
+ this.opacity = Math.random() * 0.35 + 0.08;
159
+ };
160
+ Particle.prototype.update = function () {
161
+ this.x += this.vx;
162
+ this.y += this.vy;
163
+ if (this.x > canvas.width) this.x = 0;
164
+ if (this.x < 0) this.x = canvas.width;
165
+ if (this.y > canvas.height) this.y = 0;
166
+ if (this.y < 0) this.y = canvas.height;
167
+ };
168
+ Particle.prototype.draw = function () {
169
+ ctx.beginPath();
170
+ ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
171
+ ctx.fillStyle = 'rgba(109,179,255,' + this.opacity + ')';
172
+ ctx.fill();
173
+ };
174
+
175
+ function init() {
176
+ particles = [];
177
+ var n = Math.min(55, Math.floor((canvas.width * canvas.height) / 22000));
178
+ for (var i = 0; i < n; i++) particles.push(new Particle());
179
+ }
180
+ init();
181
+ window.addEventListener('resize', init);
182
+
183
+ function animate() {
184
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
185
+ for (var i = 0; i < particles.length; i++) {
186
+ particles[i].update();
187
+ particles[i].draw();
188
+ for (var j = i + 1; j < particles.length; j++) {
189
+ var dx = particles[i].x - particles[j].x;
190
+ var dy = particles[i].y - particles[j].y;
191
+ var d = Math.sqrt(dx * dx + dy * dy);
192
+ if (d < 120) {
193
+ ctx.beginPath();
194
+ ctx.strokeStyle = 'rgba(26,107,255,' + (1 - d / 120) * 0.1 + ')';
195
+ ctx.lineWidth = 0.5;
196
+ ctx.moveTo(particles[i].x, particles[i].y);
197
+ ctx.lineTo(particles[j].x, particles[j].y);
198
+ ctx.stroke();
199
+ }
200
+ }
201
+ }
202
+ requestAnimationFrame(animate);
203
+ }
204
+ animate();
205
+
206
+ window.addEventListener('load', function () {
207
+ setTimeout(function () {
208
+ var loader = document.getElementById('loader');
209
+ if (loader) loader.classList.add('hidden');
210
+ }, 900);
211
+ });
212
+ })();
213
+ </script>
214
+
215
+ <script src="app.js"></script>
216
+ </body>
217
+ </html>