heyiam 0.2.28 → 0.3.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.
- package/README.md +45 -0
- package/dist/config.js +10 -1
- package/dist/db.js +1 -2
- package/dist/export.js +40 -25
- package/dist/format-utils.js +5 -0
- package/dist/index.js +168 -0
- package/dist/mount.js +300 -102
- package/dist/parsers/claude.js +2 -28
- package/dist/parsers/codex.js +2 -26
- package/dist/parsers/cursor.js +2 -26
- package/dist/parsers/duration.js +35 -0
- package/dist/parsers/gemini.js +2 -20
- package/dist/parsers/types.js +0 -1
- package/dist/public/assets/index-BZ65TU_Y.js +40 -0
- package/dist/public/assets/index-CqCaW2cb.css +1 -0
- package/dist/public/index.html +2 -2
- package/dist/redact.js +4 -104
- package/dist/render/build-render-data.js +9 -2
- package/dist/render/index.js +32 -5
- package/dist/render/liquid.js +147 -7
- package/dist/render/mock-data.js +303 -0
- package/dist/render/templates/aurora/portfolio.liquid +204 -0
- package/dist/render/templates/aurora/project.liquid +260 -0
- package/dist/render/templates/aurora/session.liquid +223 -0
- package/dist/render/templates/aurora/styles.css +1178 -0
- package/dist/render/templates/bauhaus/portfolio.liquid +179 -0
- package/dist/render/templates/bauhaus/project.liquid +300 -0
- package/dist/render/templates/bauhaus/session.liquid +333 -0
- package/dist/render/templates/bauhaus/styles.css +1641 -0
- package/dist/render/templates/blueprint/portfolio.liquid +167 -0
- package/dist/render/templates/blueprint/project.liquid +286 -0
- package/dist/render/templates/blueprint/session.liquid +248 -0
- package/dist/render/templates/blueprint/styles.css +1285 -0
- package/dist/render/templates/canvas/portfolio.liquid +215 -0
- package/dist/render/templates/canvas/project.liquid +235 -0
- package/dist/render/templates/canvas/session.liquid +223 -0
- package/dist/render/templates/canvas/styles.css +1436 -0
- package/dist/render/templates/carbon/portfolio.liquid +170 -0
- package/dist/render/templates/carbon/project.liquid +249 -0
- package/dist/render/templates/carbon/session.liquid +190 -0
- package/dist/render/templates/carbon/styles.css +1091 -0
- package/dist/render/templates/chalk/portfolio.liquid +199 -0
- package/dist/render/templates/chalk/project.liquid +245 -0
- package/dist/render/templates/chalk/session.liquid +215 -0
- package/dist/render/templates/chalk/styles.css +1157 -0
- package/dist/render/templates/circuit/portfolio.liquid +162 -0
- package/dist/render/templates/circuit/project.liquid +247 -0
- package/dist/render/templates/circuit/session.liquid +205 -0
- package/dist/render/templates/circuit/styles.css +1403 -0
- package/dist/render/templates/cosmos/portfolio.liquid +232 -0
- package/dist/render/templates/cosmos/project.liquid +327 -0
- package/dist/render/templates/cosmos/session.liquid +239 -0
- package/dist/render/templates/cosmos/styles.css +1151 -0
- package/dist/render/templates/daylight/portfolio.liquid +217 -0
- package/dist/render/templates/daylight/project.liquid +229 -0
- package/dist/render/templates/daylight/session.liquid +219 -0
- package/dist/render/templates/daylight/styles.css +1311 -0
- package/dist/render/templates/editorial/portfolio.liquid +126 -0
- package/dist/render/templates/editorial/project.liquid +202 -0
- package/dist/render/templates/editorial/session.liquid +171 -0
- package/dist/render/templates/editorial/styles.css +822 -0
- package/dist/render/templates/ember/portfolio.liquid +318 -0
- package/dist/render/templates/ember/project.liquid +232 -0
- package/dist/render/templates/ember/session.liquid +202 -0
- package/dist/render/templates/ember/styles.css +1283 -0
- package/dist/render/templates/glacier/portfolio.liquid +271 -0
- package/dist/render/templates/glacier/project.liquid +288 -0
- package/dist/render/templates/glacier/session.liquid +217 -0
- package/dist/render/templates/glacier/styles.css +1200 -0
- package/dist/render/templates/grid/portfolio.liquid +265 -0
- package/dist/render/templates/grid/project.liquid +306 -0
- package/dist/render/templates/grid/session.liquid +260 -0
- package/dist/render/templates/grid/styles.css +1441 -0
- package/dist/render/templates/kinetic/portfolio.liquid +170 -0
- package/dist/render/templates/kinetic/project.liquid +242 -0
- package/dist/render/templates/kinetic/session.liquid +228 -0
- package/dist/render/templates/kinetic/styles.css +944 -0
- package/dist/render/templates/meridian/portfolio.liquid +255 -0
- package/dist/render/templates/meridian/project.liquid +376 -0
- package/dist/render/templates/meridian/session.liquid +298 -0
- package/dist/render/templates/meridian/styles.css +1369 -0
- package/dist/render/templates/minimal/portfolio.liquid +71 -0
- package/dist/render/templates/minimal/project.liquid +154 -0
- package/dist/render/templates/minimal/session.liquid +140 -0
- package/dist/render/templates/minimal/styles.css +525 -0
- package/dist/render/templates/mono/portfolio.liquid +291 -0
- package/dist/render/templates/mono/project.liquid +275 -0
- package/dist/render/templates/mono/session.liquid +276 -0
- package/dist/render/templates/mono/styles.css +1016 -0
- package/dist/render/templates/neon/portfolio.liquid +217 -0
- package/dist/render/templates/neon/project.liquid +225 -0
- package/dist/render/templates/neon/session.liquid +195 -0
- package/dist/render/templates/neon/styles.css +1265 -0
- package/dist/render/templates/noir/portfolio.liquid +137 -0
- package/dist/render/templates/noir/project.liquid +220 -0
- package/dist/render/templates/noir/session.liquid +241 -0
- package/dist/render/templates/noir/styles.css +1223 -0
- package/dist/render/templates/obsidian/portfolio.liquid +257 -0
- package/dist/render/templates/obsidian/project.liquid +280 -0
- package/dist/render/templates/obsidian/session.liquid +241 -0
- package/dist/render/templates/obsidian/styles.css +1401 -0
- package/dist/render/templates/paper/portfolio.liquid +267 -0
- package/dist/render/templates/paper/project.liquid +235 -0
- package/dist/render/templates/paper/session.liquid +271 -0
- package/dist/render/templates/paper/styles.css +1509 -0
- package/dist/render/templates/parallax/portfolio.liquid +305 -0
- package/dist/render/templates/parallax/project.liquid +275 -0
- package/dist/render/templates/parallax/session.liquid +295 -0
- package/dist/render/templates/parallax/styles.css +1874 -0
- package/dist/render/templates/parchment/portfolio.liquid +290 -0
- package/dist/render/templates/parchment/project.liquid +289 -0
- package/dist/render/templates/parchment/session.liquid +346 -0
- package/dist/render/templates/parchment/styles.css +1397 -0
- package/dist/render/templates/partials/_beats.liquid +16 -0
- package/dist/render/templates/partials/_breadcrumb.liquid +9 -0
- package/dist/render/templates/partials/_footer.liquid +7 -0
- package/dist/render/templates/partials/_growth-chart.liquid +7 -0
- package/dist/render/templates/partials/_key-decisions.liquid +20 -0
- package/dist/render/templates/partials/_links.liquid +16 -0
- package/dist/render/templates/partials/_narrative.liquid +8 -0
- package/dist/render/templates/partials/_phases.liquid +20 -0
- package/dist/render/templates/partials/_portfolio-header.liquid +20 -0
- package/dist/render/templates/partials/_portfolio-projects.liquid +16 -0
- package/dist/render/templates/partials/_portfolio-stats.liquid +19 -0
- package/dist/render/templates/partials/_qa.liquid +13 -0
- package/dist/render/templates/partials/_screenshot.liquid +15 -0
- package/dist/render/templates/partials/_session-cards.liquid +30 -0
- package/dist/render/templates/partials/_session-header.liquid +39 -0
- package/dist/render/templates/partials/_session-sidebar.liquid +30 -0
- package/dist/render/templates/partials/_skills.liquid +12 -0
- package/dist/render/templates/partials/_source-breakdown.liquid +22 -0
- package/dist/render/templates/partials/_stats.liquid +38 -0
- package/dist/render/templates/partials/_work-timeline.liquid +7 -0
- package/dist/render/templates/project.liquid +7 -4
- package/dist/render/templates/radar/portfolio.liquid +233 -0
- package/dist/render/templates/radar/project.liquid +278 -0
- package/dist/render/templates/radar/session.liquid +300 -0
- package/dist/render/templates/radar/styles.css +1049 -0
- package/dist/render/templates/showcase/portfolio.liquid +231 -0
- package/dist/render/templates/showcase/project.liquid +237 -0
- package/dist/render/templates/showcase/session.liquid +210 -0
- package/dist/render/templates/showcase/styles.css +1279 -0
- package/dist/render/templates/signal/portfolio.liquid +227 -0
- package/dist/render/templates/signal/project.liquid +278 -0
- package/dist/render/templates/signal/session.liquid +282 -0
- package/dist/render/templates/signal/styles.css +1395 -0
- package/dist/render/templates/strata/portfolio.liquid +192 -0
- package/dist/render/templates/strata/project.liquid +282 -0
- package/dist/render/templates/strata/session.liquid +261 -0
- package/dist/render/templates/strata/styles.css +1350 -0
- package/dist/render/templates/styles.css +1190 -0
- package/dist/render/templates/terminal/portfolio.liquid +118 -0
- package/dist/render/templates/terminal/project.liquid +161 -0
- package/dist/render/templates/terminal/session.liquid +145 -0
- package/dist/render/templates/terminal/styles.css +492 -0
- package/dist/render/templates/verdant/portfolio.liquid +333 -0
- package/dist/render/templates/verdant/project.liquid +309 -0
- package/dist/render/templates/verdant/session.liquid +237 -0
- package/dist/render/templates/verdant/styles.css +1257 -0
- package/dist/render/templates/zen/portfolio.liquid +136 -0
- package/dist/render/templates/zen/project.liquid +187 -0
- package/dist/render/templates/zen/session.liquid +203 -0
- package/dist/render/templates/zen/styles.css +1207 -0
- package/dist/render/templates.js +90 -0
- package/dist/routes/context.js +15 -10
- package/dist/routes/enhance.js +17 -40
- package/dist/routes/export.js +14 -4
- package/dist/routes/preview.js +480 -108
- package/dist/routes/projects.js +11 -19
- package/dist/routes/publish.js +15 -17
- package/dist/routes/settings.js +94 -1
- package/dist/routes/sse.js +9 -0
- package/dist/server.js +8 -2
- package/dist/settings.js +17 -9
- package/package.json +2 -4
- package/dist/public/assets/index-B_d6DlEI.js +0 -21
- package/dist/public/assets/index-Dalqz2mC.css +0 -1
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
<div class="heyiam-portfolio showcase" data-render-version="2" data-template="showcase" data-username="{{ user.username }}">
|
|
2
|
+
|
|
3
|
+
{% if hasProfile %}
|
|
4
|
+
<!-- Cinematic Hero -->
|
|
5
|
+
<section class="sc-hero" id="hero-section" aria-label="Portfolio header">
|
|
6
|
+
{% if user.photoUrl %}
|
|
7
|
+
<div class="sc-hero__bg" style="background-image: url('{{ user.photoUrl }}');" aria-hidden="true"></div>
|
|
8
|
+
{% endif %}
|
|
9
|
+
<div class="sc-hero__overlay" aria-hidden="true"></div>
|
|
10
|
+
|
|
11
|
+
<div class="sc-hero__content sc-hero-fade">
|
|
12
|
+
{% if user.photoUrl %}
|
|
13
|
+
<img
|
|
14
|
+
src="{{ user.photoUrl }}"
|
|
15
|
+
alt="{{ user.displayName }}"
|
|
16
|
+
class="sc-hero__photo"
|
|
17
|
+
width="160"
|
|
18
|
+
height="200"
|
|
19
|
+
>
|
|
20
|
+
{% endif %}
|
|
21
|
+
<div class="sc-hero__info">
|
|
22
|
+
{% if user.displayName != blank %}
|
|
23
|
+
<h1 class="sc-hero__name">{{ user.displayName }}</h1>
|
|
24
|
+
{% endif %}
|
|
25
|
+
{% if user.location != blank %}
|
|
26
|
+
<div class="sc-hero__location">{{ user.location }}</div>
|
|
27
|
+
{% endif %}
|
|
28
|
+
{% if user.bio != blank %}
|
|
29
|
+
<p class="sc-hero__bio">{{ user.bio }}</p>
|
|
30
|
+
{% endif %}
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<!-- Contact links -->
|
|
35
|
+
<div class="sc-hero__contact sc-hero-fade">
|
|
36
|
+
{% if user.email != blank %}
|
|
37
|
+
<a href="mailto:{{ user.email }}"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="m2 4 10 8 10-8"/></svg> {{ user.email }}</a>
|
|
38
|
+
{% endif %}
|
|
39
|
+
{% if user.linkedinUrl != blank %}
|
|
40
|
+
<a href="{{ user.linkedinUrl }}" target="_blank" rel="noopener"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M20.5 2h-17A1.5 1.5 0 002 3.5v17A1.5 1.5 0 003.5 22h17a1.5 1.5 0 001.5-1.5v-17A1.5 1.5 0 0020.5 2zM8 19H5v-9h3zM6.5 8.25A1.75 1.75 0 118.3 6.5a1.78 1.78 0 01-1.8 1.75zM19 19h-3v-4.74c0-1.42-.6-1.93-1.38-1.93A1.74 1.74 0 0013 14.19V19h-3v-9h2.9v1.3a3.11 3.11 0 012.7-1.4c1.55 0 3.36.86 3.36 3.66z"/></svg> LinkedIn</a>
|
|
41
|
+
{% endif %}
|
|
42
|
+
{% if user.githubUrl != blank %}
|
|
43
|
+
<a href="{{ user.githubUrl }}" target="_blank" rel="noopener"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"/></svg> GitHub</a>
|
|
44
|
+
{% endif %}
|
|
45
|
+
{% if user.twitterHandle != blank %}
|
|
46
|
+
<a href="https://x.com/{{ user.twitterHandle }}" target="_blank" rel="noopener"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg> @{{ user.twitterHandle }}</a>
|
|
47
|
+
{% endif %}
|
|
48
|
+
{% if user.websiteUrl != blank %}
|
|
49
|
+
<a href="{{ user.websiteUrl }}" target="_blank" rel="noopener">{{ user.websiteUrl | stripProtocol }}</a>
|
|
50
|
+
{% endif %}
|
|
51
|
+
{% if user.resumeUrl != blank %}
|
|
52
|
+
<a href="{{ user.resumeUrl }}" class="sc-hero__resume-btn" download><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="12" y1="18" x2="12" y2="12"/><polyline points="9 15 12 18 15 15"/></svg> Resume (PDF)</a>
|
|
53
|
+
{% endif %}
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<!-- Stats counters -->
|
|
57
|
+
<div class="sc-hero__stats sc-hero-fade" id="hero-stats">
|
|
58
|
+
<div class="sc-hero-stat">
|
|
59
|
+
<div class="sc-hero-stat__value" data-count-to="{{ projects.size }}" data-format="int">0</div>
|
|
60
|
+
<div class="sc-hero-stat__label">Projects</div>
|
|
61
|
+
</div>
|
|
62
|
+
<div class="sc-hero-stat">
|
|
63
|
+
<div class="sc-hero-stat__value" data-count-to="{{ totalSessions }}" data-format="int">0</div>
|
|
64
|
+
<div class="sc-hero-stat__label">Sessions</div>
|
|
65
|
+
</div>
|
|
66
|
+
<div class="sc-hero-stat">
|
|
67
|
+
<div class="sc-hero-stat__value" data-count-to="{{ totalLoc }}" data-format="comma">0</div>
|
|
68
|
+
<div class="sc-hero-stat__label">Lines Changed</div>
|
|
69
|
+
</div>
|
|
70
|
+
{% if totalDurationMinutes %}
|
|
71
|
+
<div class="sc-hero-stat">
|
|
72
|
+
<div class="sc-hero-stat__value" data-count-to="{{ totalDurationMinutes }}" data-format="duration">0</div>
|
|
73
|
+
<div class="sc-hero-stat__label">Total Time</div>
|
|
74
|
+
</div>
|
|
75
|
+
{% endif %}
|
|
76
|
+
</div>
|
|
77
|
+
</section>
|
|
78
|
+
{% endif %}
|
|
79
|
+
|
|
80
|
+
<div class="sc-page">
|
|
81
|
+
<main id="main-content">
|
|
82
|
+
|
|
83
|
+
<!-- Leverage -->
|
|
84
|
+
{% if efficiencyMultiplier %}
|
|
85
|
+
<section class="sc-leverage sc-section section-gap" aria-label="AI leverage" role="figure">
|
|
86
|
+
<div class="sc-leverage__multi">{{ efficiencyMultiplier }}×</div>
|
|
87
|
+
<div class="sc-leverage__context"><span>{{ totalDurationMinutes | formatDuration }} you</span> · <span style="color:var(--accent)">{{ totalAgentDurationMinutes | formatDuration }} agents</span></div>
|
|
88
|
+
{% assign total_combined = totalDurationMinutes | plus: totalAgentDurationMinutes %}
|
|
89
|
+
{% if total_combined > 0 %}
|
|
90
|
+
{% assign human_pct = totalDurationMinutes | times: 100 | divided_by: total_combined %}
|
|
91
|
+
{% assign agent_pct = 100 | minus: human_pct %}
|
|
92
|
+
<div class="sc-leverage__bar"><div class="sc-leverage__human" style="width:{{ human_pct }}%"></div><div class="sc-leverage__agent" style="width:{{ agent_pct }}%"></div></div>
|
|
93
|
+
{% endif %}
|
|
94
|
+
</section>
|
|
95
|
+
{% endif %}
|
|
96
|
+
|
|
97
|
+
<!-- Project Cards -->
|
|
98
|
+
{% if projects.size > 0 %}
|
|
99
|
+
<section class="sc-section section-gap-lg" aria-label="Projects">
|
|
100
|
+
<div class="sc-section-header">
|
|
101
|
+
<h2>Projects</h2>
|
|
102
|
+
<span class="sc-section-label">{{ projects.size }} projects</span>
|
|
103
|
+
</div>
|
|
104
|
+
|
|
105
|
+
{% for p in projects %}
|
|
106
|
+
<a href="/{{ user.username }}/{{ p.slug }}" class="sc-project-card sc-stagger" style="display: block; margin-bottom: 0.75rem;">
|
|
107
|
+
<div class="sc-project-card__accent-bar" style="background: var(--accent);"></div>
|
|
108
|
+
<div class="sc-project-card__title">{{ p.title }}</div>
|
|
109
|
+
{% if p.narrative != blank %}
|
|
110
|
+
<p class="sc-project-card__narrative">{{ p.narrative }}</p>
|
|
111
|
+
{% endif %}
|
|
112
|
+
<div class="sc-project-card__meta">
|
|
113
|
+
<span>{{ p.totalSessions }} sessions</span>
|
|
114
|
+
<span>{{ p.totalDurationMinutes | formatDuration }}</span>
|
|
115
|
+
<span>{{ p.totalLoc | localeNumber }} LOC</span>
|
|
116
|
+
</div>
|
|
117
|
+
{% if p.skills.size > 0 %}
|
|
118
|
+
<div class="sc-project-card__skills">
|
|
119
|
+
{% for skill in p.skills limit: 6 %}
|
|
120
|
+
<span class="sc-skill-chip">{{ skill }}</span>
|
|
121
|
+
{% endfor %}
|
|
122
|
+
</div>
|
|
123
|
+
{% endif %}
|
|
124
|
+
{% if p.sourceCounts.size > 0 %}
|
|
125
|
+
<div class="project-card__source">
|
|
126
|
+
<div class="source-bar-track">
|
|
127
|
+
{% for sc in p.sourceCounts %}
|
|
128
|
+
{% assign pct = sc.count | times: 100 | divided_by: p.totalSessions %}
|
|
129
|
+
<div class="source-bar-segment" style="width: {{ pct }}%; background: var({% if forloop.first %}--accent{% else %}--green{% endif %});"></div>
|
|
130
|
+
{% endfor %}
|
|
131
|
+
</div>
|
|
132
|
+
<div class="source-labels">
|
|
133
|
+
{% for sc in p.sourceCounts %}
|
|
134
|
+
{% assign pct = sc.count | times: 100 | divided_by: p.totalSessions %}
|
|
135
|
+
<span>{{ sc.tool }} {{ pct }}%</span>
|
|
136
|
+
{% endfor %}
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
{% endif %}
|
|
140
|
+
</a>
|
|
141
|
+
{% endfor %}
|
|
142
|
+
</section>
|
|
143
|
+
{% endif %}
|
|
144
|
+
|
|
145
|
+
<!-- Aggregate Skills -->
|
|
146
|
+
{% assign all_skills = "" %}
|
|
147
|
+
{% for p in projects %}
|
|
148
|
+
{% for skill in p.skills %}
|
|
149
|
+
{% unless all_skills contains skill %}
|
|
150
|
+
{% if all_skills != "" %}{% assign all_skills = all_skills | append: "|||" %}{% endif %}
|
|
151
|
+
{% assign all_skills = all_skills | append: skill %}
|
|
152
|
+
{% endunless %}
|
|
153
|
+
{% endfor %}
|
|
154
|
+
{% endfor %}
|
|
155
|
+
{% assign unique_skills = all_skills | split: "|||" %}
|
|
156
|
+
{% if unique_skills.size > 0 %}
|
|
157
|
+
<section class="sc-section section-gap-lg" aria-label="All skills">
|
|
158
|
+
<div class="sc-section-header">
|
|
159
|
+
<h2>Skills Across Projects</h2>
|
|
160
|
+
<span class="sc-section-label">{{ unique_skills.size }} technologies</span>
|
|
161
|
+
</div>
|
|
162
|
+
<div class="sc-skills-section-card">
|
|
163
|
+
<div class="sc-skills-grid">
|
|
164
|
+
{% for skill in unique_skills %}
|
|
165
|
+
<span class="sc-skill-chip--lg sc-stagger">{{ skill }}</span>
|
|
166
|
+
{% endfor %}
|
|
167
|
+
</div>
|
|
168
|
+
</div>
|
|
169
|
+
</section>
|
|
170
|
+
{% endif %}
|
|
171
|
+
|
|
172
|
+
<!-- Source Summary -->
|
|
173
|
+
{% if sourceCounts.size > 0 %}
|
|
174
|
+
<section class="sc-section section-gap-lg" aria-label="Source breakdown and activity">
|
|
175
|
+
<div class="source-summary">
|
|
176
|
+
<div class="source-summary-card sc-stagger">
|
|
177
|
+
<h3>Source Breakdown</h3>
|
|
178
|
+
{% for sc in sourceCounts %}
|
|
179
|
+
{% assign pct = sc.count | times: 100 | divided_by: totalSourceSessions %}
|
|
180
|
+
<div class="source-summary-row">
|
|
181
|
+
<span class="source-summary-row__name">{{ sc.tool }}</span>
|
|
182
|
+
<div class="source-bar-track--summary">
|
|
183
|
+
<div class="source-bar-fill--summary" style="width: {{ pct }}%;"></div>
|
|
184
|
+
</div>
|
|
185
|
+
<span class="source-summary-row__value">{{ pct }}%</span>
|
|
186
|
+
</div>
|
|
187
|
+
{% endfor %}
|
|
188
|
+
<div style="margin-top: 1rem; padding-top: 0.75rem; border-top: 1px solid var(--border);">
|
|
189
|
+
<div class="source-summary-row">
|
|
190
|
+
<span class="source-summary-row__name">Total sessions</span>
|
|
191
|
+
<span class="source-summary-row__value">{{ totalSessions }}</span>
|
|
192
|
+
</div>
|
|
193
|
+
</div>
|
|
194
|
+
</div>
|
|
195
|
+
{% if activityByDay.size > 0 %}
|
|
196
|
+
<div class="activity-card sc-stagger">
|
|
197
|
+
<h3 style="font-family: var(--font-display); font-size: 0.875rem; font-weight: 600; color: var(--text); margin-bottom: 0.75rem;">Activity</h3>
|
|
198
|
+
<div class="activity-grid" aria-label="Activity heatmap showing session frequency over time">
|
|
199
|
+
{% for day in activityByDay %}
|
|
200
|
+
{% if day.count >= 4 %}{% assign level = 4 %}
|
|
201
|
+
{% elsif day.count >= 3 %}{% assign level = 3 %}
|
|
202
|
+
{% elsif day.count >= 2 %}{% assign level = 2 %}
|
|
203
|
+
{% elsif day.count >= 1 %}{% assign level = 1 %}
|
|
204
|
+
{% else %}{% assign level = 0 %}{% endif %}
|
|
205
|
+
<div class="activity-cell{% if level > 0 %} activity-cell--{{ level }}{% endif %}" title="{{ day.date }}: {{ day.count }} sessions"></div>
|
|
206
|
+
{% endfor %}
|
|
207
|
+
</div>
|
|
208
|
+
<div class="activity-legend">
|
|
209
|
+
<span>Less</span>
|
|
210
|
+
<div class="activity-legend__cell" data-level="0"></div>
|
|
211
|
+
<div class="activity-legend__cell" data-level="1"></div>
|
|
212
|
+
<div class="activity-legend__cell" data-level="2"></div>
|
|
213
|
+
<div class="activity-legend__cell" data-level="3"></div>
|
|
214
|
+
<div class="activity-legend__cell" data-level="4"></div>
|
|
215
|
+
<span>More</span>
|
|
216
|
+
</div>
|
|
217
|
+
</div>
|
|
218
|
+
{% endif %}
|
|
219
|
+
</div>
|
|
220
|
+
</section>
|
|
221
|
+
{% endif %}
|
|
222
|
+
|
|
223
|
+
</main>
|
|
224
|
+
|
|
225
|
+
<footer class="sc-footer">
|
|
226
|
+
<span>built with <a href="https://heyi.am">heyi.am</a></span>
|
|
227
|
+
</footer>
|
|
228
|
+
</div>
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
</div>
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
<div class="heyiam-project showcase" data-render-version="2" data-template="showcase"{% if sessionBaseUrl %} data-session-base-url="{{ sessionBaseUrl }}"{% endif %} data-username="{{ user.username }}" data-project-slug="{{ project.slug }}">
|
|
2
|
+
|
|
3
|
+
<div class="sc-page">
|
|
4
|
+
<main id="main-content">
|
|
5
|
+
|
|
6
|
+
<!-- Title -->
|
|
7
|
+
<section class="sc-title-section sc-section section-gap" style="transition-delay: 100ms;" aria-label="Project title">
|
|
8
|
+
<h1 data-editable="title">{{ project.title }}</h1>
|
|
9
|
+
{% if project.narrative != blank %}
|
|
10
|
+
<p class="sc-subtitle">{{ project.narrative | truncate: 80 }}</p>
|
|
11
|
+
{% endif %}
|
|
12
|
+
</section>
|
|
13
|
+
|
|
14
|
+
<!-- Links -->
|
|
15
|
+
{% if project.repoUrl != blank or project.projectUrl != blank %}
|
|
16
|
+
<section class="sc-section section-gap-sm" aria-label="Project links">
|
|
17
|
+
<div class="sc-links">
|
|
18
|
+
{% if project.repoUrl != blank %}
|
|
19
|
+
<a href="{{ project.repoUrl }}" class="sc-stagger" target="_blank" rel="noopener">
|
|
20
|
+
<svg viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
|
|
21
|
+
{{ project.repoUrl | stripProtocol }}
|
|
22
|
+
</a>
|
|
23
|
+
{% endif %}
|
|
24
|
+
{% if project.projectUrl != blank %}
|
|
25
|
+
<a href="{{ project.projectUrl }}" class="sc-stagger" target="_blank" rel="noopener">
|
|
26
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6.5 3.5h-4a1 1 0 00-1 1v9a1 1 0 001 1h9a1 1 0 001-1v-4"/><path d="M9.5 1.5h5v5"/><path d="M14.5 1.5L7 9"/></svg>
|
|
27
|
+
{{ project.projectUrl | stripProtocol }}
|
|
28
|
+
</a>
|
|
29
|
+
{% endif %}
|
|
30
|
+
</div>
|
|
31
|
+
</section>
|
|
32
|
+
{% endif %}
|
|
33
|
+
|
|
34
|
+
<!-- Screenshot -->
|
|
35
|
+
{% if project.screenshotUrl != blank %}
|
|
36
|
+
<section class="sc-section sc-section--screenshot section-gap-lg" aria-label="Screenshot">
|
|
37
|
+
<div class="sc-screenshot-frame">
|
|
38
|
+
<div class="sc-screenshot-chrome" aria-hidden="true">
|
|
39
|
+
<span class="sc-screenshot-dot"></span>
|
|
40
|
+
<span class="sc-screenshot-dot"></span>
|
|
41
|
+
<span class="sc-screenshot-dot"></span>
|
|
42
|
+
{% if project.projectUrl != blank %}
|
|
43
|
+
<span class="sc-screenshot-url">{{ project.projectUrl | stripProtocol }}</span>
|
|
44
|
+
{% endif %}
|
|
45
|
+
</div>
|
|
46
|
+
<div class="sc-screenshot-body">
|
|
47
|
+
<img src="{{ project.screenshotUrl }}" alt="Screenshot of {{ project.title }}" style="width:100%;height:100%;object-fit:cover;">
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
</section>
|
|
51
|
+
{% endif %}
|
|
52
|
+
|
|
53
|
+
<!-- Narrative -->
|
|
54
|
+
{% if project.narrative != blank %}
|
|
55
|
+
<section class="sc-section section-gap-lg" aria-label="Project narrative">
|
|
56
|
+
<div class="sc-narrative">
|
|
57
|
+
<p>{{ project.narrative }}</p>
|
|
58
|
+
</div>
|
|
59
|
+
</section>
|
|
60
|
+
{% endif %}
|
|
61
|
+
|
|
62
|
+
<!-- Stats Grid (animated counters) -->
|
|
63
|
+
<section class="sc-section section-gap-lg" id="stats-section" aria-label="Project statistics">
|
|
64
|
+
<div class="sc-stats-grid">
|
|
65
|
+
<div class="sc-stat-card sc-stagger">
|
|
66
|
+
<div class="sc-stat-card__label">Sessions</div>
|
|
67
|
+
<div class="sc-stat-card__value" data-count-to="{{ project.totalSessions }}" data-format="int">0</div>
|
|
68
|
+
</div>
|
|
69
|
+
<div class="sc-stat-card sc-stagger">
|
|
70
|
+
<div class="sc-stat-card__label">Lines Changed</div>
|
|
71
|
+
<div class="sc-stat-card__value" data-count-to="{{ project.totalLoc }}" data-format="comma">0</div>
|
|
72
|
+
</div>
|
|
73
|
+
<div class="sc-stat-card sc-stagger">
|
|
74
|
+
<div class="sc-stat-card__label">Files Changed</div>
|
|
75
|
+
<div class="sc-stat-card__value" data-count-to="{{ project.totalFilesChanged }}" data-format="int">0</div>
|
|
76
|
+
</div>
|
|
77
|
+
{% if project.totalTokens %}
|
|
78
|
+
<div class="sc-stat-card sc-stagger">
|
|
79
|
+
<div class="sc-stat-card__label">Tokens</div>
|
|
80
|
+
<div class="sc-stat-card__value" data-count-to="{{ project.totalTokens }}" data-format="token">0</div>
|
|
81
|
+
</div>
|
|
82
|
+
{% endif %}
|
|
83
|
+
</div>
|
|
84
|
+
</section>
|
|
85
|
+
|
|
86
|
+
<!-- Work Timeline -->
|
|
87
|
+
<section class="sc-section section-gap-lg" id="timeline-section" aria-label="Work timeline">
|
|
88
|
+
<div class="sc-chart-container">
|
|
89
|
+
<div class="sc-section-header">
|
|
90
|
+
<h3>Work Timeline</h3>
|
|
91
|
+
<span class="sc-section-label">sessions over time</span>
|
|
92
|
+
</div>
|
|
93
|
+
<div data-work-timeline data-sessions='{{ sessionsJson | raw }}'></div>
|
|
94
|
+
</div>
|
|
95
|
+
</section>
|
|
96
|
+
|
|
97
|
+
<!-- Leverage -->
|
|
98
|
+
{% if efficiencyMultiplier %}
|
|
99
|
+
<section class="sc-leverage sc-section section-gap" aria-label="AI leverage" role="figure">
|
|
100
|
+
<div class="sc-leverage__multi">{{ efficiencyMultiplier }}×</div>
|
|
101
|
+
<div class="sc-leverage__context"><span>{{ durationLabel }}</span></div>
|
|
102
|
+
{% if project.totalDurationMinutes > 0 and project.totalAgentDurationMinutes %}
|
|
103
|
+
{% assign total_combined = project.totalDurationMinutes | plus: project.totalAgentDurationMinutes %}
|
|
104
|
+
{% assign human_pct = project.totalDurationMinutes | times: 100.0 | divided_by: total_combined | round %}
|
|
105
|
+
{% assign agent_pct = 100 | minus: human_pct %}
|
|
106
|
+
<div class="sc-leverage__bar"><div class="sc-leverage__human" style="width:{{ human_pct }}%"></div><div class="sc-leverage__agent" style="width:{{ agent_pct }}%"></div></div>
|
|
107
|
+
{% endif %}
|
|
108
|
+
</section>
|
|
109
|
+
{% endif %}
|
|
110
|
+
|
|
111
|
+
<!-- Growth Chart -->
|
|
112
|
+
<section class="sc-section section-gap-lg" id="growth-section" aria-label="Code growth chart">
|
|
113
|
+
<div class="sc-chart-container">
|
|
114
|
+
<div class="sc-section-header">
|
|
115
|
+
<h3>Code Growth</h3>
|
|
116
|
+
<span class="sc-section-label">cumulative lines of code</span>
|
|
117
|
+
</div>
|
|
118
|
+
<div data-growth-chart data-project-slug="{{ project.slug }}" data-sessions='{{ growthJson | raw }}'></div>
|
|
119
|
+
</div>
|
|
120
|
+
</section>
|
|
121
|
+
|
|
122
|
+
<!-- Two-Column: Key Decisions + Source Breakdown -->
|
|
123
|
+
<section class="sc-section section-gap-lg" aria-label="Decisions and source breakdown">
|
|
124
|
+
<div class="sc-two-col">
|
|
125
|
+
{% if arc.size > 0 %}
|
|
126
|
+
<div class="sc-two-col-card sc-stagger">
|
|
127
|
+
<h4>Key Decisions</h4>
|
|
128
|
+
{% for item in arc %}
|
|
129
|
+
<div class="sc-decision-item">
|
|
130
|
+
<div class="sc-phase-label">{{ item.title }}</div>
|
|
131
|
+
<p>{{ item.description }}</p>
|
|
132
|
+
</div>
|
|
133
|
+
{% endfor %}
|
|
134
|
+
</div>
|
|
135
|
+
{% endif %}
|
|
136
|
+
|
|
137
|
+
{% if sourceCounts.size > 0 %}
|
|
138
|
+
<div class="sc-two-col-card sc-stagger">
|
|
139
|
+
<h4>Source Breakdown</h4>
|
|
140
|
+
<div style="margin-top: 0.5rem;">
|
|
141
|
+
{% assign total_sessions = 0 %}
|
|
142
|
+
{% for sc in sourceCounts %}
|
|
143
|
+
{% assign total_sessions = total_sessions | plus: sc.count %}
|
|
144
|
+
{% endfor %}
|
|
145
|
+
{% for sc in sourceCounts %}
|
|
146
|
+
{% if total_sessions > 0 %}
|
|
147
|
+
{% assign pct = sc.count | times: 100.0 | divided_by: total_sessions | round %}
|
|
148
|
+
{% endif %}
|
|
149
|
+
<div class="sc-source-row">
|
|
150
|
+
<span class="sc-source-name">{{ sc.tool }}</span>
|
|
151
|
+
<div class="sc-source-bar-track">
|
|
152
|
+
<div class="sc-source-bar-fill" style="width: {{ pct }}%;"></div>
|
|
153
|
+
</div>
|
|
154
|
+
<span class="sc-source-pct">{{ pct }}%</span>
|
|
155
|
+
</div>
|
|
156
|
+
{% endfor %}
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
{% endif %}
|
|
160
|
+
</div>
|
|
161
|
+
</section>
|
|
162
|
+
|
|
163
|
+
<!-- Phase Timeline -->
|
|
164
|
+
{% if arc.size > 0 %}
|
|
165
|
+
<section class="sc-section section-gap-lg" aria-label="Project phases">
|
|
166
|
+
<div class="sc-section-header">
|
|
167
|
+
<h3>Project Arc</h3>
|
|
168
|
+
<span class="sc-section-label">{{ arc.size }} phases</span>
|
|
169
|
+
</div>
|
|
170
|
+
<div class="sc-phase-timeline">
|
|
171
|
+
<div class="sc-phase-line" aria-hidden="true"></div>
|
|
172
|
+
{% for item in arc %}
|
|
173
|
+
<div class="sc-phase-item">
|
|
174
|
+
<div class="sc-phase-dot" aria-hidden="true"></div>
|
|
175
|
+
<div class="sc-phase-number">Phase {{ item.phase }}</div>
|
|
176
|
+
<div class="sc-phase-title">{{ item.title }}</div>
|
|
177
|
+
<div class="sc-phase-desc">{{ item.description }}</div>
|
|
178
|
+
</div>
|
|
179
|
+
{% endfor %}
|
|
180
|
+
</div>
|
|
181
|
+
</section>
|
|
182
|
+
{% endif %}
|
|
183
|
+
|
|
184
|
+
<!-- Skills -->
|
|
185
|
+
{% if project.skills.size > 0 %}
|
|
186
|
+
<section class="sc-section sc-section--skills section-gap-lg" aria-label="Skills">
|
|
187
|
+
<div class="sc-section-header">
|
|
188
|
+
<h3>Skills</h3>
|
|
189
|
+
<span class="sc-section-label">{{ project.skills.size }} technologies</span>
|
|
190
|
+
</div>
|
|
191
|
+
<div class="sc-skills-grid">
|
|
192
|
+
{% for skill in project.skills %}
|
|
193
|
+
<span class="sc-skill-chip sc-stagger">{{ skill }}</span>
|
|
194
|
+
{% endfor %}
|
|
195
|
+
</div>
|
|
196
|
+
</section>
|
|
197
|
+
{% endif %}
|
|
198
|
+
|
|
199
|
+
<!-- Featured Sessions -->
|
|
200
|
+
{% if featuredSessions.size > 0 %}
|
|
201
|
+
<section class="sc-section sc-section--cards section-gap-lg" aria-label="Featured sessions">
|
|
202
|
+
<div class="sc-section-header">
|
|
203
|
+
<h3>Sessions</h3>
|
|
204
|
+
<span class="sc-section-label">{{ featuredSessions.size }} of {{ project.totalSessions }}</span>
|
|
205
|
+
</div>
|
|
206
|
+
<div class="sc-session-grid">
|
|
207
|
+
{% for s in featuredSessions %}
|
|
208
|
+
<a href="{{ sessionBaseUrl }}/{{ s.slug | default: s.token }}{{ sessionSuffix }}" class="sc-session-card sc-stagger">
|
|
209
|
+
<div class="sc-session-card__accent-bar" style="background: var(--accent);"></div>
|
|
210
|
+
<div class="sc-session-card__title">{{ s.title }}</div>
|
|
211
|
+
<div class="sc-session-card__meta">
|
|
212
|
+
<span>{{ s.durationMinutes | formatDuration }}</span>
|
|
213
|
+
<span>{{ s.locChanged | localeNumber }} LOC</span>
|
|
214
|
+
</div>
|
|
215
|
+
<div class="sc-session-card__bottom">
|
|
216
|
+
{% if s.skills.size > 0 %}
|
|
217
|
+
<span class="sc-session-card__skill">{{ s.skills[0] }}</span>
|
|
218
|
+
{% endif %}
|
|
219
|
+
{% if s.sourceTool != blank %}
|
|
220
|
+
<span class="sc-session-card__source">{{ s.sourceTool }}</span>
|
|
221
|
+
{% endif %}
|
|
222
|
+
</div>
|
|
223
|
+
</a>
|
|
224
|
+
{% endfor %}
|
|
225
|
+
</div>
|
|
226
|
+
</section>
|
|
227
|
+
{% endif %}
|
|
228
|
+
|
|
229
|
+
</main>
|
|
230
|
+
|
|
231
|
+
<footer class="sc-footer">
|
|
232
|
+
<span>built with <a href="https://heyi.am">heyi.am</a></span>
|
|
233
|
+
</footer>
|
|
234
|
+
</div>
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
</div>
|