Compare commits

62 Commits
Author SHA1 Message Date
me b78eb3f0f4 apps, fix title and reword description for Sunset Alarm. 2026-11-04 13:07:39 -07:00
me 77d96bdfd9 apps, update Obtainium instructions. 2026-11-04 12:51:53 -07:00
me 851171609b apps, go back to using src URI for obtainium since it's just showing the text on Android FF. 2026-11-04 12:45:51 -07:00
me a45a0a6368 Add README's for the new folders. 2026-11-04 12:44:56 -07:00
me 032e551858 favicon, add var to favicon.io links and add sizes="any" to svg. 2026-11-02 14:47:43 -07:00
me a3192ec559 favicon, comment redundant entries. 2026-11-02 09:05:02 -07:00
me 826daabc72 main, add timestamps to the log. 2026-11-02 08:52:04 -07:00
me 53bb02063a banner, use asset images. 2026-11-02 08:13:47 -07:00
me 10bb283a44 favicon, add new favicons and manifests. 2026-11-02 08:13:31 -07:00
me eda39d07ba assets, add favicons and manifests from same websites used for blog site, this time based on peace icon. 2026-11-02 08:13:10 -07:00
me 845d7ecdcb art, add images frequently used as icons. 2026-11-02 08:12:12 -07:00
me 027a7875d8 main, implement an 'assets' folder for files needed at the website's root, allows having a local favicon and images. 2026-11-02 08:11:35 -07:00
me 47a022161c apps, point hypergames image to dev branch since main may not be done for a while. 2026-11-01 11:07:33 -07:00
me 31d9a8b706 apps, update TicTacToe and HyperGames to be new standard. 2026-11-01 10:28:32 -07:00
me d424a4c7c3 apps, update T45MR to new standard. 2026-11-01 08:34:25 -07:00
me e44e8a6d18 apps, update Expense Tracker to use the new standard. 2026-11-01 07:45:13 -07:00
me 3f0fff42d4 header, move favicons to their own file before adding better support. 2026-10-29 21:53:34 -07:00
me 25ff248b92 main, begin to minify HTML. 2026-10-29 21:53:08 -07:00
me ed934ea5d9 banner, hide the underlines. 2026-10-05 15:51:34 -07:00
me f7dd491553 font, fix whitespace. 2026-10-05 15:40:42 -07:00
me 4ba60b1c21 announcements, small refactor and add the video for F-Droid. 2026-10-05 15:21:12 -07:00
me 31217aa641 css, fix row behavior for banner. 2026-10-05 15:07:30 -07:00
me 82ad8a9134 main, fix garbage inserted from Android editor app. 2026-10-05 15:05:01 -07:00
me 6155a21a24 banner, fix not showing up on mobile views. 2026-10-05 15:04:30 -07:00
me 3c441f117a Commit mobile testing on Termux, will finish on laptop. 2026-10-05 13:40:41 -07:00
me 67c968e390 banner, change to go to root not about. 2026-10-05 11:53:18 -07:00
me 1544fd140f banner, fix width for tablet mode. 2026-10-05 11:51:43 -07:00
me cab5a4cbcf css, add commas for tablet mode. 2026-10-05 11:51:21 -07:00
me d58261f8c2 apps, shorten link for mobile. 2026-10-05 11:50:45 -07:00
me 2e8eefda7f css, fix the widths in tablet move. 2026-10-05 10:48:49 -07:00
me 2cae390404 css, further de-dupe mobile code. 2026-10-05 10:46:36 -07:00
me e285ccf5d5 css, add a section which is both phone and tablets rather than duplicating code. 2026-10-05 10:46:02 -07:00
me 74611fa707 css, hide banner images if phone or tablet. 2026-10-05 10:42:49 -07:00
me 11c990f1e4 menu, add colons back to headers. 2026-10-05 10:39:07 -07:00
me b8e3840d7a css, add spacing back to menu items. 2026-10-05 10:38:13 -07:00
me 6d497a238d menu, continue shrinking menu. 2026-10-05 10:36:58 -07:00
me 6b32473727 main css, border does not need to be related to font size. 2026-10-05 10:16:09 -07:00
me 8dcbbab181 main, use menu-list and change border to be relative. 2026-10-05 10:13:04 -07:00
me 0e029a9ab6 menu, take up much less space. 2026-10-05 10:12:45 -07:00
me c838fba60c main, add comment for testing later. 2026-10-05 10:00:51 -07:00
me 6fd8441419 menu, take advantage of updated grid setup. 2026-10-05 09:58:37 -07:00
me 67b6643c69 apps, take advantage of updated grid setup. 2026-10-05 09:58:29 -07:00
me d4f8712d11 main, update grid setup to be more modern and dynamic. 2026-10-05 09:58:07 -07:00
me 22d89d4bb3 main, update CSS so that phones and tablets break columns into rows again. 2026-10-05 09:05:01 -07:00
me 3eee3913c0 font, disable to attempt to fix Firefox Mobile's sizing. 2026-10-05 08:48:12 -07:00
me 001f5d471a header, add a viewport tag to see if Firefox Mobile acts different. 2026-10-05 08:47:15 -07:00
me fc2668008d font, refactor file and adjust some more sizes. 2026-10-05 08:42:12 -07:00
me a5bcf0c054 donate, use b instead of code for subheaders, keep the monospaced font using a class. 2026-10-05 08:41:51 -07:00
me 0c2c45d633 font, make b slightly smaller than strong. 2026-10-05 08:24:43 -07:00
me 0fdb5f3787 font, try to correct Firefox Mobile doing odd things. 2026-10-05 08:23:23 -07:00
me f78e521d8f font, use explicit base size so that Firefox hopefully does not distort things anymore. 2026-10-05 08:09:01 -07:00
me b15bc7b15a font, install the new sizes and families to see how it looks on mobile using dev site. 2026-10-05 07:58:14 -07:00
me 37e26bd7ec menu, fix link to books. 2026-10-05 07:30:33 -07:00
me ace12bc24e apps, change Obtainium to use prod rather than main so no pull requests are needed. 2026-10-02 11:42:47 -07:00
me e1ef71971c apps, use Infinite Timer app icon for image. 2026-10-01 20:35:45 -07:00
me 4df8d59202 apps, add latest APK URL for Carb Up and reference its icon. 2026-10-01 15:41:32 -07:00
me a0ce3998db announcements, add Sunset Alarm entry. 2026-10-01 15:19:53 -07:00
me 8e93c814e8 apps, add Sunset Alarm URLs. 2026-10-01 15:19:41 -07:00
me c1c2a71277 Add announcement for Sunsset Alarm. 2026-09-28 18:21:23 -07:00
me 7941dade8c run, check all prog variables. 2026-09-28 18:14:50 -07:00
me 810ff3ce36 run, start changing script to handle Artix/Arch. 2026-09-28 15:45:01 -07:00
me 30da06e1fe apps, begin adding Sunset Timer. 2026-09-28 15:44:27 -07:00
32 changed files with 494 additions and 205 deletions

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
# Art
Support directory to store images which are used inderectly for the site.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

+4
View File
@@ -0,0 +1,4 @@
# Assets
Similar to `static/` on a Hugo website, these files are served at the website's
root as-is. Useful for favicon type content. Can have folders if desired.
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 662 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="1000" height="1000"><metadata><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/"><rdf:Description><dc:creator>RealFaviconGenerator</dc:creator><dc:source>https://realfavicongenerator.net</dc:source></rdf:Description></rdf:RDF></metadata><g clip-path="url(#SvgjsClipPath1046)"><rect width="1000" height="1000" fill="#ffffff"></rect><g transform="matrix(3.3333333333333335,0,0,3.3333333333333335,0,0)"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" height="300" viewBox="0 0 300 300"><image width="300" height="300" xlink:href="data:image/png;base64,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 truncated

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.
Binary file not shown.
+21
View File
@@ -0,0 +1,21 @@
{
"name": "Hyperling.com",
"short_name": "Hyperling",
"icons": [
{
"src": "/web-app-manifest-192x192.png?v=20261102",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "/web-app-manifest-512x512.png?v=20261102",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

+137 -60
View File
@@ -14,6 +14,8 @@ const execSync = require('child_process').execSync;
const fs = require('fs'); const fs = require('fs');
const { minify } = require('html-minifier-terser');
//// Global Variables //// //// Global Variables ////
const DEBUG = false; const DEBUG = false;
@@ -24,12 +26,16 @@ let pages = [];
const pages_dir = "./pages/"; const pages_dir = "./pages/";
const file_types = ["php", "sh"]; const file_types = ["php", "sh"];
let assets = [];
const asset_dir = "./assets/";
const asset_types = ['png', 'svg', 'ico', 'webmanifest', 'jpg'];
let ports = []; let ports = [];
// Check parameters for numeric port numbers. // Check parameters for numeric port numbers.
process.argv.forEach(function (val, index, array) { process.argv.forEach(function (val, index, array) {
console.log("Parameter", index + ':', val, !isNaN(val)); console.log(now() + ": Parameter", index + ':', val, !isNaN(val));
if (!isNaN(val)) { if (!isNaN(val)) {
console.log("Adding Port", val) console.log(now() + ": Adding Port", val)
ports.push(val); ports.push(val);
} }
}); });
@@ -44,25 +50,76 @@ const stringsToRemove = [
//// Functions //// //// Functions ////
// Compact HTML and remove unnecessary content like comments and whitespace.
// May help with performance for slower connections. Also more professional.
async function mini(html) {
//console.log(`html=${html}`);
const minified = await minify(html, {
collapseWhitespace: true,
removeComments: true,
minifyJS: true,
minifyCSS: true
});
//console.log(`minified=${minified}`);
return minified.toString();
}
// Check extension and guess a MIME type.
function getMIME(extension) {
let mime;
switch (extension) {
case "apk":
mime = "application/vnd.android.package-archive";
break;
case "jpg":
case "jpeg":
mime = "image/jpeg";
break;
case "png":
mime = "image/png";
break;
case "html":
mime = "text/html";
break;
case "zip":
mime = "application/zip";
break;
case "md":
case "txt":
case "csv":
mime = "text/*";
break;
default:
mime = "application/" + extension;
break;
}
return mime;
}
// Print datetime for logging.
function now() {
return new Date().toISOString();
}
/* Code exists inside a main function so that we may use async/await. /* Code exists inside a main function so that we may use async/await.
*/ */
async function main() { async function main() {
console.log("...Starting Main..."); console.log(now() + ": ...Starting Main...");
// Getting dates in Node.js is awful, just use Linux. // Getting dates in Node.js is awful, just use Linux.
const start_datetime = "" + await execSync('date "+%Y-%m-%dT%H:%M:%S%:z"'); const start_datetime = "" + await execSync('date "+%Y-%m-%dT%H:%M:%S%:z"');
const start_datetime_trimmed = start_datetime.trim(); const start_datetime_trimmed = start_datetime.trim();
console.log("Set app to return HTML documents."); console.log(now() + ": Set app to return HTML documents.");
app.use(function (req, res, next) { app.use(function (req, res, next) {
res.contentType('text/html'); res.contentType('text/html');
next(); next();
}); });
/* Loop through all file in the pages subdirectory and add the allowed /* Loop through all files in the pages subdirectory and add the allowed
// file types into the pages array for automatic router creation. // file types into the pages array for automatic router creation.
*/ */
console.log("...Starting Main..."); console.log(now() + ": ...Starting Pages...");
let ls = await fs.promises.readdir(pages_dir); let ls = await fs.promises.readdir(pages_dir);
if (DEBUG) console.log("DEBUG: Results of ls, ", ls); if (DEBUG) console.log("DEBUG: Results of ls, ", ls);
for (let file of ls) { for (let file of ls) {
@@ -72,14 +129,35 @@ async function main() {
if (file_types.includes(file_type)) { if (file_types.includes(file_type)) {
if (DEBUG) console.log("DEBUG: Hooray!", file, "is being added."); if (DEBUG) console.log("DEBUG: Hooray!", file, "is being added.");
pages[file_name] = pages_dir + file; pages[file_name] = pages_dir + file;
console.log(" * Added page", file); console.log(now() + ": * Added page", file);
} else { } else {
if (DEBUG) console.log("DEBUG: ", file, "is not an approved type, skipping."); if (DEBUG) console.log("DEBUG: ", file, "is not an approved type, skipping.");
} }
} }
console.log(" * Pages loaded: ", pages); console.log(now() + ": * Pages loaded: ", pages);
//return; // Stop execution FORTESTING //return; // Stop execution FORTESTING
/* Loop through the assets folder and grab favicons, manifests, etc. and
// allow them to be accessed via the root of the website, such as a favicon
// at 'https://hyperling.com/favicon.ico'. May help with SEO!
*/
console.log(now() + ": ...Starting Assets...");
let ls_assets = await fs.promises.readdir(asset_dir);
if (DEBUG) console.log("DEBUG: Results of ls_assets, ", ls_assets);
for (let file of ls_assets) {
let file_test = file.split(".");
//let file_name = file_test[0]; // not needed (yet)
let file_type = file_test[file_test.length - 1];
if (asset_types.includes(file_type)) {
if (DEBUG) console.log("DEBUG: Hooray!", file, "is being added.");
assets[file] = asset_dir + file;
console.log(now() + ": * Added asset", file);
} else {
if (DEBUG) console.log("DEBUG: ", file, "is not an approved type, skipping.");
}
}
console.log(now() + ": * Assets loaded: ", assets);
/* Create both an XML and HTML sitemap based on these entries. XML is used for /* Create both an XML and HTML sitemap based on these entries. XML is used for
// bots like SEO scrapers. HTML will be for human users looking for a list of // bots like SEO scrapers. HTML will be for human users looking for a list of
// all pages. Some are not in the menu. Generated an example XML sitemap at // all pages. Some are not in the menu. Generated an example XML sitemap at
@@ -140,7 +218,7 @@ async function main() {
Sitemap: https://hyperling.com/sitemap.xml Sitemap: https://hyperling.com/sitemap.xml
`; `;
console.log("...Adding Routes..."); console.log(now() + ": ...Adding Routes...");
let router = express.Router(); let router = express.Router();
/* AUTOMATIC METHOD BASED ON OBJECT/ARRAY OF WEB SCRIPTS /* AUTOMATIC METHOD BASED ON OBJECT/ARRAY OF WEB SCRIPTS
@@ -148,19 +226,20 @@ async function main() {
*/ */
// TBD/TODO would be great to log this as "DATE: ADDRESS hit ROUTER requesting RESOURCE" // TBD/TODO would be great to log this as "DATE: ADDRESS hit ROUTER requesting RESOURCE"
for (let key in pages) { for (let key in pages) {
console.log(" * Creating router for", key); console.log(now() + ": * Creating router for", key);
router.get("/" + key, function (req,res) { router.get("/" + key, async function (req,res) {
console.log(key, "fulfilling request to", req.socket.remoteAddress, "asking for", req.url); console.log(now() + ":", key, "fulfilling request to", req.socket.remoteAddress, "asking for", req.url);
let html = "" + execSync(pages[key]); let html = "" + execSync(pages[key]);
stringsToRemove.forEach(string => { stringsToRemove.forEach(string => {
html = html.replace(string, ""); html = html.replace(string, "");
}); });
html = await mini(html);
res.send(html); res.send(html);
}); });
/* Append the page to the sitemap variables. /* Append the page to the sitemap variables.
*/ */
console.log(" * * Adding to sitemap.xml"); console.log(now() + ": * * Adding to sitemap.xml");
sitemap_xml = sitemap_xml + ` sitemap_xml = sitemap_xml + `
<url> <url>
<loc>https://hyperling.com/`+key+`/</loc> <loc>https://hyperling.com/`+key+`/</loc>
@@ -168,7 +247,7 @@ async function main() {
<priority>0.80</priority> <priority>0.80</priority>
</url> </url>
`; `;
console.log(" * * Adding to sitemap.html"); console.log(now() + ": * * Adding to sitemap.html");
sitemap_html = sitemap_html + ` sitemap_html = sitemap_html + `
<li> <li>
<b>`+key+`</b> <b>`+key+`</b>
@@ -187,69 +266,66 @@ async function main() {
</ul></body></html> </ul></body></html>
`; `;
console.log(now() + ": * Creating routers for assets");
for (let key in assets) {
console.log(now() + ": * * Adding /" + key);
router.get('/' + key, function (req, res) {
console.log(now() + ": asset response to", req.socket.remoteAddress, "asking for", req.url)
// Build variables.
const file = "./assets/" + req.path;
const extensions = req.path.split(".");
const extension = extensions[extensions.length-1];
let mime = getMIME(extension);
// Return the file
res.contentType(mime);
let f = fs.createReadStream(file)
.on("error", function(e) {
res.contentType("text/plain");
res.send(404, "Asset Not Found");
})
.pipe(res)
;
});
}
// Provide sitemap.xml file for "SEO". // Provide sitemap.xml file for "SEO".
// TBD/TODO would be great to log this as "DATE: ADDRESS hit ROUTER requesting RESOURCE" // TBD/TODO would be great to log this as "DATE: ADDRESS hit ROUTER requesting RESOURCE"
console.log(" * Creating router for sitemap.xml"); console.log(now() + ": * Creating router for sitemap.xml");
router.get('/sitemap.xml', function (req, res) { router.get('/sitemap.xml', function (req, res) {
console.log("sitemap.xml being provided to", req.socket.remoteAddress) console.log(now() + ": sitemap.xml being provided to", req.socket.remoteAddress)
res.contentType('text/xml'); res.contentType('text/xml');
res.send(sitemap_xml); res.send(sitemap_xml);
}); });
// Provide human-usable sitemap links. // Provide human-usable sitemap links.
// TBD/TODO would be great to log this as "DATE: ADDRESS hit ROUTER requesting RESOURCE" // TBD/TODO would be great to log this as "DATE: ADDRESS hit ROUTER requesting RESOURCE"
console.log(" * Creating router for sitemap*"); console.log(now() + ": * Creating router for sitemap*");
router.get('/sitemap*', function (req, res) { router.get('/sitemap*', async function (req, res) {
console.log("sitemap.html being provided to", req.socket.remoteAddress) console.log(now() + ": sitemap.html being provided to", req.socket.remoteAddress)
res.send(sitemap_html); html = await mini(sitemap_html);
res.send(mini(html));
}); });
// Provide a robots.txt for where search engines should find things. // Provide a robots.txt for where search engines should find things.
console.log(" * Creating router for robots.txt"); console.log(now() + ": * Creating router for robots.txt");
router.get('/robots.txt', function (req, res) { router.get('/robots.txt', function (req, res) {
console.log("robots.txt being provided to", req.socket.remoteAddress) console.log(now() + ": robots.txt being provided to", req.socket.remoteAddress)
res.send(robots_txt); res.send(robots_txt);
}); });
// Return a resource from the files folder. // Return a resource from the files folder.
// TBD/TODO would be great to log this as "DATE: ADDRESS hit ROUTER requesting RESOURCE" // TBD/TODO would be great to log this as "DATE: ADDRESS hit ROUTER requesting RESOURCE"
console.log(" * Creating router for files"); console.log(now() + ": * Creating router for files");
router.get('/files*', function (req, res) { router.get('/files*', function (req, res) {
console.log("file response to", req.socket.remoteAddress, "asking for", req.url) console.log(now() + ": file response to", req.socket.remoteAddress, "asking for", req.url)
// Build variables. // Build variables.
const file = "." + req.path; const file = "." + req.path;
const extensions = req.path.split("."); const extensions = req.path.split(".");
const extension = extensions[extensions.length-1]; const extension = extensions[extensions.length-1];
let mime = getMIME(extension);
// Check extension and guess a MIME type.
let mime;
switch (extension) {
case "apk":
mime = "application/vnd.android.package-archive";
break;
case "jpg":
case "jpeg":
mime = "image/jpeg";
break;
case "png":
mime = "image/png";
break;
case "html":
mime = "text/html";
break;
case "zip":
mime = "application/zip";
break;
case "md":
case "txt":
case "csv":
mime = "text/*";
break;
default:
mime = "application/" + extension;
break;
}
// Return the file // Return the file
res.contentType(mime); res.contentType(mime);
@@ -263,28 +339,29 @@ async function main() {
}); });
// Originally a test, now a catch-all redirection to Home! // Originally a test, now a catch-all redirection to Home!
console.log(" * Creating router for redirection"); console.log(now() + ": * Creating router for redirection");
router.get('/*', function (req, res) { router.get('/*', async function (req, res) {
// WARNING: These are huge so only look when you need to. // WARNING: These are huge so only look when you need to.
//console.log(req); //console.log(req);
//console.log(res); //console.log(res);
console.log("*wildcard* replying to", req.socket.remoteAddress, "asking for", req.url) console.log(now() + ": *wildcard* replying to", req.socket.remoteAddress, "asking for", req.url)
let html = "" + execSync("./pages/home.php"); let html = "" + execSync("./pages/home.php");
stringsToRemove.forEach(string => { stringsToRemove.forEach(string => {
html = html.replace(string, ""); html = html.replace(string, "");
}); });
html = await mini(html);
res.send(html); res.send(html);
}); });
app.use('', router); app.use('', router);
console.log("...Adding Ports..."); console.log(now() + ": ...Adding Ports...");
ports.forEach(port => { ports.forEach(port => {
app.listen(port); app.listen(port);
console.log(" * Now listening on port " + port + "."); console.log(now() + ": * Now listening on port " + port + ".");
console.log(" * URL: http://localhost:" + port); console.log(now() + ": * URL: http://localhost:" + port);
}); });
console.log("Done! Now we wait..."); console.log(now() + ": Done! Now we wait...");
} }
//// Program Execution //// //// Program Execution ////
+2 -1
View File
@@ -1,6 +1,7 @@
{ {
"dependencies": { "dependencies": {
"express": ">=4.18.1 < 5.0.0" "express": ">=4.18.1 < 5.0.0",
"html-minifier-terser": "^7.2.0"
}, },
"scripts": { "scripts": {
"start": "./run.sh" "start": "./run.sh"
+66 -52
View File
@@ -38,7 +38,7 @@
convenient group: convenient group:
</p> </p>
<ul class="indent"><li> <ul class="indent"><li>
<a href="https://git.hyperling.com/me/env-obtainium-hyperling/raw/branch/main/obtainium-export.json" <a href="https://git.hyperling.com/me/env-obtainium-hyperling/src/branch/prod/obtainium-export.json"
target="_blank" rel="noopener noreferrer" target="_blank" rel="noopener noreferrer"
> >
[obtainium-export.json] | Hyperling's Apps [obtainium-export.json] | Hyperling's Apps
@@ -57,15 +57,13 @@
section below, here is how to show the correct version numbers: section below, here is how to show the correct version numbers:
</p> </p>
<ul> <ul>
<li>Enable <i>"Sort by only the last segment of the link"</i>.</li>
<li> <li>
Set the <i>"Version string extraction RegEx"</i> field to: Set the <i>"Version string extraction RegEx"</i> field to:
<code>[0-9\.]+[0-9]+</code> <code>\d+\.\d+\.\d+</code>
</li> </li>
</ul> </ul>
<p> <p>
Otherwise, using <i>"Take first link"</i> ensures you get the That should be all that's needed as of November 2026.
proper update but will show pseudo versions.
</p> </p>
</div> </div>
@@ -108,7 +106,7 @@
>[fdroid.Hyperling.com]</a> >[fdroid.Hyperling.com]</a>
or or
<a href="https://fdroid.link/#https://fdroid.hyperling.com/fdroid/repo"> <a href="https://fdroid.link/#https://fdroid.hyperling.com/fdroid/repo">
[open directly with F-Droid]</a> [open with F-Droid]</a>
</li> </li>
</ul> </ul>
<p> <p>
@@ -125,12 +123,37 @@
<div class="row center text"> <div class="row center text">
<div class="col-12 text border" id="expense"> <div class="col-4 text border" id="sunset">
<a href="https://git.hyperling.com/me/flutter-sunset-alarm/releases"
target="_blank" rel="noopener noreferrer">
<figure>
<img class="app-icon" loading="lazy" alt="<<sunset.png>>"
src="https://git.hyperling.com/me/flutter-sunset-alarm/raw/branch/main/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png"
>
<figcaption>
Sunset Alarm
</figcaption>
</figure>
</a>
<p>
Set an alarm time based on sunset. (Linux & Android)
</p>
<p>
[<a href="https://git.hyperling.com/me/flutter-sunset-alarm/releases/download/latest/sunset_alarm-arm64-v8a-release.apk/"
target="_blank" rel="noopener noreferrer">APK</a>]
[<a href="https://git.hyperling.com/me/flutter-sunset-alarm/"
target="_blank" rel="noopener noreferrer">Source Code</a>]
[<a href="https://git.hyperling.com/me/flutter-sunset-alarm/releases"
target="_blank" rel="noopener noreferrer">Obtainium URL</a>]
</p>
</div>
<div class="col-4 text border" id="expense">
<a href="https://git.hyperling.com/me/flutter-expense-tracker/releases" <a href="https://git.hyperling.com/me/flutter-expense-tracker/releases"
target="_blank" rel="noopener noreferrer"> target="_blank" rel="noopener noreferrer">
<figure> <figure>
<img class="app-icon" loading="lazy" alt="<<expense.png>>" <img class="app-icon" loading="lazy" alt="<<expense.png>>"
src="/files/media/icons/expense.png" src="https://git.hyperling.com/me/flutter-expense-tracker/raw/branch/main/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png"
> >
<figcaption> <figcaption>
Recurring Expense Tracker Recurring Expense Tracker
@@ -140,24 +163,25 @@
<p> <p>
Keep track of repeating expenses and Keep track of repeating expenses and
view projections of their effect on your finances. view projections of their effect on your finances.
First app written with Flutter. (Linux & Android)
</p> </p>
<p> <p>
<!--[<s><a>F-Droid</a></s>]--> [<a href="https://git.hyperling.com/me/flutter-expense-tracker/releases/download/latest/ExpenseTracker.apk"
target="_blank" rel="noopener noreferrer">APK</a>]
[<a href="https://git.hyperling.com/me/flutter-expense-tracker/" [<a href="https://git.hyperling.com/me/flutter-expense-tracker/"
target="_blank" rel="noopener noreferrer">Source Code</a>] target="_blank" rel="noopener noreferrer">Source Code</a>]
[<a href="https://git.hyperling.com/me/flutter-expense-tracker/releases" [<a href="https://git.hyperling.com/me/flutter-expense-tracker/releases"
target="_blank" rel="noopener noreferrer">APKs / Obtainium URL</a>] target="_blank" rel="noopener noreferrer">Obtainium URL</a>]
</p> </p>
</div> </div>
<div class="col-12 text border" id="timer"> <div class="col-4 text border" id="timer">
<a href="https://git.hyperling.com/me/android-infinite-timer/releases" <a href="https://git.hyperling.com/me/android-infinite-timer/releases"
target="_blank" rel="noopener noreferrer" target="_blank" rel="noopener noreferrer"
> >
<figure> <figure>
<img class="app-icon" loading="lazy" alt="<<infinitetimer.png>>" <img class="app-icon" loading="lazy" alt="<<infinitetimer.png>>"
src="/files/media/icons/infinitetimer.png" src="https://git.hyperling.com/me/android-infinite-timer/raw/branch/main/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png"
> >
<figcaption> <figcaption>
Infinite Timer Infinite Timer
@@ -170,27 +194,28 @@
<p> <p>
<!--[<a href="https://play.google.com/store/apps/details?id=com.hyperling.apps.infinitetimer" <!--[<a href="https://play.google.com/store/apps/details?id=com.hyperling.apps.infinitetimer"
target="_blank" rel="noopener noreferrer">Play Store</a>]--> target="_blank" rel="noopener noreferrer">Play Store</a>]-->
[<a href="https://git.hyperling.com/me/android-infinite-timer/releases/download/latest/InfiniteTimer.apk"
target="_blank" rel="noopener noreferrer">APK</a>]
[<a href="https://git.hyperling.com/me/android-infinite-timer/" [<a href="https://git.hyperling.com/me/android-infinite-timer/"
target="_blank" rel="noopener noreferrer">Source Code</a>] target="_blank" rel="noopener noreferrer">Source Code</a>]
[<a href="https://git.hyperling.com/me/android-infinite-timer/releases" [<a href="https://git.hyperling.com/me/android-infinite-timer/releases"
target="_blank" rel="noopener noreferrer">APKs / Obtainium URL</a>] target="_blank" rel="noopener noreferrer">Obtainium URL</a>]
</p> </p>
<!--<p>
<s>
[<a target="_blank" rel="noopener noreferrer">F-Droid</a>]
</s>
</p>-->
</div> </div>
<div class="col-12 text border" id="ctfu"> </div>
<div class="row center text">
<div class="col-3 text border" id="ctfu">
<a href="https://git.hyperling.com/me/android-carb-up/releases" <a href="https://git.hyperling.com/me/android-carb-up/releases"
target="_blank" rel="noopener noreferrer"> target="_blank" rel="noopener noreferrer">
<figure> <figure>
<img class="app-icon" loading="lazy" alt="<<ctfu.png>>" <img class="app-icon" loading="lazy" alt="<<ctfu.png>>"
src="/files/media/icons/ctfu.png" src="https://git.hyperling.com/me/android-carb-up/raw/branch/main/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png"
> >
<figcaption> <figcaption>
Carb Up! BETA Carb Up!
</figcaption> </figcaption>
</figure> </figure>
</a> </a>
@@ -198,26 +223,21 @@
Calculate cost-effective foods on a High Carb Low Fat lifestyle. Calculate cost-effective foods on a High Carb Low Fat lifestyle.
</p> </p>
<p> <p>
<!--[<a href="https://play.google.com/store/apps/details?id=com.hyperling.carbupbeta" [<a href="https://git.hyperling.com/me/android-carb-up/releases/download/latest/CarbUp.apk"
target="_blank" rel="noopener noreferrer">Play Store</a>]--> target="_blank" rel="noopener noreferrer">APK</a>]
[<a href="https://git.hyperling.com/me/android-carb-up/" [<a href="https://git.hyperling.com/me/android-carb-up/"
target="_blank" rel="noopener noreferrer">Source Code</a>] target="_blank" rel="noopener noreferrer">Source Code</a>]
[<a href="https://git.hyperling.com/me/android-carb-up/releases" [<a href="https://git.hyperling.com/me/android-carb-up/releases"
target="_blank" rel="noopener noreferrer">APKs / Obtainium URL</a>] target="_blank" rel="noopener noreferrer">Obtainium URL</a>]
</p> </p>
<!--<p>
<s>
[<a target="_blank" rel="noopener noreferrer">F-Droid</a>]
</s>
</p>-->
</div> </div>
<div class="col-12 text border" id="sleep"> <div class="col-3 text border" id="sleep">
<a href="https://git.hyperling.com/me/android-45-minute-rule/releases" <a href="https://git.hyperling.com/me/android-45-minute-rule/releases"
target="_blank" rel="noopener noreferrer"> target="_blank" rel="noopener noreferrer">
<figure> <figure>
<img class="app-icon" loading="lazy" alt="<<t45mr.png>>" <img class="app-icon" loading="lazy" alt="<<t45mr.png>>"
src="/files/media/icons/t45mr.png" src="https://git.hyperling.com/me/android-45-minute-rule/raw/branch/main/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png"
> >
<figcaption> <figcaption>
45 Minute Rule 45 Minute Rule
@@ -230,24 +250,21 @@
<p> <p>
<!--[<a href="https://play.google.com/store/apps/details?id=com.hyperling.apps.the45minuterule" <!--[<a href="https://play.google.com/store/apps/details?id=com.hyperling.apps.the45minuterule"
target="_blank" rel="noopener noreferrer">Play Store</a>]--> target="_blank" rel="noopener noreferrer">Play Store</a>]-->
[<a href="https://git.hyperling.com/me/android-45-minute-rule/releases/download/latest/The45MinuteRule.apk"
target="_blank" rel="noopener noreferrer">APK</a>]
[<a href="https://git.hyperling.com/me/android-45-minute-rule/" [<a href="https://git.hyperling.com/me/android-45-minute-rule/"
target="_blank" rel="noopener noreferrer">Source Code</a>] target="_blank" rel="noopener noreferrer">Source Code</a>]
[<a href="https://git.hyperling.com/me/android-45-minute-rule/releases" [<a href="https://git.hyperling.com/me/android-45-minute-rule/releases"
target="_blank" rel="noopener noreferrer">APKs / Obtainium URL</a>] target="_blank" rel="noopener noreferrer">Obtainium URL</a>]
</p> </p>
<!--<p>
<s>
[<a target="_blank" rel="noopener noreferrer">F-Droid</a>]
</s>
</p>-->
</div> </div>
<div class="col-12 text border" id="tictactoe"> <div class="col-3 text border" id="tictactoe">
<a href="https://git.hyperling.com/me/android-tictactoe/releases" <a href="https://git.hyperling.com/me/android-tictactoe/releases"
target="_blank" rel="noopener noreferrer"> target="_blank" rel="noopener noreferrer">
<figure> <figure>
<img class="app-icon" loading="lazy" alt="<<tictactoe.png>>" <img class="app-icon" loading="lazy" alt="<<tictactoe.png>>"
src="/files/media/icons/tictactoe.png" src="https://git.hyperling.com/me/android-tictactoe/raw/branch/main/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png"
> >
<figcaption> <figcaption>
Tic-Tac-Toe Tic-Tac-Toe
@@ -259,21 +276,22 @@
Written to practice Kotlin/Compose. Written to practice Kotlin/Compose.
</p> </p>
<p> <p>
<!--[<s><a>F-Droid</a></s>]--> [<a href="https://git.hyperling.com/me/android-tictactoe/releases/download/latest/TicTacToe.apk"
target="_blank" rel="noopener noreferrer">APK</a>]
[<a href="https://git.hyperling.com/me/android-tictactoe/" [<a href="https://git.hyperling.com/me/android-tictactoe/"
target="_blank" rel="noopener noreferrer">Source Code</a>] target="_blank" rel="noopener noreferrer">Source Code</a>]
[<a href="https://git.hyperling.com/me/android-tictactoe/releases" [<a href="https://git.hyperling.com/me/android-tictactoe/releases"
target="_blank" rel="noopener noreferrer">APKs / Obtainium URL</a>] target="_blank" rel="noopener noreferrer">Obtainium URL</a>]
</p> </p>
</div> </div>
<div class="col-12 text border" id="games"> <div class="col-3 text border" id="games">
<a href="https://git.hyperling.com/me/android-hypergames/releases" <a href="https://git.hyperling.com/me/android-hypergames/releases"
target="_blank" rel="noopener noreferrer" target="_blank" rel="noopener noreferrer"
> >
<figure> <figure>
<img class="app-icon" loading="lazy" alt="<<hypergames.png>>" <img class="app-icon" loading="lazy" alt="<<hypergames.png>>"
src="/files/media/icons/hypergames.png" src="https://git.hyperling.com/me/android-hypergames/raw/branch/dev/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png"
> >
<figcaption> <figcaption>
HyperGames HyperGames
@@ -287,19 +305,15 @@
<p> <p>
<!--[<a href="https://play.google.com/store/apps/details?id=apps.hyperling.com.platformer" <!--[<a href="https://play.google.com/store/apps/details?id=apps.hyperling.com.platformer"
target="_blank" rel="noopener noreferrer">Play Store</a>]--> target="_blank" rel="noopener noreferrer">Play Store</a>]-->
[<a href="https://git.hyperling.com/me/android-hypergames/releases/download/latest/HyperGames.apk"
target="_blank" rel="noopener noreferrer">APK</a>]
[<a href="https://git.hyperling.com/me/android-hypergames/" [<a href="https://git.hyperling.com/me/android-hypergames/"
target="_blank" rel="noopener noreferrer">Source Code</a>] target="_blank" rel="noopener noreferrer">Source Code</a>]
[<a href="https://git.hyperling.com/me/android-hypergames/releases" [<a href="https://git.hyperling.com/me/android-hypergames/releases"
target="_blank" rel="noopener noreferrer">APKs / Obtainium URL</a>] target="_blank" rel="noopener noreferrer">Obtainium URL</a>]
</p> </p>
<!--
<p>
<s>
[<a target="_blank" rel="noopener noreferrer">F-Droid</a>]
</s>
</p>
-->
</div> </div>
</div> </div>
<div class="row" id="other"> <div class="row" id="other">
+6 -2
View File
@@ -29,8 +29,12 @@
height: 237px; /* 69*3[banner stripes] + 15*2[padding top+bot] */ height: 237px; /* 69*3[banner stripes] + 15*2[padding top+bot] */
} }
.banner-image01 { .banner-image01 {
background-image: url("/files/media/icons/home.jpg"); background-image: url("/banner-image01.jpg");
} }
.banner-image02 { .banner-image02 {
background-image: url("/files/media/icons/contact.jpg"); background-image: url("/banner-image02.jpg");
}
.banner-anchor {
text-decoration: none;
} }
+19 -4
View File
@@ -5,14 +5,15 @@
$GLOBALS["SHOW_BANNER_PICS"] = true; $GLOBALS["SHOW_BANNER_PICS"] = true;
} }
$show_pics = $GLOBALS["SHOW_BANNER_PICS"]; $show_pics = $GLOBALS["SHOW_BANNER_PICS"];
$banner_width = $show_pics ? 6 : 12; $banner_width_desktop = $show_pics ? 6 : 12;
$banner_width_mobile = $show_pics ? 8 : 12;
?> ?>
<a href='/about/'> <a class="banner-anchor" href='/'>
<div class="row"> <div class="row banner-desktop">
<?php if ($show_pics) echo ' <?php if ($show_pics) echo '
<div class="col-3 header center banner-image banner-image01"></div> <div class="col-3 header center banner-image banner-image01"></div>
';?> ';?>
<div class="col-<?php echo "$banner_width"; ?> header"> <div class="col-<?php echo "$banner_width_desktop"; ?> header">
<div class="banner-top">Peace</div> <div class="banner-top">Peace</div>
<div class="banner-middle">Love</div> <div class="banner-middle">Love</div>
<div class="banner-bottom">Happiness</div> <div class="banner-bottom">Happiness</div>
@@ -21,4 +22,18 @@
<div class="col-3 header center banner-image banner-image02"></div> <div class="col-3 header center banner-image banner-image02"></div>
';?> ';?>
</div> </div>
<div class="row banner-mobile">
<?php if ($show_pics) echo '
<div class="col-2 header center banner-image banner-image01"></div>
';?>
<div class="col-<?php echo "$banner_width_mobile"; ?> header">
<div class="banner-top">Peace</div>
<div class="banner-middle">Love</div>
<div class="banner-bottom">Happiness</div>
</div>
<?php if ($show_pics) echo '
<div class="col-2 header center banner-image banner-image02"></div>
';?>
</div>
</a> </a>
+21
View File
@@ -0,0 +1,21 @@
<!-- Old, no longer needed
<link rel="icon" sizes="32x32" href="/favicon.ico">
<link rel="icon" sizes="192x192" href="/favicon.ico">
-->
<!-- https://favicon.io, added the ?v=20261102 manually. -->
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png?v=20261102">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png?v=20261102">
<!-- Not needed, covered in the realfavicongenerator section.
<link rel="manifest" href="/site.webmanifest">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
-->
<!-- https://realfavicongenerator.net , added the sizes=any manually. -->
<link rel="icon" type="image/png" href="/favicon-96x96.png?v=20261102" sizes="96x96" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg?v=20261102" sizes="any" />
<link rel="shortcut icon" href="/favicon.ico?v=20261102" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png?v=20261102" />
<meta name="apple-mobile-web-app-title" content="Hyperling" />
<link rel="manifest" href="/site.webmanifest?v=20261102" />
+60 -17
View File
@@ -7,28 +7,71 @@
} }
/* */ /* */
p,li,code,a,pre { /*** Fonts ***/
font-size: medium;
html, body {
font-family: system-ui, sans-serif;
} }
b,figcaption { /* * /
font-size: large; h1, h2, h3, h4, h5, h6 {
font-weight: bold; font-family: 'Space Grotesk', Georgia, system-ui, Consolas, sans-serif;
}
/* */
code, pre, .mono {
font-family:
ui-monospace,
SFMono-Regular,
Menlo, Monaco,
Consolas,
"Liberation Mono",
"Courier New",
monospace
;
} }
strong,img { /*** Font Sizes ***/
font-size: larger;
font-weight: bolder; html {
font-size: 16px;
/* Attempt to prevent Firefox sizing inconsistencies. * /
-webkit-text-size-adjust: 100%;
-moz-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
text-size-adjust: 100%;
/* */
} }
h6,h5 { code, pre { font-size: 0.8rem; }
font-size: larger;
}
h4,h3 { body { font-size: 1rem; }
font-size: x-large; p, li, a { font-size: 1rem; }
}
h2,h1 { b { font-size: 1.05rem; }
font-size: xx-large; figcaption { font-size: 1.1rem; }
} strong { font-size: 1.2rem; }
img { font-size: 1.25rem; }
/* More Subtle */
h6 { font-size: 1.3rem; }
h5 { font-size: 1.4rem; }
h4 { font-size: 1.5rem; }
h3 { font-size: 1.6rem; }
h2 { font-size: 1.7rem; }
h1 { font-size: 1.8rem; }
/* */
/* More Pronounced * /
h6 { font-size: 1.30rem; }
h5 { font-size: 1.55rem; }
h4 { font-size: 1.80rem; }
h3 { font-size: 1.95rem; }
h2 { font-size: 2.10rem; }
h1 { font-size: 2.35rem; }
/* */
/*** Font Weights ***/
b, figcaption { font-weight: bold; }
strong, img { font-weight: bolder; }
+5 -6
View File
@@ -10,12 +10,9 @@
<html lang="en"> <html lang="en">
<head> <head>
<title>Hyperling<?php echo($GLOBALS["HEADER_TITLE"]); ?></title> <title>Hyperling<?php echo($GLOBALS["HEADER_TITLE"]); ?></title>
<link rel="icon" sizes="32x32" <?php
href="/files/media/icons/favicon.ico" include "favicon.php";
> ?>
<link rel="icon" sizes="192x192"
href="/files/media/icons/favicon.ico"
>
<!-- CSS --> <!-- CSS -->
<style> <style>
<?php include "main.css"; ?> <?php include "main.css"; ?>
@@ -42,4 +39,6 @@
<meta name="twitter:title" content="Hyperling"> <meta name="twitter:title" content="Hyperling">
<meta name="twitter:description" content="Apps, eBooks, media, and other resources from the brands Hyperling and HyperVegan."> <meta name="twitter:description" content="Apps, eBooks, media, and other resources from the brands Hyperling and HyperVegan.">
<meta name="twitter:image" content="https://hyperling.com/files/media/icons/home.jpg"> <meta name="twitter:image" content="https://hyperling.com/files/media/icons/home.jpg">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head> </head>
+51 -18
View File
@@ -21,24 +21,57 @@
.col-11 {width: 91.66%;} .col-11 {width: 91.66%;}
.col-12 {width: 100%;} .col-12 {width: 100%;}
.row {
border: 1px solid #131313;
border-radius: 4px;
display: flex;
flex-wrap: wrap;
align-items: stretch;
}
[class*="col-"] { [class*="col-"] {
float: left;
padding: 15px; padding: 15px;
/* FORTESTING, otherwise disable */ /* FORTESTING, otherwise disable */
/*border: 1px solid green;*/ /*border: 1px solid green;*/
} }
/* Ensure columns are respected as if they always exist. */ /* Handle mobile devices a bit better, making columns break out as rows. */
.row::after {
content: ""; .banner-desktop { display: flex; }
clear: both; .banner-mobile { display: none; }
display: table;
/* Phones */
@media (max-width: 767px) {
[class*="col-"] {
width: 100%;
}
} }
.row { /* Tablets */
border: 1px solid #131313; @media (min-width: 768px) and (max-width: 1023px) {
border-radius: 4px; .col-1, .col-2, .col-3, .col-4, .col-5, .col-6 {
width: 50%;
}
.col-7, .col-8, .col-9, .col-10, .col-11, .col-12 {
width: 100%;
}
}
/* Both Mobiles */
@media (max-width: 1023px) {
[class*="col-"] {
float: none;
display: block;
}
.banner-image {display: none; }
.banner-desktop { display: none; }
.banner-mobile { display: flex; }
}
/* Desktop */
@media (min-width: 1024px) {
} }
/** Make the menu items centered and layout horizontal. **/ /** Make the menu items centered and layout horizontal. **/
@@ -51,12 +84,12 @@
.menu-list { .menu-list {
text-align: center; text-align: center;
list-style-type: none; list-style-type: none;
padding-left: 0px;
} }
.menu_item { .menu-item {
display: inline-block; display: inline-block;
padding: 0px;
white-space: nowrap; white-space: nowrap;
margin: 0.1rem;
padding: 0.1rem;
} }
/** Be able to position anything easily. **/ /** Be able to position anything easily. **/
@@ -77,8 +110,8 @@
/** Extra objects which need borders **/ /** Extra objects which need borders **/
.border { .border {
border: 1px solid #131313; border: 1px solid #131313;
border-radius: 4px; border-radius: 4px;
} }
/** Explicitly remove border from some objects. **/ /** Explicitly remove border from some objects. **/
@@ -125,10 +158,10 @@
overflow-x: scroll; overflow-x: scroll;
overflow-y: hidden; overflow-y: hidden;
padding: 10px; padding: 10px;
border: 2px solid #131313; border: 2px solid #131313;
border-radius: 8px; border-radius: 8px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
} }
body { body {
+44 -25
View File
@@ -1,6 +1,6 @@
#!/usr/bin/php #!/usr/bin/php
<!--
<div class="row header menu"> <div class="row header menu">
<!--
<ul class="menu-list"> <ul class="menu-list">
<li class="col-3 menu-item"><a href="/">Home</a></li> <li class="col-3 menu-item"><a href="/">Home</a></li>
<li class="col-3 menu-item"><a href="/about/">About</a></li> <li class="col-3 menu-item"><a href="/about/">About</a></li>
@@ -33,29 +33,48 @@
</li> </li>
<li class="col-3 menu-item"></li> <li class="col-3 menu-item"></li>
</ul> </ul>
--> </div>
-->
<p class="menu-list"> <div class="menu row header center">
Main: <div class="menu-list col-12">
<a href="/apps/">Apps</a> <strong>Main:</strong>
<a href="/about/">About</a> <a class="menu-item" href="/apps/">Apps</a>
<a href="/contact/">Contact</a> <a class="menu-item" href="/about/">About</a>
<a href="/support/">Support</a> <a class="menu-item" href="/contact/">Contact</a>
| Media: <a class="menu-item" href="/support/">Support</a>
<a href="https://git.hyperling.com/me/" <strong>Media:</strong>
target="_blank" rel="noopener noreferrer">Code</a> <a class="menu-item"
<a href="https://works.hyperling.com/tags/books/" href="https://git.hyperling.com/me/"
target="_blank" rel="noopener noreferrer">Books</a> target="_blank" rel="noopener noreferrer"
<a href="https://works.hyperling.com/videos/" >Code</a>
target="_blank" rel="noopener noreferrer">Videos</a> <a class="menu-item"
<a href="/photos/">Photos</a> href="https://works.hyperling.com/categories/books/"
| Blog: target="_blank" rel="noopener noreferrer"
<a href="https://blog.hyperling.com/categories/articles/" >Books</a>
target="_blank" rel="noopener noreferrer">Articles</a> <a class="menu-item"
<a href="https://recipes.hyperling.com/categories/recipes/" href="https://works.hyperling.com/videos/"
target="_blank" rel="noopener noreferrer">Recipes</a> target="_blank" rel="noopener noreferrer"
<a href="https://blog.hyperling.com/categories/musings/" >Videos</a>
target="_blank" rel="noopener noreferrer">Poetry</a> <a class="menu-item"
<a href="https://recipes.hyperling.com/categories/guides/" href="/photos/"
target="_blank" rel="noopener noreferrer">Guides</a> >Photos</a>
<strong>Blog:</strong>
<a class="menu-item"
href="https://blog.hyperling.com/categories/articles/"
target="_blank" rel="noopener noreferrer"
>Articles</a>
<a class="menu-item"
href="https://recipes.hyperling.com/categories/recipes/"
target="_blank" rel="noopener noreferrer"
>Recipes</a>
<a class="menu-item"
href="https://blog.hyperling.com/categories/musings/"
target="_blank" rel="noopener noreferrer"
>Poetry</a>
<a class="menu-item"
href="https://recipes.hyperling.com/categories/guides/"
target="_blank" rel="noopener noreferrer"
>Guides</a>
</div>
</div> </div>
+24 -4
View File
@@ -6,6 +6,16 @@
<h2 class="col-12 header">Announcements</h2> <h2 class="col-12 header">Announcements</h2>
</div> </div>
<div class="row">
<div class="col-12 text">
<strong><a href="/apps/#sunset/">2026-10-01</a></strong>
<p>
Sunset Alarm has been finished! Check it out
<a href="/apps/#sunset">here</a>.
</p>
</div>
</div>
<div class="row"> <div class="row">
<div class="col-12 text"> <div class="col-12 text">
<strong><a href="https://fdroid.hyperling.com/">2026-07-04</a></strong> <strong><a href="https://fdroid.hyperling.com/">2026-07-04</a></strong>
@@ -15,6 +25,12 @@
target="_blank" rel="noopener noreferrer" target="_blank" rel="noopener noreferrer"
>Find it here</a>! >Find it here</a>!
</p> </p>
<p>
Watch the announcement:
<a href="https://odysee.com/@HyperVegan:2/20260707-HyperVegan-FDroidRepo:a"
target="_blank" rel="noopener noreferrer"
>HyperVegan: "F-Droid Repository"</a>
</p>
</div> </div>
</div> </div>
@@ -36,9 +52,10 @@
</p> </p>
";?> ";?>
<p> <p>
Watch the announcement:
<a href="https://odysee.com/@HyperVegan:2/20251003-Announcements:0" <a href="https://odysee.com/@HyperVegan:2/20251003-Announcements:0"
target="_blank" rel="noopener noreferrer" target="_blank" rel="noopener noreferrer"
>Watch the announcement here | (HyperVegan: "Announcements: Skipped Midfest, Voluntary Sovereignty eBook, CheapRVLiving Interview")</a> >HyperVegan: "Announcements: Skipped Midfest, Voluntary Sovereignty eBook, CheapRVLiving Interview"</a>
</p> </p>
</div> </div>
</div> </div>
@@ -61,9 +78,10 @@
</p> </p>
";?> ";?>
<p> <p>
Watch the announcement:
<a href="https://odysee.com/@HyperVegan:2/20250402-HyperVegan-ExpenseTrackerApp:4" <a href="https://odysee.com/@HyperVegan:2/20250402-HyperVegan-ExpenseTrackerApp:4"
target="_blank" rel="noopener noreferrer" target="_blank" rel="noopener noreferrer"
>Watch the announcement here | (HyperVegan: "Expense Tracker App")</a> >HyperVegan: "Expense Tracker App"</a>
</p> </p>
</div> </div>
</div> </div>
@@ -88,9 +106,10 @@
</p> </p>
";?> ";?>
<p> <p>
Watch the announcement:
<a href="https://odysee.com/@HyperVegan:2/20240306_MyHealthProtocol-Book:9" <a href="https://odysee.com/@HyperVegan:2/20240306_MyHealthProtocol-Book:9"
target="_blank" rel="noopener noreferrer" target="_blank" rel="noopener noreferrer"
>Watch the announcement here | (HyperVegan: "My Health Protocol | eBook")</a> >HyperVegan: "My Health Protocol | eBook"</a>
</p> </p>
</div> </div>
</div> </div>
@@ -112,9 +131,10 @@
</p> </p>
";?> ";?>
<p> <p>
Watch the announcement:
<a href="https://odysee.com/@HyperVegan:2/20240401_NewYearNewApp:1" <a href="https://odysee.com/@HyperVegan:2/20240401_NewYearNewApp:1"
target="_blank" rel="noopener noreferrer" target="_blank" rel="noopener noreferrer"
>Watch the announcement here | (HyperVegan: "New Year, New App")</a> >HyperVegan: "New Year, New App"</a>
</p> </p>
</div> </div>
</div> </div>
+6 -6
View File
@@ -22,25 +22,25 @@
<br> <br>
<a href="monero:4ATk6owoMki46CuVfyAHS57FB5deqVFudTsaifQC1cfmcaQemgPEftcjZcW9DmcyfrfdRjxHQ9m4JAVSorYTgm6h8JnT7ao"> <a href="monero:4ATk6owoMki46CuVfyAHS57FB5deqVFudTsaifQC1cfmcaQemgPEftcjZcW9DmcyfrfdRjxHQ9m4JAVSorYTgm6h8JnT7ao">
<strong><code>XMR | Monero</code></strong> <b class="mono">XMR | Monero</b>
</a> </a>
<div class="code"><code>4ATk6owoMki46CuVfyAHS57FB5deqVFudTsaifQC1cfmcaQemgPEftcjZcW9DmcyfrfdRjxHQ9m4JAVSorYTgm6h8JnT7ao</code></div> <div class="code"><code>4ATk6owoMki46CuVfyAHS57FB5deqVFudTsaifQC1cfmcaQemgPEftcjZcW9DmcyfrfdRjxHQ9m4JAVSorYTgm6h8JnT7ao</code></div>
<br> <br>
<a href="bitcoin:bc1qsfe8dkvry3d34kztz449gkq67wq8fu2nkgfkh0?"> <a href="bitcoin:bc1qsfe8dkvry3d34kztz449gkq67wq8fu2nkgfkh0?">
<strong><code>BTC | Bitcoin</code></strong> <b class="mono">BTC | Bitcoin</b>
</a> </a>
<div class="code"><code>bc1qsfe8dkvry3d34kztz449gkq67wq8fu2nkgfkh0</code></div> <div class="code"><code>bc1qsfe8dkvry3d34kztz449gkq67wq8fu2nkgfkh0</code></div>
<br> <br>
<a href="bitcoincash:qzr00gaqeldlu3amjdn59f2y73276v8jwu6vanays2"> <a href="bitcoincash:qzr00gaqeldlu3amjdn59f2y73276v8jwu6vanays2">
<strong><code>BCH | Bitcoin Cash</code></strong> <b class="mono">BCH | Bitcoin Cash</b>
</a> </a>
<div class="code"><code>qzr00gaqeldlu3amjdn59f2y73276v8jwu6vanays2</code></div> <div class="code"><code>qzr00gaqeldlu3amjdn59f2y73276v8jwu6vanays2</code></div>
<br> <br>
<a href="litecoin:ltc1qavmpu5d6ljntxsd6jj548m4yys83zwscl0dzkx"> <a href="litecoin:ltc1qavmpu5d6ljntxsd6jj548m4yys83zwscl0dzkx">
<strong><code>LTC | Litecoin</code></strong> <b class="mono">LTC | Litecoin</b>
</a> </a>
<div class="code"><code>ltc1qavmpu5d6ljntxsd6jj548m4yys83zwscl0dzkx</code></div> <div class="code"><code>ltc1qavmpu5d6ljntxsd6jj548m4yys83zwscl0dzkx</code></div>
<br> <br>
@@ -67,7 +67,7 @@
<div class="header"> <div class="header">
<br> <br>
<strong><code>Zelle</code></strong> <b class="mono">Zelle</b>
<div class="code"> <div class="code">
<code>me@hyperling.com</code> <code>me@hyperling.com</code>
<br> <br>
@@ -76,7 +76,7 @@
</div> </div>
<br> <br>
<strong><code>Venmo</code></strong> <b class="mono">Venmo</b>
<div class="code"> <div class="code">
<code> <code>
@HyperVegan @HyperVegan
+24 -10
View File
@@ -80,28 +80,42 @@ fi
log "Check if any system dependencies need installed." log "Check if any system dependencies need installed."
progs="" progs=""
if [[ ! `which php` ]]; then if [[ ! `which php 2>/dev/null` ]]; then
echo "- Installing PHP" echo "- Installing PHP"
progs="$progs php-cli" progs_apt="$progs_apt php-cli"
progs_pm="$progs_pm php"
fi fi
if [[ ! `which node` ]]; then if [[ ! `which node 2>/dev/null` ]]; then
echo "- Installing Node" echo "- Installing Node"
progs="$progs nodejs" progs="$progs nodejs"
fi fi
if [[ ! `which npm` ]]; then if [[ ! `which npm 2>/dev/null` ]]; then
echo "- Installing NPM" echo "- Installing NPM"
progs="$progs npm" progs_apt="$progs_apt npm"
progs_pm="$progs_pm " # comes with Node.js
fi fi
if [[ ! `which curl` ]]; then if [[ ! `which curl 2>/dev/null` ]]; then
echo "- Installing Curl" echo "- Installing Curl"
progs="$progs curl" progs="$progs curl"
fi fi
if [[ ! `which ps` ]]; then if [[ ! `which ps 2>/dev/null` ]]; then
echo "- Installing PS" echo "- Installing PS"
progs="$progs procps" progs_apt="$progs_apt procps"
progs_pm="$progs_pm procps-ng"
fi fi
if [[ -n "$progs" ]]; then if [[ -n "$progs" || -n "$progs_apt" || -n "$progs_pm" ]]; then
$sudo apt-get install -y $progs if [[ `which apt 2>/dev/null` ]]; then
echo "Using APT..."
progs="$progs $progs_apt"
$sudo apt-get install -y $progs
elif [[ `which pacman 2>/dev/null` ]]; then
echo "Using pacman..."
progs="$progs $progs_pm"
$sudo pacman -Sy --noconfirm $progs
else
echo "ERROR: Please install these programs then try again: $progs"
exit 1
fi
fi fi
# Directories and allowed page types are executable, others are not. # Directories and allowed page types are executable, others are not.