1 | <!DOCTYPE html>
|
2 | <html>
|
3 | <head>
|
4 | <title>gun - the open source, real-time, fully decentralized, offline-first, graph database</title>
|
5 | <meta name="viewport" content="width=device-width, initial-scale=1">
|
6 | <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
|
7 | <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.3/jquery.easing.min.js"></script>
|
8 | </head>
|
9 | <body>
|
10 | <style>
|
11 | @import url(https://fonts.googleapis.com/css?family=Dosis|Poiret+One|Oxygen);
|
12 | html, body {
|
13 | margin: 0;
|
14 | padding: 0;
|
15 | height: 100%;
|
16 | font-family: 'Oxygen', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
|
17 | }
|
18 | .center {
|
19 | text-align: center;
|
20 | }
|
21 | .lean {
|
22 | font-family: 'Poiret One', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
|
23 | }
|
24 | .clean {
|
25 | font-family: 'Dosis', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
|
26 | }
|
27 | .crisp {
|
28 | font-family: 'Oxygen', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
|
29 | }
|
30 | .svg {
|
31 | background: white url('./web/img/devices.svg') no-repeat 50% 50%;
|
32 | height: 40em;
|
33 | }
|
34 | .GUN {
|
35 | background: transparent url('./web/img/gun.svg') no-repeat 50% 50%;
|
36 | background-size: 60%;
|
37 | }
|
38 | .dull {
|
39 | background-color: #EEE;
|
40 | -webkit-transition: background-color 600ms linear;
|
41 | -moz-transition: background-color 600ms linear;
|
42 | transition: background-color 600ms linear;
|
43 | }
|
44 | .blue {
|
45 | background-color: skyblue;
|
46 | -webkit-transition: background-color 600ms linear;
|
47 | -moz-transition: background-color 600ms linear;
|
48 | transition: background-color 600ms linear;
|
49 | }
|
50 | .red {
|
51 | background-color: red;
|
52 | -webkit-transition: background-color 600ms linear;
|
53 | -moz-transition: background-color 600ms linear;
|
54 | transition: background-color 600ms linear;
|
55 | }
|
56 | .green {
|
57 | background-color: MediumSpringGreen;
|
58 | -webkit-transition: background-color 600ms linear;
|
59 | -moz-transition: background-color 600ms linear;
|
60 | transition: background-color 600ms linear;
|
61 | }
|
62 | .fold {
|
63 | width: 100%;
|
64 | position: relative;
|
65 | overflow: hidden;
|
66 | }
|
67 | .behold {
|
68 | margin-top: 8%;
|
69 | padding:0;
|
70 | text-align: center;
|
71 | }
|
72 | .grid {
|
73 | display: inline-block;
|
74 | }
|
75 | @media (max-width: 760px) {
|
76 | body {
|
77 | font-size: 8pt;
|
78 | }
|
79 | }
|
80 | @media (max-width: 1279px) {
|
81 | .wide {
|
82 | display: none;
|
83 | }
|
84 | }
|
85 |
|
86 | .screen {
|
87 | position: relative;
|
88 | overflow: hidden;
|
89 | }
|
90 | .mouse {
|
91 | display: block;
|
92 | position: absolute;
|
93 | top: 60%;
|
94 | left: -6%;
|
95 | }
|
96 | </style>
|
97 |
|
98 | <div class="fold">
|
99 |
|
100 | <div class="behold">
|
101 |
|
102 | <div class="graphic grid" style="min-width: 300px; max-width: 600px; height: 400px; position: relative; margin:0 auto; padding:0;">
|
103 |
|
104 | <img src="./web/img/server.png" class="server" style="position: absolute; top: 2%; left: 35%; wid-th: 50%;">
|
105 |
|
106 | <div class="desktop" style="height: 10em; width: 17em; position: absolute; top: 36%; left: 3%;">
|
107 | <div class="monitor" style="height: 100%; width: 100%; background: #222; padding: .75em; margin-left: -.75em; border-radius: 1em;">
|
108 | <div class="dull screen GUN" style="height: 100%; width: 100%;">
|
109 | <img class="mouse" src="./web/img/mouse.png">
|
110 | </div>
|
111 | </div>
|
112 | <div class="stand" style="margin: 1px auto 0px;
|
113 | border-bottom: 2.75em solid #888;
|
114 | border-left: .5em solid transparent;
|
115 | border-right: .5em solid transparent;
|
116 | height: 0;
|
117 | width: 3.2em;">
|
118 | </div>
|
119 | <div class="stand" style="width: 6em; height: .5em; background: #888; margin: 0px auto"></div>
|
120 | </div>
|
121 |
|
122 | <div class="laptop" style="height: 7em; width: 12em; position: absolute; top: 60%; left: 48%;">
|
123 | <div class="lid" style="height: 100%; width: 100%; background: #222; padding: .6em; margin-left: -.6em; border-radius: .6em .6em 0em 0em;">
|
124 | <div class="dull screen GUN" style="height: 100%; width: 100%;">
|
125 | </div>
|
126 | </div>
|
127 | <div class="case" style="height: .75em; width: 140%; margin-left: -20%; background: #999; border-radius: 0em 0em 5em 5em;">
|
128 | </div>
|
129 | </div>
|
130 |
|
131 | <div class="phone" style="height: 3.75em; width: 2.25em; position: absolute; top: 35%; left: 70%;">
|
132 | <div class="case" style="height: 100%; width: 100%; background: #222; padding: .5em .2em; margin-left: -.2em; border-radius: 0.25em;">
|
133 | <div class="dull screen GUN" style="height: 100%; width: 100%;">
|
134 | </div>
|
135 | </div>
|
136 | </div>
|
137 |
|
138 | <div class="arrow desktop-server" style="width: 52px; height: 52px; border: dashed 0px FireBrick; border-radius: 50px 0 0 0;
|
139 | position: absolute; left: 20%; top: 15%; border-width: 3px 0px 0px 3px;">
|
140 | <div class="rarr" style="position: absolute; top: -.59em; right: -.7em;
|
141 | width: 0;
|
142 | height: 0;
|
143 | border-top: .5em solid transparent;
|
144 | border-left: 1em solid FireBrick;
|
145 | border-bottom: .5em solid transparent;">
|
146 | </div>
|
147 | <div class="darr" style="position: absolute; bottom: -.75em; left: -.59em;
|
148 | width: 0;
|
149 | height: 0;
|
150 | border-left: .5em solid transparent;
|
151 | border-right: .5em solid transparent;
|
152 | border-top: 1em solid FireBrick;">
|
153 | </div>
|
154 | </div>
|
155 |
|
156 | <div class="arrow phone-server" style="width: 26px; height: 52px; border: dashed 0px FireBrick; border-radius: 0 0 50px 0;
|
157 | position: absolute; left: 80%; top: 35%; border-width: 0px 3px 3px 0px;">
|
158 | <div class="uarr" style="position: absolute; top: -.9em; right: -.59em;
|
159 | width: 0;
|
160 | height: 0;
|
161 | border-left: .5em solid transparent;
|
162 | border-right: .5em solid transparent;
|
163 | border-bottom: 1em solid FireBrick;">
|
164 | </div>
|
165 | <div class="larr" style="position: absolute; bottom: -.55em; left: -.59em;
|
166 | width: 0;
|
167 | height: 0;
|
168 | border-top: .5em solid transparent;
|
169 | border-right: 1em solid FireBrick;
|
170 | border-bottom: .5em solid transparent;">
|
171 | </div>
|
172 | </div>
|
173 |
|
174 | <div class="arrow updown laptop-server" style="height: 50px; border: dashed 0px FireBrick; border-radius: 0;
|
175 | position: absolute; left: 60%; top: 40%; border-width: 0px 3px 0px 0px;">
|
176 | <div class="uarr" style="position: absolute; top: -1em; left: -.45em;
|
177 | width: 0;
|
178 | height: 0;
|
179 | border-left: .5em solid transparent;
|
180 | border-right: .5em solid transparent;
|
181 | border-bottom: 1em solid FireBrick;">
|
182 | </div>
|
183 | <div class="darr" style="position: absolute; bottom: -1em; left: -.45em;
|
184 | width: 0;
|
185 | height: 0;
|
186 | border-left: .5em solid transparent;
|
187 | border-right: .5em solid transparent;
|
188 | border-top: 1em solid FireBrick;">
|
189 | </div>
|
190 | </div>
|
191 |
|
192 | <span style="color: transparent">Distributed embedded graph database engine. The no pain, no cost, no backend, NoDB database, gun.</span>
|
193 | </div>
|
194 |
|
195 | <div class="graphic wide grid" style="min-width: 300px; max-width: 600px; height: 400px;
|
196 | position: relative; margin:0 auto; padding:0;">
|
197 |
|
198 | <div class="arrow server-server" style="width: 100px; height: 0px; border: dashed 0px FireBrick; border-radius: 0;
|
199 | position: absolute; left: -9%; top: 15%; border-width: 3px 0px 0px 0px;">
|
200 | <div class="rarr" style="position: absolute; top: -.59em; left: -.5em;
|
201 | width: 0;
|
202 | height: 0;
|
203 | border-top: .5em solid transparent;
|
204 | border-right: 1em solid FireBrick;
|
205 | border-bottom: .5em solid transparent;">
|
206 | </div>
|
207 | <div class="larr" style="position: absolute; top: -.59em; right: -.6em;
|
208 | width: 0;
|
209 | height: 0;
|
210 | border-left: 1em solid FireBrick;
|
211 | border-bottom: .5em solid transparent;
|
212 | border-top: .5em solid transparent;">
|
213 | </div>
|
214 | </div>
|
215 |
|
216 | <img src="./web/img/server.png" class="server" style="position: absolute; top: 2%; right: 35%;">
|
217 |
|
218 | <div class="desktop" style="height: 10em; width: 17em; position: absolute; top: 36%; right: 3%;">
|
219 | <div class="monitor" style="height: 100%; width: 100%; background: #222; padding: .75em; margin-left: -.75em; border-radius: 1em;">
|
220 | <div class="dull screen GUN" style="height: 100%; width: 100%;">
|
221 | </div>
|
222 | </div>
|
223 | <div class="stand" style="margin: 1px auto 0px;
|
224 | border-bottom: 2.75em solid #888;
|
225 | border-left: .5em solid transparent;
|
226 | border-right: .5em solid transparent;
|
227 | height: 0;
|
228 | width: 3.2em;">
|
229 | </div>
|
230 | <div class="stand" style="width: 6em; height: .5em; background: #888; margin: 0px auto"></div>
|
231 | </div>
|
232 |
|
233 | <div class="laptop" style="height: 7em; width: 12em; position: absolute; top: 60%; right: 48%;">
|
234 | <div class="lid" style="height: 100%; width: 100%; background: #222; padding: .6em; margin-left: -.6em; border-radius: .6em .6em 0em 0em;">
|
235 | <div class="dull screen GUN" style="height: 100%; width: 100%;">
|
236 | </div>
|
237 | </div>
|
238 | <div class="case" style="height: .75em; width: 140%; margin-left: -20%; background: #999; border-radius: 0em 0em 5em 5em;">
|
239 | </div>
|
240 | </div>
|
241 |
|
242 | <div class="phone" style="height: 3.75em; width: 2.25em; position: absolute; top: 35%; right: 70%;">
|
243 | <div class="case" style="height: 100%; width: 100%; background: #222; padding: .5em .2em; margin-left: -.2em; border-radius: 0.25em;">
|
244 | <div class="dull screen GUN" style="height: 100%; width: 100%;">
|
245 | </div>
|
246 | </div>
|
247 | </div>
|
248 |
|
249 | <div class="arrow desktop-server" style="width: 52px; height: 52px; border: dashed 0px FireBrick; border-radius: 0 50px 0 0;
|
250 | position: absolute; right: 20%; top: 15%; border-width: 3px 3px 0px 0px;">
|
251 | <div class="rarr" style="position: absolute; top: -.59em; left: -.5em;
|
252 | width: 0;
|
253 | height: 0;
|
254 | border-top: .5em solid transparent;
|
255 | border-right: 1em solid FireBrick;
|
256 | border-bottom: .5em solid transparent;">
|
257 | </div>
|
258 | <div class="darr" style="position: absolute; bottom: -.75em; right: -.59em;
|
259 | width: 0;
|
260 | height: 0;
|
261 | border-left: .5em solid transparent;
|
262 | border-right: .5em solid transparent;
|
263 | border-top: 1em solid FireBrick;">
|
264 | </div>
|
265 | </div>
|
266 |
|
267 |
|
268 | <div class="arrow phone-server" style="width: 26px; height: 52px; border: dashed 0px FireBrick; border-radius: 0 0 0px 50px;
|
269 | position: absolute; right: 80.3%; top: 34.3%; border-width: 0px 0px 3px 3px;">
|
270 | <div class="uarr" style="position: absolute; top: -.8em; left: -.59em;
|
271 | width: 0;
|
272 | height: 0;
|
273 | border-left: .5em solid transparent;
|
274 | border-right: .5em solid transparent;
|
275 | border-bottom: 1em solid FireBrick;">
|
276 | </div>
|
277 | <div class="rarr" style="position: absolute; bottom: -.55em; right: -.7em;
|
278 | width: 0;
|
279 | height: 0;
|
280 | border-top: .5em solid transparent;
|
281 | border-left: 1em solid FireBrick;
|
282 | border-bottom: .5em solid transparent;">
|
283 | </div>
|
284 | </div>
|
285 |
|
286 | <div class="arrow updown laptop-server" style="height: 50px; border: dashed 0px FireBrick; border-radius: 0;
|
287 | position: absolute; right: 60%; top: 40%; border-width: 0px 3px 0px 0px;">
|
288 | <div class="uarr" style="position: absolute; top: -1em; left: -.45em;
|
289 | width: 0;
|
290 | height: 0;
|
291 | border-left: .5em solid transparent;
|
292 | border-right: .5em solid transparent;
|
293 | border-bottom: 1em solid FireBrick;">
|
294 | </div>
|
295 | <div class="darr" style="position: absolute; bottom: -1em; left: -.45em;
|
296 | width: 0;
|
297 | height: 0;
|
298 | border-left: .5em solid transparent;
|
299 | border-right: .5em solid transparent;
|
300 | border-top: 1em solid FireBrick;">
|
301 | </div>
|
302 | </div>
|
303 |
|
304 | <span style="color: transparent">Distributed embedded graph database engine. The no pain, no cost, no backend, NoDB database, gun.</span>
|
305 | </div>
|
306 |
|
307 | <script>
|
308 | $(function(){
|
309 | var c = ['dull', 'blue', 'green']
|
310 | , a = 'dull blue red green', n = 0, to;
|
311 | $(".screen").click(function(){
|
312 | c.push(c.shift());
|
313 | to = to || c[0];
|
314 | $(this).removeClass(a).addClass(to);
|
315 | $('.screen').not(this).each(function(){
|
316 | var t = $(this); n++;
|
317 | setTimeout(function(){
|
318 | t.removeClass(a).addClass(to);
|
319 | if(!(--n)){ to = null }
|
320 | }, rand(400,700));
|
321 | });
|
322 | });
|
323 | function rand(min, max) {
|
324 | return Math.floor(Math.random() * (max - min + 1)) + min;
|
325 | }
|
326 | });
|
327 | </script>
|
328 | <script>
|
329 | $(function(){
|
330 | var mouse = $('.mouse');
|
331 | function show(i){
|
332 | function to(){
|
333 | mouse.animate({top: "60%", left: "55%"}, {
|
334 | duration: 500,
|
335 | specialEasing: {top: 'easeInQuad', left: 'easeOutQuad'},
|
336 | complete: click
|
337 | });
|
338 | }
|
339 | function click(){
|
340 | mouse.delay(230).animate({width: mouse.width() / 2}, {
|
341 | duration: 60,
|
342 | complete: function(){
|
343 | mouse.closest('.screen').trigger('click');
|
344 | mouse.animate({width: mouse.width() * 2}, {
|
345 | duration: 120,
|
346 | complete: fro
|
347 | });
|
348 | }
|
349 | });
|
350 | }
|
351 | function fro(){
|
352 | mouse.delay(900).animate({top: "87%", left: "110%"}, {
|
353 | duration: 700,
|
354 | specialEasing: {top: 'easeOutQuad', left: 'easeInQuad'},
|
355 | complete: function(){
|
356 | setTimeout(show, 4 * 1000);
|
357 | }
|
358 | });
|
359 | }
|
360 | if(!i && $('.graphic').filter(function() { return $(this).is(":hover"); }).length){
|
361 | setTimeout(show, 2000);
|
362 | } else {
|
363 | to();
|
364 | }
|
365 | };
|
366 | mouse.delay(1200).animate({top: "70%", left: "20%"}, {
|
367 | duration: 400,
|
368 | specialEasing: {top: 'easeOutQuad', left: 'easeInQuad'},
|
369 | complete: function(){ show(true) }
|
370 | });
|
371 | });
|
372 | </script>
|
373 |
|
374 | <div class="center" style="margin: 2% 0;">
|
375 | <div class="lean" style="font-size: 400%;">Easiest Database Ever</div>
|
376 | <div class="lean" style="font-size: 225%;">Sync state in a cinch at a distributed system scale.</div>
|
377 | </div>
|
378 |
|
379 | </div>
|
380 |
|
381 | </div>
|
382 | <a href="https://github.com/amark/gun" target="_blank"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/365986a132ccd6a44c23a9169022c0b5c890c387/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f7265645f6161303030302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png"></a>
|
383 |
|
384 | <script type="text/javascript">
|
385 | window.heap=window.heap||[],heap.load=function(t,e){window.heap.appid=t,window.heap.config=e;var a=document.createElement("script");a.type="text/javascript",a.async=!0,a.src=("https:"===document.location.protocol?"https:":"http:")+"//cdn.heapanalytics.com/js/heap-"+t+".js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(a,n);for(var o=function(t){return function(){heap.push([t].concat(Array.prototype.slice.call(arguments,0)))}},p=["clearEventProperties","identify","setEventProperties","track","unsetEventProperty"],c=0;c<p.length;c++)heap[p[c]]=o(p[c])};
|
386 | heap.load("2174172773");
|
387 | </script>
|
388 |
|
389 |
|
390 |
|
391 |
|
392 |
|
393 |
|
394 |
|
395 |
|
396 |
|
397 | <div class="tutorial">
|
398 | <script src="https://gunjs.herokuapp.com/gun.js"></script>
|
399 | <link id="style" rel="stylesheet" href="https://yandex.st/highlightjs/8.0/styles/ir_black.min.css">
|
400 | <script src="https://yandex.st/highlightjs/8.0/highlight.min.js"></script>
|
401 | <style>
|
402 | @import url(https://fonts.googleapis.com/css?family=Dosis|Poiret+One|Oxygen);
|
403 | .tutorial {
|
404 | margin: 0;
|
405 | padding: 0;
|
406 | he-ight: 100%;
|
407 | font-family: 'Oxygen', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
|
408 | background: #222;
|
409 | color: #eee;
|
410 | overflow: auto;
|
411 | }
|
412 | .center {
|
413 | text-align: center;
|
414 | }
|
415 | .lean {
|
416 | font-family: 'Poiret One', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
|
417 | }
|
418 | .clean {
|
419 | font-family: 'Dosis', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
|
420 | }
|
421 | .crisp {
|
422 | font-family: 'Oxygen', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
|
423 | }
|
424 | pre {
|
425 | background-color: black;
|
426 | border: 1px dashed white;
|
427 | color: white;
|
428 | line-height: 1.5em;
|
429 | padding: .5em;
|
430 | margin: 0em;
|
431 | overflow: auto;
|
432 | }
|
433 | button {
|
434 | border: none;
|
435 | color: white;
|
436 | background: skyblue;
|
437 | padding: 1em;
|
438 | cursor: pointer;
|
439 | }
|
440 | .hide {
|
441 | display: none;
|
442 | }
|
443 | .show {
|
444 | display: block;
|
445 | }
|
446 | .grid {
|
447 | text-align: center;
|
448 | }
|
449 | .unit {
|
450 | display: inline-block;
|
451 | }
|
452 | .main {
|
453 | min-width: 250px;
|
454 | max-width: 1024px;
|
455 | width: 90%;
|
456 | margin: 0% auto;
|
457 | padding: 2% 5%;
|
458 | }
|
459 | div {
|
460 | position: relative;
|
461 | }
|
462 | .left { float: left;}
|
463 | .teft { text-align: left; }
|
464 | .middle {
|
465 | vertical-align: middle;
|
466 | }
|
467 | .full {
|
468 | width: 100%;
|
469 | }
|
470 | </style>
|
471 | <div class="main">
|
472 | <div style="font-size: 18pt; margin: 0 0 .75em;">Try it now</div>
|
473 |
|
474 | <div class="step show step1">
|
475 |
|
476 | <div class="full grid">
|
477 | <div class="middle unit teft">
|
478 | <pre style="max-width: 30.1em; margin: 0 1em 1em 0;">var gun = Gun('https://gunjs.herokuapp.com/gun');
|
479 | gun.put({hello: "world"}).key('<span class="your-key">example/tutorial</span>');</pre>
|
480 | </div>
|
481 | <div class="middle unit teft" style="min-width: 20em; max-width: 28em; margin-bottom: 1em;">
|
482 | <a href="#step2"><button class="left" style="margin-right: 1em;"><big>Run!</big></button></a>
|
483 | In this <b>1 minute</b> tutorial, we will connect to a gun peer, create an object, and sync data in realtime.
|
484 | </div>
|
485 | </div>
|
486 |
|
487 | </div>
|
488 |
|
489 | <div class="step hide step2">
|
490 |
|
491 | <div class="full grid">
|
492 | <div class="middle unit teft">
|
493 | <pre style="max-width: 30.1em; margin: 0 1em 1em 0;">var ref = gun.get('<span class="your-key">example/tutorial</span>');
|
494 | ref.on(function(data){
|
495 | $('body').text(JSON.stringify(data));
|
496 | });</pre>
|
497 | </div>
|
498 | <div class="middle unit teft" style="min-width: 34em; max-width: 28em; margin-bottom: 1em;">
|
499 | <a href="#step3"><button class="left" style="margin-right: 1em; background: MediumSpringGreen;"><big>Next</big></button></a>
|
500 | Congratulations! You just made an object and saved a reference to it.
|
501 | In two tabs, we'll load that key to open a shared reference.
|
502 | </div>
|
503 | </div>
|
504 |
|
505 | </div>
|
506 |
|
507 |
|
508 | <div class="step hide step3">
|
509 |
|
510 | <div class="full grid">
|
511 | <style>
|
512 | .browser {
|
513 | background: white;
|
514 | border-radius: .25em;
|
515 | width: 250px;
|
516 | //height: 300px;
|
517 | color: #222;
|
518 | margin: .5em;
|
519 | overflow: hidden;
|
520 | }
|
521 | .b-bar {
|
522 | background: #EEE;
|
523 | border-radius: .25em .25em 0 0;
|
524 | }
|
525 | .b-but {
|
526 | float: left;
|
527 | width: 1em;
|
528 | height: 1em;
|
529 | }
|
530 | .browser a {
|
531 | text-decoration: none;
|
532 | background: white;
|
533 | border-radius: .4em;
|
534 | padding: 0 1em;
|
535 | color: #555;
|
536 | }
|
537 | .browser iframe { border: none; }
|
538 | </style>
|
539 | <div class="browser unit teft">
|
540 | <div class="b-bar">
|
541 | <div class="b-but">←</div>
|
542 | <div class="b-but">→</div>
|
543 | <div class="b-but"><small>↻</small></div>
|
544 | <small><small><span>
|
545 | <a href="https://gunjs.herokuapp.com/" target="_blank">https://gunjs.herokuapp.com/</a>
|
546 | </span></small></small>
|
547 | <small class="center" style="position: relative; top: -.14em;">x</small>
|
548 | <span class="center">≡<span>
|
549 | </div>
|
550 | <iframe></iframe>
|
551 | </div>
|
552 | <div class="browser unit teft">
|
553 | <div class="b-bar">
|
554 | <div class="b-but">←</div>
|
555 | <div class="b-but">→</div>
|
556 | <div class="b-but"><small>↻</small></div>
|
557 | <small><small><span>
|
558 | <a href="https://gunjs.herokuapp.com/" target="_blank">https://gunjs.herokuapp.com/</a>
|
559 | </span></small></small>
|
560 | <small class="center" style="position: relative; top: -.14em;">x</small>
|
561 | <span class="center">≡<span>
|
562 | </div>
|
563 | <iframe></iframe>
|
564 | </div>
|
565 | </div>
|
566 |
|
567 | <form action="#step3" onsubmit="return false;">
|
568 | <style>
|
569 | .step3 input {
|
570 | width: 6em;
|
571 | }
|
572 | </style>
|
573 | <div class="grid">
|
574 | <div class="middle unit teft">
|
575 | <pre style="max-width: 40em; margin: 0 1em 1em 0;">ref.path('<input id="try-path" value="hello">').put("<input id="try-sync" value="sync">");</pre>
|
576 | </div>
|
577 | <div class="middle unit teft" style="min-width: 20em; max-width: 30em; margin-bottom: 1em;">
|
578 | <button type="submit" class="left" style="margin-right: 1em;"><big>Update!</big></button>
|
579 | Let's update the "hello" field with a different value.
|
580 | We can path into any field, and update it directly.
|
581 | </div>
|
582 | </div>
|
583 | </form>
|
584 |
|
585 | </div>
|
586 |
|
587 | <script>
|
588 | $(function(){
|
589 | var gun, key = "random/" + Gun.text.random(9),
|
590 | hili = function(){
|
591 | $("pre").each(function(){
|
592 | hljs.highlightBlock(this);
|
593 | })
|
594 | }
|
595 | $(".your-key").text(key);
|
596 | hili();
|
597 |
|
598 | location.hash = 'step1';
|
599 | $(window).on('hashchange', function(){
|
600 | $('.step').removeClass('show').addClass('hide')
|
601 | $(location.hash.replace('#','.')).addClass('show');
|
602 | });
|
603 |
|
604 | $(".step1").find('button').on('click', function(e){
|
605 | if(gun){ return }
|
606 | gun = Gun('https://gunjs.herokuapp.com/gun');
|
607 | gun.put({hello: "world"}).key(key);
|
608 | });
|
609 | $(".step2").find('button').on('click', function(e){
|
610 | $(".browser").find("iframe").attr("src", "./web/tabs.html?key=" + key);
|
611 | });
|
612 | $(".step3").find('form').on('submit', function(e){
|
613 | var val = $("#try-sync").val() || null;
|
614 | var path = $("#try-path").val();
|
615 | gun.get(key).path(path).put(val);
|
616 | });
|
617 | })
|
618 | </script>
|
619 | </div>
|
620 | </div>
|
621 |
|
622 |
|
623 |
|
624 | <! OLD BLOG POST HERE -->
|
625 |
|
626 | <style>
|
627 | #main {
|
628 | min-width: 250px;
|
629 | max-width: 700px;
|
630 | width: 75%;
|
631 | margin: 7% auto;
|
632 | padding: 2% 5%;
|
633 | background: white;
|
634 | background: rgba(100%,100%,100%,.6);
|
635 | font-family: Arial;
|
636 | font-size: 18pt;
|
637 | text-shadow: 0px 0px 7px #DDD;
|
638 | line-height: 20pt;
|
639 | }
|
640 | #main p {
|
641 | text-indent: 2em;
|
642 | }
|
643 | </style>
|
644 | <div id="main">
|
645 |
|
646 | <h3>The blog that started it all...</h3>
|
647 | <p>
|
648 | Gun is a persisted distributed cache, part of a NoDB movement.
|
649 | It requires zero maintenance and runs on your own infrastructure.
|
650 | Think of it as <i>"Dropbox for Databases"</i> or a <i>"Self-hosted Firebase"</i>.
|
651 | This is an early preview, so check out the <a href="https://github.com/amark/gun" target="_blank">github</a> and read on.
|
652 | </p>
|
653 | <p>
|
654 | Everything gets cached, so your users experience lightning fast response times.
|
655 | Since gun can be embedded anywhere javascript can run,
|
656 | that cache can optionally be right inside your user's browser using localstorage fallbacks.
|
657 | Updates are then pushed up to the servers when the network is available.
|
658 | </p>
|
659 | <p>
|
660 | All conflict resolution happens locally in each peer using a deterministic algorithm.
|
661 | Such that eventual consistency is guaranteed across all writes within the mesh,
|
662 | with fault tolerant retries built in at each step for at least once deliveries.
|
663 | Data integrity is now a breeze.
|
664 | </p>
|
665 | <p>
|
666 | Gun also establishes and repairs server to server communication across geographically separated machines,
|
667 | with just the help of an initial IP from you.
|
668 | It bridges the distance with a realtime connection,
|
669 | so updates propagate at the speed of the raw pipes linking them.
|
670 | However each server is intelligent enough to only subscribe to the necessary subsection of your data set that is in its working memory,
|
671 | keeping things nimble for its connected users.
|
672 | </p>
|
673 | <p>
|
674 | Data is then persisted to any S3 like service,
|
675 | allowing you to save a truly webscale amount of "big data" without breaking your wallet.
|
676 | Consistency across concurrency is achieved at this layer
|
677 | by each parallel snapshot going through an idempotent transformation that is agreed upon.
|
678 | The granularity and frequency of these snapshots can be tweaked by you,
|
679 | easily tailor fitting it to your data needs and budget concerns.
|
680 | </p>
|
681 | <p>
|
682 | <b>In summary,</b> this marks an important progression in web technologies.
|
683 | Memory is getting cheap enough that we can now front load each connected user's active data
|
684 | right into the application layer and manipulate it directly.
|
685 | Networks are fast enough that if we get too many connected users we can just horizontally
|
686 | redistribute them across different machines.
|
687 | Conflict resolution algorithms are sophisticated enough to handle things immediately
|
688 | in the majority of data cases, with the remaining few as transactions performed ontop.
|
689 | <p>
|
690 | This is will be a win for both developers and users,
|
691 | because it makes things easier to build and faster to respond.
|
692 | We are excited about this and working hard to finish the first release.
|
693 | </p>
|
694 | <p>
|
695 | If you would like to learn more, email <a href="mailto:hi@gunDB.io">hi@gunDB.io</a> -
|
696 | or join the <a href="http://groups.google.com/forum/#!forum/g-u-n" target="_blank">Google Group</a>.
|
697 | Plus we're hiring, so contact us!
|
698 | </p>
|
699 | <h2>FAQ</h2>
|
700 | <h4>Why did you build this thing?</h4>
|
701 | <p>
|
702 | 1. I love databases, especially new ones that keep the working set in memory.
|
703 | But I was horrified to realize that if I use a Database as a Service (DaaS)
|
704 | then I would have to rely on a network call to get that data, which is horribly slow.
|
705 | I wanted something faster, and if possible, cheaper - because they start charging you
|
706 | outrageous prices if you get past their incredibly tiny free tier.
|
707 | </p>
|
708 | <p>
|
709 | 2. Hosting your own database is a pain because you have to maintain the hard drives.
|
710 | Even the basic setup and configuration is nasty...
|
711 | having to create a bunch of EBS volumes, attaching them, then mounting, formatting,
|
712 | MDADM and LVM, striping, mirroring, and keeping fstab from locking on boot.
|
713 | This is ignoring having to figure out how to resize them.
|
714 | Even with SSDs you have problems that they are bound to one instance and
|
715 | you get charged for the total volume size, not the amount used.
|
716 | </p>
|
717 | <p>
|
718 | I wanted something easy, needing no maintenance and be extremely portable
|
719 | - allowing me to spin up an ephemeral server anywhere, on any cloud,
|
720 | and my data "just work" there.
|
721 | </p>
|
722 | <h4>How are you different from every other database that is trying to reinvent the wheel?</h4>
|
723 | <p>
|
724 | 1. Because gun is not a database (NoDB), it is a persisted distributed cache.
|
725 | The fatal flaw with databases is that they assume some centralized authority.
|
726 | While this may be the case initially when you are small,
|
727 | it always ceases to be true when you become large enough that concurrency is unavoidable.
|
728 | No amount of leader election and consensus algorithms can patch this
|
729 | without facing an unjustified amount of complexity.
|
730 | Gun resolves all this by biting the bullet -
|
731 | it solves the hard problems first, not last.
|
732 | It gets data synchronization and conflict resolution right from the beginning,
|
733 | so it never has to rely on vulnerable leader election or consensus locking.
|
734 | </p>
|
735 | <p>
|
736 | 2. Plus it embeds directly into your application,
|
737 | so you can do your own custom queries with just pure programming logic.
|
738 | Meaning you never have to learn some silly separate query language again.
|
739 | A query language which just attempts to be some DSL to RPC another machine
|
740 | into doing the same query you could have already written in half the time
|
741 | it took to learn the query language. Because face it, any sufficiently capable
|
742 | query language has to be Turing complete, and at that point -
|
743 | why aren't you just writing your entire application logic in it?
|
744 | Your app is nothing without your data.
|
745 | </p>
|
746 | </div>
|
747 |
|
748 |
|
749 |
|
750 |
|
751 | </body>
|
752 | </html>
|