A fun, easy to use, sticky note web-app.
start with manifest.json
** instructions to save the app to a screen,
create an icon, and work offline.
create this file from terminal
touch manifest.json
A text editor will work
{ "name": "oh-stick!", "short_name": "notes by jr", "start_url": "https://sudo-self.github.io/oh-stick/#", "scope": "./", "icons": [ { "src": "APPicon.png", "sizes": "192x192", "type": "image/png" }, { "src": "APPicon1.png", "sizes": "512x512", "type": "image/png" } ], "theme_color": "#ffd31d", "background_color": "#333", "display": "standalone" }
APPicon.png = Appicon
Oh-stick starts with HTML
touch index.html
link external CSS and JAVA
<link rel=¨stylesheet¨ type=¨text/css¨ href=¨..\[folder_name]\[file_name].css¨><br> <script src="myscripts.js"></script>
standard is legit in 2024.
Set header with favicon
add
favicon.ico & apple-touch-icon.png
in the root folder
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"> <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"> <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"> <link rel="manifest" href="/site.webmanifest">
next is html body
<h1>Oh-Stick!</h1> <p id="ts">notes by Jesse</p> </div> <div id="form"> <form id="inputForm"> <input type="text" class="inputText" placeholder="Title" id="new-note-title-input" autocomplete="off" required autofocus /><br><br> <input class="inputText" type="text" placeholder="Note Content" id="new-note-body-input" autocomplete="off" required /> <button type="submit" class="btn"> 🧲 </button> </form> </div> </html>
Emoji as a button to stick note.
The favicon you can create from scratch.
A good quality starting image is key.
Javascript makes up the function of the notes.
touch script.js
Set or modify alerts as needed.
if ("serviceWorker" in navigator) { // register service worker navigator.serviceWorker.register("service-worker.js"); } var itemList = document.getElementById("notes"); itemList.addEventListener("click", removeItem); let count = Number(window.localStorage.getItem("count")); if (!count) { window.localStorage.setItem("count", "0"); } console.log(count); let createNote = (noteTitle, noteBody) => { if (count > 0) { document.getElementById("no-notes").className = "hidden"; } var li = document.createElement("li"); var a = document.createElement("a"); var h2 = document.createElement("h2"); var p = document.createElement("p"); var ul = document.getElementById("notes"); let xButton = document.createElement("button"); xButton.classList.add("delete"); let xText = document.createTextNode("X"); let h2TN = document.createTextNode(noteTitle); let pTN = document.createTextNode(noteBody); h2.appendChild(h2TN); p.appendChild(pTN); xButton.appendChild(xText); a.appendChild(h2); a.appendChild(xButton); a.appendChild(p); a.setAttribute("href", "#"); li.appendChild(a); ul.appendChild(li); }; let createNoteFromInput = (e) => { e.preventDefault(); var noteTitle = document.getElementById("new-note-title-input").value; var noteBody = document.getElementById("new-note-body-input").value; document.getElementById("new-note-title-input").value = ""; document.getElementById("new-note-body-input").value = ""; console.log("yes"); if (!noteTitle || !noteBody) { alert("Both Title and body of the note must be provided"); return; } count += 1; window.localStorage.setItem("count", count); while (window.localStorage.getItem(noteTitle)) { noteTitle = noteTitle + " - 1"; } window.localStorage.setItem(noteTitle, noteBody); createNote(noteTitle, noteBody); }; function removeItem(e) { //console.log('2'); if (e.target.classList.contains("delete")) { console.log(e); if ( confirm( 'Remove adhesive from "' + e.target.previousElementSibling.innerText + '" stick?' ) ) { //grab the parent // console.log(e.target.previousSibling.data); var li = e.target.parentElement.parentElement; itemList.removeChild(li); count -= 1; window.localStorage.setItem("count", count); window.localStorage.removeItem(e.target.previousElementSibling.innerText); if (count < 1) { document.getElementById("no-notes").className = ""; } } } } for (i = 0; i < count + 1; i++) { console.log(window.localStorage.key(i)); let noteTitle = window.localStorage.key(i); let noteBody = window.localStorage.getItem(noteTitle); if (noteTitle !== "count" && noteTitle) { createNote(noteTitle, noteBody); } } document .getElementById("inputForm") .addEventListener("submit", createNoteFromInput, false);
style.css
strong foundations can scale vertically
.json adds wrapper versatility.
touch style.css
* { margin: 0; padding: 0; } body { font-family: arial, sans-serif; font-size: 100%; margin: 3em; background: #333; color: #fff; } #heading { position: sticky; top: 0; background-color: #333; z-index: 7; padding: 15px 0px; margin-left: 15px; } #no-notes { padding: 100px 0px; text-align: center; } #ts { color: #9085c4; } .inputText { padding: 10px; border-radius: 5px; border: 2px solid #9085c4; width: 30%; margin: 15px; outline: none; } .hidden { display: none; } .btn { padding: 10px; border-radius: 20px; border: 2px solid #9085c4; background-color: #333; color: #333; cursor: pointer; outline: none; -webkit-tap-highlight-color: transparent; } .btn:active { border: 2px solid #333; box-shadow: inset 0 0 5px #000000; } h2, p { font-size: 100%; font-weight: normal; } ul, li { list-style: none; } ul { overflow: hidden; padding: 3em 1em; } ul li a { text-decoration: none; color: #000; background: #9085c4; display: block; height: 10em; width: 10em; padding: 1em; box-shadow: 5px 5px 7px rgba(33, 33, 33, 0.7); } ul li { margin: 1em; float: left; position: relative; } ul li h2 { font-size: 1.2rem; font-weight: bold; padding-bottom: 10px; } ul li p { font-family: "Reenie Beanie", cursive; font-size: 1.1rem; } .delete { float: right; position: absolute; top: 0; right: 0; width: 30px; height: 30px; background-color: red; border: 4px double white; font-weight: bold; cursor: pointer; } ul li a { transform: rotate(-6deg); -moz-transform: rotate(-6deg); cursor: default; } ul li:nth-child(even) a { transform: rotate(4deg); -moz-transform: rotate(4deg); position: relative; top: 5px; background: #ff5733; } ul li:nth-child(3n) a { transform: rotate(-3deg); -moz-transform: rotate(-3deg); position: relative; top: -5px; background: #77d8d8; } ul li:nth-child(5n) a { transform: rotate(5deg); -moz-transform: rotate(5deg); position: relative; top: -10px; } ul li a:hover, ul li a:focus { box-shadow: 10px 10px 7px rgba(0, 0, 0, 0.7); -moz-box-shadow: 10px 10px 7px rgba(0, 0, 0, 0.7); transform: scale(1.25); -moz-transform: scale(1.25); position: relative; z-index: 5; } ol { text-align: center; } ol li { display: inline; padding-right: 1em; } ol li a { color: #fff; } @media only screen and (max-width: 600px) { body { margin-top: 1em; } #new-note-title-input, #new-note-body-input { display: block; width: 90%; margin-left: 0px; } #heading { margin-left: 0px; } .btn { margin-left: 0px; } }
A static.yml will work to publish a workflow.
The workflow is essential for wrapping to PWA to APK. with GH-Pages you now have a URL for manifest.json
https://sudo-self.github.io/oh-stick/ manifest.json HERE
static.yml
name: Deploy static content to Pages on: push: branches: ["main"] tab workflow_dispatch: permissions: contents: read pages: write id-token: write concurrency: group: "pages" cancel-in-progress: false jobs: deploy: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Pages uses: actions/configure-pages@v4 - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: path: '.' - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4
Now The App is live online.
https://sudo-self.github.io/oh-stick/
- index.html
- style.css
- script.js
- ""
- "" <----website---->
<---webapp----->
- liscense.txt
- README.md (project explanation)
<----TWA---->
- manifest.json (for PWA to APK or IPA)
See the Pen Oh-stick! by sudo-self (@sudo-self) on CodePen.
All the way to a signed android APK with a wrapper.
sticky reminders
https://oh-stick.JesseJesse.com
See the Pen
Oh-stick! by sudo-self (@sudo-self)
on CodePen.
Top comments (0)