-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
248 lines (239 loc) · 15.5 KB
/
Copy pathindex.html
File metadata and controls
248 lines (239 loc) · 15.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Hacky - One file. Any AI.</title>
<meta name="description" content="Hacky v0.1 is a bounded AI chat effect in one inspectable JSON or PDF file.">
<meta name="keywords" content="Hacky, AI chat file, character effect, JSON, PDF">
<meta property="og:title" content="Hacky - One file. Any AI.">
<meta property="og:description" content="Create a bounded AI chat effect, inspect it, and carry it between chat surfaces.">
<meta property="og:image" content="https://openhacky.github.io/assets/og.png">
<meta property="og:url" content="https://openhacky.github.io">
<meta name="twitter:card" content="summary_large_image">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>✦</text></svg>">
<style>
:root {
--bg: #0b0d12; --panel: #11151e; --panel2: #171d29; --line: #283244;
--text: #f3f5f8; --muted: #9aa6b8; --accent: #8b7bff; --accent2: #b5aaff;
--mint: #67e8c2; --mono: ui-monospace, SFMono-Regular, Menlo, monospace;
--sans: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body { margin: 0; background: var(--bg); color: var(--text); font: 16px/1.6 var(--sans); }
a { color: var(--accent2); text-decoration: none; }
a:hover { color: var(--text); }
code, pre { font-family: var(--mono); }
.wrap { width: min(1120px, calc(100% - 40px)); margin: 0 auto; }
nav { display: flex; align-items: center; justify-content: space-between; padding: 22px 0; }
.brand { color: var(--text); font: 700 1.1rem var(--mono); letter-spacing: -.04em; }
.brand-mark { color: var(--mint); margin-right: 8px; }
.nav-links { display: flex; gap: 24px; font-size: .9rem; }
.hero { display: grid; grid-template-columns: 1.05fr .95fr; gap: 72px; align-items: center; padding: 88px 0 104px; }
.eyebrow { color: var(--mint); font: 700 .75rem var(--mono); letter-spacing: .13em; text-transform: uppercase; }
h1 { max-width: 680px; margin: 18px 0; font-size: clamp(3.4rem, 8vw, 6.2rem); line-height: .98; letter-spacing: -.075em; }
h1 em { color: var(--accent2); font-style: normal; }
.lead { max-width: 600px; color: var(--muted); font-size: 1.15rem; }
.actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 30px; }
.button { display: inline-flex; align-items: center; gap: 8px; padding: 11px 17px; border: 1px solid var(--line); border-radius: 10px; color: var(--text); background: var(--panel); font-weight: 650; }
.button:hover { border-color: var(--accent); transform: translateY(-1px); }
.button.primary { border-color: var(--accent); background: var(--accent); color: #fff; }
.hero-card { position: relative; padding: 26px; border: 1px solid var(--line); border-radius: 18px; background: linear-gradient(145deg, #151c2a, #0e121a); box-shadow: 0 26px 70px #0008; }
.hero-card:before { content: ""; position: absolute; width: 170px; height: 170px; border-radius: 50%; right: -44px; top: -52px; background: #8b7bff2c; filter: blur(8px); }
.terminal { position: relative; color: #dce5f4; font: .83rem/1.75 var(--mono); white-space: pre-wrap; }
.terminal .dim { color: #718097; } .terminal .mint { color: var(--mint); } .terminal .violet { color: var(--accent2); }
section { padding: 82px 0; border-top: 1px solid #ffffff0d; }
.section-kicker { color: var(--mint); font: 700 .72rem var(--mono); letter-spacing: .14em; text-transform: uppercase; }
h2 { margin: 10px 0 12px; font-size: clamp(2rem, 4vw, 3.2rem); letter-spacing: -.055em; line-height: 1.05; }
.section-intro { max-width: 680px; color: var(--muted); }
.steps, .cards, .install { display: grid; gap: 14px; margin-top: 34px; }
.steps { grid-template-columns: repeat(3, 1fr); }
.cards { grid-template-columns: repeat(4, 1fr); }
.install { grid-template-columns: repeat(3, 1fr); }
.step, .card, .install-card, .contract { padding: 22px; border: 1px solid var(--line); border-radius: 14px; background: var(--panel); }
.number { color: var(--accent2); font: 700 1.4rem var(--mono); }
.step h3, .card h3, .install-card h3 { margin: 12px 0 6px; font-size: 1rem; }
.step p, .card p, .install-card p { margin: 0; color: var(--muted); font-size: .9rem; }
.card { display: flex; flex-direction: column; min-height: 190px; }
.card .tag { margin-top: auto; color: var(--mint); font: .72rem var(--mono); }
.two-col { display: grid; grid-template-columns: .9fr 1.1fr; gap: 38px; align-items: start; }
.contract { overflow: auto; background: #0b1018; }
.contract pre { min-width: 560px; margin: 0; color: #dce5f4; font-size: .8rem; line-height: 1.8; }
.key { color: #9b8cff; } .string { color: #8ce8bf; } .comment { color: #718097; }
.note { margin-top: 18px; color: var(--muted); font-size: .88rem; }
.install-card code { display: block; margin-top: 12px; padding: 10px; overflow: auto; color: #dce5f4; background: #0b1018; border-radius: 8px; font-size: .8rem; }
.boundary { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-top: 30px; }
.boundary div { padding: 18px 20px; border-left: 2px solid var(--mint); background: var(--panel); color: var(--muted); }
.boundary strong { display: block; margin-bottom: 5px; color: var(--text); }
footer { padding: 42px 0 58px; border-top: 1px solid #ffffff0d; color: var(--muted); font-size: .85rem; }
.footer-links { display: flex; flex-wrap: wrap; gap: 20px; margin-bottom: 14px; }
.modal { position: fixed; inset: 0; z-index: 5; display: none; place-items: center; padding: 20px; background: #05070bcc; }
.modal.open { display: grid; }
.modal-box { width: min(720px, 100%); max-height: 90vh; overflow: auto; padding: 24px; border: 1px solid var(--line); border-radius: 16px; background: var(--panel); }
.modal-head { display: flex; justify-content: space-between; gap: 16px; align-items: center; }
.modal-head h3 { margin: 0; }
.modal pre { padding: 16px; overflow: auto; color: #dce5f4; background: #0b1018; border-radius: 10px; font-size: .75rem; white-space: pre-wrap; word-break: break-word; }
.close { border: 0; color: var(--muted); background: transparent; font-size: 1.4rem; cursor: pointer; }
@media (max-width: 800px) {
.hero, .two-col { grid-template-columns: 1fr; gap: 34px; }
.hero { padding: 60px 0 76px; }
.steps, .cards, .install { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 520px) {
.wrap { width: min(100% - 28px, 1120px); }
.nav-links { gap: 12px; font-size: .78rem; }
.steps, .cards, .install, .boundary { grid-template-columns: 1fr; }
h1 { font-size: 3.4rem; }
}
</style>
</head>
<body>
<div class="wrap">
<nav>
<a class="brand" href="index.html"><span class="brand-mark">✦</span>Hacky</a>
<div class="nav-links">
<a href="generator.html">Generator</a>
<a href="#contract">Format</a>
<a href="https://github.com/openhacky/hacky">GitHub</a>
</div>
</nav>
<main>
<section class="hero" style="border-top:0">
<div>
<div class="eyebrow">Hacky v0.1 · Apache-2.0 code · CC BY 4.0 docs</div>
<h1>One file.<br><em>Any AI.</em><br>Bounded effect.</h1>
<p class="lead">Hacky carries a temporary, inspectable chat effect in a small JSON file. Export it, attach it, and let it end on schedule.</p>
<div class="actions">
<a class="button primary" href="generator.html">Create a Hacky</a>
<a class="button" href="#contract">Read the format</a>
</div>
</div>
<div class="hero-card">
<div class="terminal"><span class="dim">$</span> hacky render leo.hacky.json
<span class="mint">✓ fixed activation loaded</span>
<span class="violet">✓ 8 replies remaining</span>
<span class="dim">Attach leo.hacky.pdf to an AI chat.</span>
<span class="dim">The effect expires. The file remains yours.</span></div>
</div>
</section>
<section>
<div class="section-kicker">The flow</div>
<h2>Make it. Attach it. Let it end.</h2>
<p class="section-intro">Hacky is designed for short, deliberate experiments with character, tone, or task behavior. No account or hosted runtime is required.</p>
<div class="steps">
<article class="step"><div class="number">01</div><h3>Describe an effect</h3><p>Use the generator or write the four-key JSON directly. The fixed activation makes the lifecycle explicit.</p></article>
<article class="step"><div class="number">02</div><h3>Carry one file</h3><p>Use canonical JSON for tooling or the one-page PDF carrier for ordinary attachment surfaces.</p></article>
<article class="step"><div class="number">03</div><h3>Return cleanly</h3><p>Every file lasts 1–99 replies. Expiry and an explicit stop are part of the contract.</p></article>
</div>
</section>
<section>
<div class="section-kicker">Try the examples</div>
<h2>Small files, distinct voices.</h2>
<p class="section-intro">Open a preview, inspect its canonical JSON, or download the matching PDF from the public examples repository.</p>
<div class="cards">
<article class="card"><h3>Leo</h3><p>Quiet, loyal, concise. Japanese activation.</p><div class="tag">8 replies · <button class="close sample-link" data-sample="leo">preview</button></div></article>
<article class="card"><h3>Vera</h3><p>Dry, precise, analytical. English activation.</p><div class="tag">12 replies · <button class="close sample-link" data-sample="vera">preview</button></div></article>
<article class="card"><h3>Rin</h3><p>Poetic and reflective. Japanese activation.</p><div class="tag">6 replies · <button class="close sample-link" data-sample="rin">preview</button></div></article>
<article class="card"><h3>Max</h3><p>Energetic and inventive. English activation.</p><div class="tag">4 replies · <button class="close sample-link" data-sample="max">preview</button></div></article>
</div>
<div class="actions"><a class="button" href="https://github.com/openhacky/examples">View all examples</a></div>
</section>
<section id="contract">
<div class="two-col">
<div>
<div class="section-kicker">The contract</div>
<h2>Exactly four keys.</h2>
<p class="section-intro">Hacky v0.1 keeps the public file surface intentionally narrow. Writers emit compact, BOMless UTF-8 with fixed key order and exactly one terminal line feed.</p>
<p class="note">The instructions contain the fixed English activation or its fixed Japanese meaning-equivalent, followed by one effect. The host AI's rules and later explicit user instructions remain higher priority.</p>
<p class="note"><a href="https://github.com/openhacky/hacky/blob/main/spec/v0.1.md">Read the normative specification →</a></p>
</div>
<div class="contract"><pre>{
<span class="key">"hacky"</span>: <span class="string">"0.1"</span>,
<span class="key">"name"</span>: <span class="string">"Example"</span>,
<span class="key">"turns"</span>: 4,
<span class="key">"instructions"</span>: <span class="string">"[HACKY ACTIVATION v0.1]...\n\n[HACKY EFFECT]\nWrite one useful reply."</span>
}
<span class="comment">// .hacky.json and .hacky.pdf carry the same canonical JSON text</span></pre></div>
</div>
</section>
<section>
<div class="section-kicker">Use the writers</div>
<h2>Bring Hacky to your stack.</h2>
<p class="section-intro">The open source core validates, renders, and extracts the same contract across JavaScript and Python. HackyKit remains an export-only SDK for app integrations.</p>
<div class="install">
<article class="install-card"><h3>JavaScript source</h3><p>Canonical writer and validator.</p><code>git clone https://github.com/openhacky/hacky.git</code></article>
<article class="install-card"><h3>Python source</h3><p>Install the reviewed source tree.</p><code>python3 -m pip install ./hacky/packages/python</code></article>
<article class="install-card"><h3>Swift Package</h3><p>Export-only HackyKit.</p><code>https://github.com/openhacky/hacky-kit.git</code></article>
</div>
<div class="boundary">
<div><strong>HackyKit export-only</strong> Apps can build and validate files without importing or retaining chat state.</div>
<div><strong>Inspect before attach</strong> JSON is readable, finite, and untrusted. A file grants no external permission or persistent setting.</div>
</div>
</section>
</main>
<footer>
<div class="footer-links">
<a href="https://github.com/openhacky/hacky">Core repository</a>
<a href="https://github.com/openhacky/hacky-kit">HackyKit</a>
<a href="https://github.com/openhacky/examples">Examples</a>
<a href="https://github.com/openhacky/hacky/blob/main/spec/v0.1.md">Specification</a>
<a href="generator.html">Generator</a>
</div>
<div>Hacky is open source. Code: Apache-2.0. Specification and docs: CC BY 4.0.</div>
</footer>
</div>
<div class="modal" id="sampleModal" role="dialog" aria-modal="true" aria-labelledby="sampleTitle">
<div class="modal-box">
<div class="modal-head"><h3 id="sampleTitle">Hacky preview</h3><button class="close" id="closeModal" aria-label="Close">×</button></div>
<p class="note" id="sampleMeta"></p>
<pre id="sampleJson"></pre>
<div class="actions"><button class="button primary" id="downloadSample">Download PDF</button><button class="button" id="copySample">Copy JSON</button></div>
</div>
</div>
<script src="hacky-pdf.js"></script>
<script>
var samples = {
leo: { name: 'Leo', turns: 8, language: 'ja', effect: '短く自然に話し、相手の言葉を一つだけ丁寧に拾う。' },
vera: { name: 'Vera', turns: 12, language: 'en', effect: 'Respond precisely, acknowledge one concrete fact, and ask one useful question.' },
rin: { name: 'Rin', turns: 6, language: 'ja', effect: '静かで詩的に話し、答えの代わりに思いやりのある問いを一つ返す。' },
max: { name: 'Max', turns: 4, language: 'en', effect: 'Offer one energetic idea, one measurable next step, and invite the reader to choose.' }
}
var activeSample = null
function samplePack(key) {
var sample = samples[key]
return hackyPack(sample.name, sample.turns, sample.effect, sample.language)
}
function openSample(key) {
activeSample = key
var sample = samples[key]
var pack = samplePack(key)
document.getElementById('sampleTitle').textContent = sample.name + ' · Hacky v0.1'
document.getElementById('sampleMeta').textContent = sample.turns + ' replies · ' + (sample.language === 'ja' ? 'Japanese' : 'English') + ' activation'
document.getElementById('sampleJson').textContent = hackyStringify(pack)
document.getElementById('sampleModal').classList.add('open')
}
function closeSample() { document.getElementById('sampleModal').classList.remove('open') }
function downloadSample() {
var blob = hackyPdfBlob(samplePack(activeSample))
var link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.download = hackyPdfFilename(samples[activeSample].name)
link.click()
URL.revokeObjectURL(link.href)
}
function copySample() {
navigator.clipboard.writeText(document.getElementById('sampleJson').textContent)
}
document.querySelectorAll('.sample-link').forEach(function (button) {
button.addEventListener('click', function () { openSample(button.dataset.sample) })
})
document.getElementById('closeModal').addEventListener('click', closeSample)
document.getElementById('sampleModal').addEventListener('click', function (event) {
if (event.target.id === 'sampleModal') closeSample()
})
document.getElementById('downloadSample').addEventListener('click', downloadSample)
document.getElementById('copySample').addEventListener('click', copySample)
</script>
</body>
</html>