├── README.md
├── src
├── index.html
├── script.js
└── style.css
├── dist
├── index.html
├── script.js
└── style.css
└── LICENSE.txt
/README.md:
--------------------------------------------------------------------------------
1 | # Fireproof Homepage Demo
2 |
3 | A Pen created on CodePen.io. Original URL: [https://codepen.io/jchrisa/pen/bGOGvBz](https://codepen.io/jchrisa/pen/bGOGvBz).
4 |
5 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Fireproof Example
8 |
9 |
10 |
11 |
12 |
13 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CodePen - Fireproof Homepage Demo
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Fireproof Example
18 |
19 |
20 |
21 |
22 |
23 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2024 Chris Anderson (https://codepen.io/jchrisa/pen/bGOGvBz)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/dist/script.js:
--------------------------------------------------------------------------------
1 | db = connect("fireproof");
2 |
3 | function addItemDb(text) {
4 | db.put({
5 | text,
6 | done: false,
7 | created: Date.now()
8 | });
9 | }
10 |
11 | function addItem(e) {
12 | e.preventDefault();
13 | const input = document.querySelector("form input");
14 | if (!input.value) return;
15 | addItemDb(input.value);
16 | input.value = "";
17 | }
18 | window.addItem = addItem;
19 |
20 | function toggleDone(doc) {
21 | doc.done = !doc.done;
22 | doc.updated = Date.now();
23 | db.put(doc);
24 | }
25 |
26 | async function redraw() {
27 | const result = await db.query("created", {
28 | includeDocs: true,
29 | descending: true,
30 | limit: 10
31 | });
32 |
33 | document.querySelector("ul").innerHTML = "";
34 |
35 | for (const row of result.rows) {
36 | const textSpan = document.createElement("span");
37 | textSpan.innerText = row.doc.text;
38 |
39 | const checkbox = document.createElement("input");
40 | checkbox.onchange = () => {
41 | toggleDone(row.doc);
42 | };
43 | if (row.doc.done) {
44 | checkbox.setAttribute("checked", true);
45 | }
46 | checkbox.setAttribute("type", "checkbox");
47 |
48 | const deleteSpan = document.createElement("span");
49 | deleteSpan.innerText = "x";
50 | deleteSpan.style = "text-align:right; color:#999";
51 | deleteSpan.onclick = function (e) {
52 | e.preventDefault();
53 | db.del(row.id);
54 | if (result.rows.length <= 1) reset();
55 | };
56 |
57 | const li = document.createElement("li");
58 | li.appendChild(checkbox);
59 | li.appendChild(textSpan);
60 | li.appendChild(deleteSpan);
61 |
62 | document.querySelector("ul").appendChild(li);
63 | }
64 | }
65 |
66 | const fixtures = [
67 | "Merkle integrity",
68 | "Runs in any cloud",
69 | "End-to-end encryption",
70 | "JSON documents",
71 | "Open-source connectors",
72 | "Commodity storage",
73 | "Serverless architecture",
74 | "Immutable history",
75 | "Self-sovereign auth",
76 | "Cloudless operation",
77 | "Event-driven architecture",
78 | "React state management"
79 | ];
80 |
81 | function getRandomThree(arr) {
82 | let result = ["Multi-writer CRDT"];
83 | let clonedArray = [...arr];
84 |
85 | for (let i = 1; i < 3; i++) {
86 | let randomIndex = Math.floor(Math.random() * clonedArray.length);
87 | result.push(clonedArray[randomIndex]);
88 | clonedArray.splice(randomIndex, 1);
89 | }
90 |
91 | return result;
92 | }
93 |
94 | async function reset(e) {
95 | if (e) e.preventDefault();
96 | const allDocs = await db.allDocs();
97 | for (const row of allDocs.rows) {
98 | db.del(row.key);
99 | }
100 |
101 | const puts = getRandomThree(fixtures).map((text) => {
102 | db.put({
103 | created: Date.now(),
104 | text,
105 | done: true
106 | });
107 | });
108 | await Promise.all(puts);
109 |
110 | db.compact();
111 | }
112 | window.reset = reset;
113 |
114 | window.onload = function initialize() {
115 | db.subscribe(redraw);
116 | redraw();
117 | // reset() // remove when connected
118 | };
119 |
120 | function connect(name) {
121 | const db = Fireproof.fireproof(name + 7);
122 | // placeholder until Fireproof Cloud ships
123 | FireproofConnect.connect.partykitS3(
124 | db,
125 | "https://firehouse-chat.jchris.partykit.dev"
126 | );
127 | return db;
128 | }
129 |
130 | // for another app that syncs live with the same dataset see
131 | // https://replit.com/@jchris5/HTML-CSS-JS-Auto-Refresh#script.js
--------------------------------------------------------------------------------
/src/script.js:
--------------------------------------------------------------------------------
1 | db = connect("fireproof");
2 |
3 | function addItemDb(text) {
4 | db.put({
5 | text,
6 | done: false,
7 | created: Date.now()
8 | });
9 | }
10 |
11 | function addItem(e) {
12 | e.preventDefault();
13 | const input = document.querySelector("form input");
14 | if (!input.value) return;
15 | addItemDb(input.value);
16 | input.value = "";
17 | }
18 | window.addItem = addItem;
19 |
20 | function toggleDone(doc) {
21 | doc.done = !doc.done;
22 | doc.updated = Date.now();
23 | db.put(doc);
24 | }
25 |
26 | async function redraw() {
27 | const result = await db.query("created", {
28 | includeDocs: true,
29 | descending: true,
30 | limit: 10
31 | });
32 |
33 | document.querySelector("ul").innerHTML = "";
34 |
35 | for (const row of result.rows) {
36 | const textSpan = document.createElement("span");
37 | textSpan.innerText = row.doc.text;
38 |
39 | const checkbox = document.createElement("input");
40 | checkbox.onchange = () => {
41 | toggleDone(row.doc);
42 | };
43 | if (row.doc.done) {
44 | checkbox.setAttribute("checked", true);
45 | }
46 | checkbox.setAttribute("type", "checkbox");
47 |
48 | const deleteSpan = document.createElement("span");
49 | deleteSpan.innerText = "x";
50 | deleteSpan.style = "text-align:right; color:#999";
51 | deleteSpan.onclick = function (e) {
52 | e.preventDefault();
53 | db.del(row.id);
54 | if (result.rows.length <= 1) reset();
55 | };
56 |
57 | const li = document.createElement("li");
58 | li.appendChild(checkbox);
59 | li.appendChild(textSpan);
60 | li.appendChild(deleteSpan);
61 |
62 | document.querySelector("ul").appendChild(li);
63 | }
64 | }
65 |
66 | const fixtures = [
67 | "Merkle integrity",
68 | "Runs in any cloud",
69 | "End-to-end encryption",
70 | "JSON documents",
71 | "Open-source connectors",
72 | "Commodity storage",
73 | "Serverless architecture",
74 | "Immutable history",
75 | "Self-sovereign auth",
76 | "Cloudless operation",
77 | "Event-driven architecture",
78 | "React state management"
79 | ];
80 |
81 | function getRandomThree(arr) {
82 | let result = ["Multi-writer CRDT"];
83 | let clonedArray = [...arr];
84 |
85 | for (let i = 1; i < 3; i++) {
86 | let randomIndex = Math.floor(Math.random() * clonedArray.length);
87 | result.push(clonedArray[randomIndex]);
88 | clonedArray.splice(randomIndex, 1);
89 | }
90 |
91 | return result;
92 | }
93 |
94 | async function reset(e) {
95 | if (e) e.preventDefault();
96 | const allDocs = await db.allDocs();
97 | for (const row of allDocs.rows) {
98 | db.del(row.key);
99 | }
100 |
101 | const puts = getRandomThree(fixtures).map((text) => {
102 | db.put({
103 | created: Date.now(),
104 | text,
105 | done: true
106 | });
107 | });
108 | await Promise.all(puts);
109 |
110 | db.compact();
111 | }
112 | window.reset = reset;
113 |
114 | window.onload = function initialize() {
115 | db.subscribe(redraw);
116 | redraw();
117 | // reset() // remove when connected
118 | };
119 |
120 | function connect(name) {
121 | const db = Fireproof.fireproof(name + 7);
122 | // placeholder until Fireproof Cloud ships
123 | FireproofConnect.connect.partykitS3(
124 | db,
125 | "https://firehouse-chat.jchris.partykit.dev"
126 | );
127 | return db;
128 | }
129 |
130 | // for another app that syncs live with the same dataset see
131 | // https://replit.com/@jchris5/HTML-CSS-JS-Auto-Refresh#script.js
132 |
--------------------------------------------------------------------------------
/dist/style.css:
--------------------------------------------------------------------------------
1 | /* General styles for dark mode */
2 | body {
3 | background-color: #121212; /* Dark background */
4 | color: #e0e0e0; /* Light text */
5 | font-family: Arial, sans-serif; /* Change to your preferred font */
6 | }
7 |
8 | /* Container Styles */
9 | .container {
10 | display: flex; /* Use flexbox for alignment */
11 | flex-direction: column; /* Stack form and list vertically */
12 | align-items: center; /* Center items horizontally */
13 | max-width: 600px; /* Limit the maximum width */
14 | margin: 0 auto; /* Center the container horizontally */
15 | }
16 |
17 | /* Unordered List Styles */
18 | ul {
19 | list-style-type: none; /* Remove default bullets */
20 | padding: 0;
21 | margin: 0;
22 | width: 100%; /* Make the list take the full width of the container */
23 | }
24 |
25 | /* List Item Styles */
26 | ul > li {
27 | display: flex; /* Use flexbox for alignment */
28 | align-items: center; /* Center items vertically */
29 | background-color: #1e1e1e; /* Slightly lighter background for list items */
30 | border: 1px solid #333; /* Border to separate items */
31 | border-radius: 5px; /* Rounded corners */
32 | padding: 10px; /* Spacing inside list items */
33 | margin: 5px 0; /* Space between list items */
34 | transition: background-color 0.3s; /* Smooth background change on hover */
35 | }
36 |
37 | /* Hover effect */
38 | ul > li:hover {
39 | background-color: #333; /* Darker background on hover */
40 | cursor: pointer; /* Pointer cursor on hover */
41 | }
42 |
43 | /* Optional: Add a subtle shadow */
44 | ul > li {
45 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); /* Subtle shadow */
46 | }
47 |
48 | /* Optional: Active or selected item */
49 | ul > li.active {
50 | background-color: #444; /* Different color for active/selected item */
51 | border-color: #555; /* Slightly different border for active/selected item */
52 | }
53 |
54 | /* Checkbox Styles */
55 | ul > li input[type="checkbox"] {
56 | appearance: none; /* Remove default checkbox style */
57 | background-color: #2a2a2a; /* Dark background */
58 | border: 2px solid #444; /* Border color */
59 | border-radius: 4px; /* Rounded corners */
60 | width: 20px;
61 | height: 20px;
62 | cursor: pointer; /* Pointer cursor */
63 | position: relative; /* Position relative for checkmark */
64 | transition: background-color 0.3s, border-color 0.3s; /* Smooth transition */
65 | margin-right: 10px; /* Space between checkbox and text */
66 | }
67 |
68 | ul > li input[type="checkbox"]:checked {
69 | background-color: #f58709; /* Green background when checked */
70 | border-color: #f58709; /* Green border when checked */
71 | }
72 |
73 | ul > li input[type="checkbox"]:checked::after {
74 | content: "✔"; /* Checkmark */
75 | color: #fff; /* White checkmark color */
76 | font-size: 14px;
77 | position: absolute;
78 | top: 50%;
79 | left: 50%;
80 | transform: translate(-50%, -50%); /* Center the checkmark */
81 | }
82 |
83 | ul > li input[type="checkbox"]:hover {
84 | background-color: #3a3a3a; /* Slightly lighter background on hover */
85 | border-color: #555; /* Slightly different border on hover */
86 | }
87 |
88 | /* Text Styles inside List Items */
89 | ul > li span {
90 | flex-grow: 1; /* Take up remaining space */
91 | margin-left: 10px; /* Space between checkbox and text */
92 | }
93 |
94 | /* Form Styles */
95 | form {
96 | display: flex; /* Use flexbox for alignment */
97 | align-items: center; /* Center items vertically */
98 | margin-bottom: 14px; /* Space below the form */
99 | margin-top: 10px;
100 | width: 100%; /* Make the form take the full width of the container */
101 | padding: 0 10px; /* Add padding to left and right */
102 | box-sizing: border-box; /* Include padding in width calculation */
103 | }
104 |
105 | /* Input Styles */
106 | form input[type="text"] {
107 | background-color: #2a2a2a; /* Dark background */
108 | color: #e0e0e0; /* Light text */
109 | border: 1px solid #444; /* Border color */
110 | border-radius: 4px; /* Rounded corners */
111 | padding: 8px; /* Padding inside the input */
112 | margin-right: 10px; /* Space between input and button */
113 | flex-grow: 1; /* Take up remaining space */
114 | box-sizing: border-box; /* Include padding in width calculation */
115 | }
116 |
117 | /* Button Styles */
118 | form button {
119 | background-color: #f58709; /* Green background */
120 | color: #fff; /* White text */
121 | font-weight: bold;
122 | font-size: 0.8em;
123 | border: none; /* Remove default border */
124 | border-radius: 4px; /* Rounded corners */
125 | padding: 8px 12px; /* Padding inside the button */
126 | cursor: pointer; /* Pointer cursor */
127 | transition: background-color 0.3s; /* Smooth background change on hover */
128 | white-space: nowrap; /* Prevent text wrap */
129 | box-sizing: border-box; /* Include padding in width calculation */
130 | }
131 |
132 | form button:hover {
133 | background-color: #f16c12; /* Darker green on hover */
134 | }
--------------------------------------------------------------------------------
/src/style.css:
--------------------------------------------------------------------------------
1 | /* General styles for dark mode */
2 | body {
3 | background-color: #121212; /* Dark background */
4 | color: #e0e0e0; /* Light text */
5 | font-family: Arial, sans-serif; /* Change to your preferred font */
6 | }
7 |
8 | /* Container Styles */
9 | .container {
10 | display: flex; /* Use flexbox for alignment */
11 | flex-direction: column; /* Stack form and list vertically */
12 | align-items: center; /* Center items horizontally */
13 | max-width: 600px; /* Limit the maximum width */
14 | margin: 0 auto; /* Center the container horizontally */
15 | }
16 |
17 | /* Unordered List Styles */
18 | ul {
19 | list-style-type: none; /* Remove default bullets */
20 | padding: 0;
21 | margin: 0;
22 | width: 100%; /* Make the list take the full width of the container */
23 | }
24 |
25 | /* List Item Styles */
26 | ul > li {
27 | display: flex; /* Use flexbox for alignment */
28 | align-items: center; /* Center items vertically */
29 | background-color: #1e1e1e; /* Slightly lighter background for list items */
30 | border: 1px solid #333; /* Border to separate items */
31 | border-radius: 5px; /* Rounded corners */
32 | padding: 10px; /* Spacing inside list items */
33 | margin: 5px 0; /* Space between list items */
34 | transition: background-color 0.3s; /* Smooth background change on hover */
35 | }
36 |
37 | /* Hover effect */
38 | ul > li:hover {
39 | background-color: #333; /* Darker background on hover */
40 | cursor: pointer; /* Pointer cursor on hover */
41 | }
42 |
43 | /* Optional: Add a subtle shadow */
44 | ul > li {
45 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); /* Subtle shadow */
46 | }
47 |
48 | /* Optional: Active or selected item */
49 | ul > li.active {
50 | background-color: #444; /* Different color for active/selected item */
51 | border-color: #555; /* Slightly different border for active/selected item */
52 | }
53 |
54 | /* Checkbox Styles */
55 | ul > li input[type="checkbox"] {
56 | appearance: none; /* Remove default checkbox style */
57 | background-color: #2a2a2a; /* Dark background */
58 | border: 2px solid #444; /* Border color */
59 | border-radius: 4px; /* Rounded corners */
60 | width: 20px;
61 | height: 20px;
62 | cursor: pointer; /* Pointer cursor */
63 | position: relative; /* Position relative for checkmark */
64 | transition: background-color 0.3s, border-color 0.3s; /* Smooth transition */
65 | margin-right: 10px; /* Space between checkbox and text */
66 | }
67 |
68 | ul > li input[type="checkbox"]:checked {
69 | background-color: #f58709; /* Green background when checked */
70 | border-color: #f58709; /* Green border when checked */
71 | }
72 |
73 | ul > li input[type="checkbox"]:checked::after {
74 | content: "✔"; /* Checkmark */
75 | color: #fff; /* White checkmark color */
76 | font-size: 14px;
77 | position: absolute;
78 | top: 50%;
79 | left: 50%;
80 | transform: translate(-50%, -50%); /* Center the checkmark */
81 | }
82 |
83 | ul > li input[type="checkbox"]:hover {
84 | background-color: #3a3a3a; /* Slightly lighter background on hover */
85 | border-color: #555; /* Slightly different border on hover */
86 | }
87 |
88 | /* Text Styles inside List Items */
89 | ul > li span {
90 | flex-grow: 1; /* Take up remaining space */
91 | margin-left: 10px; /* Space between checkbox and text */
92 | }
93 |
94 | /* Form Styles */
95 | form {
96 | display: flex; /* Use flexbox for alignment */
97 | align-items: center; /* Center items vertically */
98 | margin-bottom: 14px; /* Space below the form */
99 | margin-top: 10px;
100 | width: 100%; /* Make the form take the full width of the container */
101 | padding: 0 10px; /* Add padding to left and right */
102 | box-sizing: border-box; /* Include padding in width calculation */
103 | }
104 |
105 | /* Input Styles */
106 | form input[type="text"] {
107 | background-color: #2a2a2a; /* Dark background */
108 | color: #e0e0e0; /* Light text */
109 | border: 1px solid #444; /* Border color */
110 | border-radius: 4px; /* Rounded corners */
111 | padding: 8px; /* Padding inside the input */
112 | margin-right: 10px; /* Space between input and button */
113 | flex-grow: 1; /* Take up remaining space */
114 | box-sizing: border-box; /* Include padding in width calculation */
115 | }
116 |
117 | /* Button Styles */
118 | form button {
119 | background-color: #f58709; /* Green background */
120 | color: #fff; /* White text */
121 | font-weight: bold;
122 | font-size: 0.8em;
123 | border: none; /* Remove default border */
124 | border-radius: 4px; /* Rounded corners */
125 | padding: 8px 12px; /* Padding inside the button */
126 | cursor: pointer; /* Pointer cursor */
127 | transition: background-color 0.3s; /* Smooth background change on hover */
128 | white-space: nowrap; /* Prevent text wrap */
129 | box-sizing: border-box; /* Include padding in width calculation */
130 | }
131 |
132 | form button:hover {
133 | background-color: #f16c12; /* Darker green on hover */
134 | }
135 |
--------------------------------------------------------------------------------