first release
All checks were successful
NPM Audit Check / Check NPM audit (push) Successful in -2m11s
App Image CI / Build app image (push) Successful in 46s

This commit is contained in:
2025-10-22 00:56:17 -05:00
parent 2e20859580
commit aa918ad435
10 changed files with 365 additions and 22 deletions

3
.gitignore vendored
View File

@@ -105,6 +105,7 @@ dist
assets/css/
assets/js/
assets/webp/
assets/images/webp/
assets/images/avif/
config/
distribution/

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

78
package-lock.json generated
View File

@@ -11,6 +11,7 @@
"dependencies": {
"ejs": "3.1.10",
"express": "5.1.0",
"ics": "^3.8.1",
"json5": "2.2.3"
},
"devDependencies": {
@@ -1015,6 +1016,17 @@
"node": ">=0.10.0"
}
},
"node_modules/ics": {
"version": "3.8.1",
"resolved": "https://registry.npmjs.org/ics/-/ics-3.8.1.tgz",
"integrity": "sha512-UqQlfkajfhrS4pUGQfGIJMYz/Jsl/ob3LqcfEhUmLbwumg+ZNkU0/6S734Vsjq3/FYNpEcZVKodLBoe+zBM69g==",
"license": "ISC",
"dependencies": {
"nanoid": "^3.1.23",
"runes2": "^1.1.2",
"yup": "^1.2.0"
}
},
"node_modules/immutable": {
"version": "5.1.4",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz",
@@ -1199,6 +1211,24 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/nanoid": {
"version": "3.3.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/negotiator": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
@@ -1288,6 +1318,12 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/property-expr": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz",
"integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==",
"license": "MIT"
},
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -1386,6 +1422,12 @@
"node": ">= 18"
}
},
"node_modules/runes2": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/runes2/-/runes2-1.1.4.tgz",
"integrity": "sha512-LNPnEDPOOU4ehF71m5JoQyzT2yxwD6ZreFJ7MxZUAoMKNMY1XrAo60H1CUoX5ncSm0rIuKlqn9JZNRrRkNou2g==",
"license": "MIT"
},
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
@@ -1567,6 +1609,12 @@
"node": ">= 0.8"
}
},
"node_modules/tiny-case": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz",
"integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==",
"license": "MIT"
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -1590,6 +1638,24 @@
"node": ">=0.6"
}
},
"node_modules/toposort": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
"integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==",
"license": "MIT"
},
"node_modules/type-fest": {
"version": "2.19.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
"integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
"license": "(MIT OR CC0-1.0)",
"engines": {
"node": ">=12.20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/type-is": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
@@ -1661,6 +1727,18 @@
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"license": "ISC"
},
"node_modules/yup": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/yup/-/yup-1.7.1.tgz",
"integrity": "sha512-GKHFX2nXul2/4Dtfxhozv701jLQHdf6J34YDh2cEkpqoo8le5Mg6/LrdseVLrFarmFygZTlfIhHx/QKfb/QWXw==",
"license": "MIT",
"dependencies": {
"property-expr": "^2.0.5",
"tiny-case": "^1.0.3",
"toposort": "^2.0.2",
"type-fest": "^2.19.0"
}
}
}
}

View File

@@ -26,6 +26,7 @@
"dependencies": {
"ejs": "3.1.10",
"express": "5.1.0",
"ics": "^3.8.1",
"json5": "2.2.3"
},
"devDependencies": {

View File

@@ -3,13 +3,15 @@ import crypto from 'crypto';
import express from 'express';
import bodyParser from 'body-parser';
import type { Express } from 'express';
import { createEvent} from 'ics';
interface WebConfig {
sessionSecret?: string;
port?: number;
secure?: boolean;
}
const DATE = process.env['DATE'] || 'November 1st';
const TIME = process.env['TIME'] || '2:30PM-5:30PM';
/**
* I still hate typescript.
*/
@@ -21,23 +23,17 @@ class Web {
private _webserver: http.Server | null = null;
private app: Express | null = null;
private port: number;
private options: WebConfig;
// private options: WebConfig;
constructor(options: WebConfig = {}) {
this.options = options;
// this.options = options;
this.port = notStupidParseInt(process.env['PORT']) || options['port'] as number || 8080;
}
initialize = async () => {
const options = this.options;
const sessionSecret = process.env['SESSIONSECRET'] || options.sessionSecret;
// const options = this.options;
const app: Express = this.app = express();
if (!sessionSecret) {
console.error('sessionSecret is required.');
throw new Error('sessionSecret is required.');
}
app.set('trust proxy', 1);
app.set('view engine', 'ejs');
app.set('view options', { outputFunctionName: 'echo' });
@@ -63,14 +59,53 @@ class Web {
app.get('/', (_, res) => {
res.render('index', {
page: {
title: 'Web',
titlesuffix: 'Home',
description: 'Homepage'
title: 'Madison End of 10 Install Party',
titlesuffix: 'Get help installing Linux',
description: `Windows 10 support is ending, but you may not need a brand-new PC! Sector67 in Madison, Wisconsin is hosting a Linux install party to help the community keep their current computers usable and up-to-date. Join us on ${DATE}`
},
date: DATE,
time: TIME
});
});
app.get('/os', (_, res) => {
res.render('os', {
page: {
title: 'Linux Distro Recommendations',
titlesuffix: 'madisonlinux.com',
description: 'Choosing a Linux distro can be overwhelming. Here are my personal recommendations for beginners and beyond.'
}
});
});
this._webserver = this.app.listen(this.port, () => console.log(`archery is running on port ${this.port}`));
app.get('/event.ics', (_, res) => {
createEvent({
uid: '1@madisonlinux.com',
start: [2025, 11, 1, 19, 30],
duration: { hours: 3, minutes: 0 },
title: 'Madison Linux Workshop',
description: 'Keep your current PC up-to-date by installing a free OS!',
location: '56 Corry St, Madison, WI 53704',
url: 'https://madisonlinux.com/',
geo: { lat: 43.0982199, lon: -89.3481373 },
status: 'CONFIRMED',
busyStatus: 'TENTATIVE',
organizer: { name: 'Cory Sanin', email: 'endof10@cory.sanin.dev' },
method: 'REQUEST'
}, (err, s) => {
if(err) {
console.error(err);
res.status(500).send('something went wrong.');
return;
}
res.set({
'Content-Type': 'text/calendar; charset=utf-8',
'Content-Disposition': 'attachment; filename="event.ics"'
}).send(s);
});
});
this._webserver = this.app.listen(this.port, () => console.log(`madisonlinux is running on port ${this.port}`));
}
close = () => {

89
styles/01-layout.scss Normal file
View File

@@ -0,0 +1,89 @@
html,
body {
min-height: 100%;
padding-bottom: 3em;
}
body {
line-height: 1.5;
font-family: Arial, Helvetica, sans-serif;
font-size: 14pt;
}
.content {
width: 80%;
width: calc(100% - 150px);
margin: auto;
}
.em {
font-style: italic;
}
h1 {
font-size: 3em;
}
h2 {
font-size: 2.25em;
}
p {
margin-bottom: .5em;
}
blockquote {
padding-left: 10px;
}
a {
font-weight: bold;
}
ul li {
list-style: disc;
}
img {
max-width: 100%;
}
.nav_links {
padding: .3em .5em;
text-align: center;
margin-bottom: 1em;
li {
display: inline;
a {
padding: .3em .5em;
}
}
}
.img-container {
overflow-x: auto;
max-width: 100%;
}
@media screen and (max-width:540px) {
.content {
width: 95%;
width: calc(100% - 50px);
}
h1 {
font-size: 2.3em;
}
h2 {
font-size: 2em;
}
}
@media screen and (max-width:450px) {
img {
max-width: initial;
}
}

29
styles/02-colors.scss Normal file
View File

@@ -0,0 +1,29 @@
body {
color: #fff;
background: #13417B;
background: linear-gradient(90deg, rgba(19, 65, 123, 1) 0%, rgba(25, 74, 136, 1) 50%, rgba(19, 65, 123, 1) 100%);
}
a, a:link, a:visited {
color: #fff;
}
blockquote {
border-left: 5px solid #fff;
}
.nav_links {
background-color: #fff;
color: #13417B;
li a {
color: #13417B;
text-decoration: none;
border-radius: .25em;
&:hover {
background-color: #13417B;
color: #fff;
}
}
}

View File

@@ -8,7 +8,62 @@
<body class="preload">
<%- include("navigation", locals) %>
<div class="content">
<h1>Hello World</h1>
<p><a href="https://www.sector67.org/">Sector67</a> presents...</p>
<h1>Linux Install Party Madison</h1>
<h2>Are you ready to reduce e-waste and save some money?</h2>
<p>
Microsoft ended support for Windows 10 on October 14th of this year.
</p>
<div class="img-container"><img src="/assets/images/webp/end-of-support.webp" alt="A screenshot of Windows Update reporting that Windows 10 has reached end of support"/></div>
<p>
If you see this message in your Windows Update section in the Settings app, this likely affects you.
</p>
<p>
Microsoft is offering free upgrades to Windows 11. <span class="em">But</span> some older hardware doesn't meet the Windows 11 requirements,
despite being fully capable machines.
</p>
<p>
Don't fret! You can upgrade your computer to a free alternative and we're here to help you do it!
</p>
<h2>Why?</h2>
<p>
If you bought your computer after 2010, there's most likely no reason to throw it out just yet.
By extending the life of your device, you're not only keeping it out of the landfills but also saving money!
</p>
<h2>Don't I need Windows 11?</h2>
<p>
Maybe not!
Many of the apps you use on a daily basis either work on Linux or have an open source equivalent.
We will help you install an OS that meets your needs and familiarize you with your new operating system.
</p>
<h2>What happens if I keep Windows 10?</h2>
<p>
Windows 10 is no longer receiving free security updates. Over time, more and more vulnerabilities will be discovered, putting your computer and your data at risk.
Microsoft has this to say on <a href="https://support.microsoft.com/en-us/windows/windows-10-support-has-ended-on-october-14-2025-2ca8b313-1946-43d3-b55c-2b95b107f281">their own website</a>:
<blockquote>
While you could continue to use a PC running Windows 10, without continued software and security updates, your PC will be at a greater risk for viruses and malware.
</blockquote>
</p>
<h2 id="event">Event Details</h2>
<p>
This completely free event will take place on <%= date %> from <%= time %>.
</p>
<p>
Come meet us at Sector67:<br/>56 Corry St, Madison, WI 53704
</p>
<p>
If you have additional questions about the event, email me at <a href="mailto:endof10@cory.sanin.dev">endof10@cory.sanin.dev</a>
</p>
<h2>What to bring</h2>
<p>
If it's a laptop, bring the device and its charging cable.
</p>
<p>
If it's a desktop, only bring the tower. Monitors, keyboards, and mice will be provided on-site.
</p>
<p>
If you're able, please back up your personal data to a flash drive or external drive and bring that with. Otherwise we will have storage devices available if necessary.
</p>
</div>
</body>
</html>

View File

@@ -1,11 +1,9 @@
<div class="navigation">
<div class="nav_logo">
<a href="/"><img src="/assets/svg/logo.svg" alt="Logo" /></a>
</div>
<nav>
<ul class="nav_links">
<li><a href="/">Home</a></li>
<li><a href="/ky">Away</a></li>
<li><a href="/#event">Event&nbsp;Details</a></li>
<li><a href="/os">OS&nbsp;Recommendations</a></li>
</ul>
</nav>
</div>

57
views/os.ejs Normal file
View File

@@ -0,0 +1,57 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<%- include("head", locals) %>
</head>
<body class="preload">
<%- include("navigation", locals) %>
<div class="content">
<h1>Recommended OSes</h1>
<p>
There are countless choices when it comes to alternatives to Windows. Here are my personal
recommendations to help you avoid decision paralysis if you decide to do it yourself.
</p>
<h2>Beginner Friendly</h2>
<p>
I believe these make the most sense for anyone looking for a general purpose OS.
Beginner friendly distros should have a simple app store and actively encourage users to keep the system
up-to-date.
</p>
<p>
<ul>
<li><a href="https://www.linuxmint.com/">Linux Mint, Cinnamon Edition</a></li>
<li><a href="https://manjaro.org/">Manjaro with KDE Plasma</a></li>
<li><a href="https://chromeos.google/products/chromeos-flex/">ChromeOS Flex</a></li>
</ul>
</p>
<h2>Advanced Users</h2>
<p>These are my picks for those who aren't afraid of using or learning the command line.</p>
<p>
<ul>
<li><a href="https://fedoraproject.org/">Fedora Linux</a></li>
<li><a href="https://endeavouros.com/">EndeavourOS</a></li>
</ul>
</p>
<h2>Gaming Focused</h2>
<p>
For gaming-focused PC's, of course most general purpose distro will do. However, there are a couple
options worth your consideration.
</p>
<p>
If you want an experience similar to SteamOS on the Steam Deck, Bazzite has you covered.
</p>
<p>
CachyOS is a distro based on Arch that specializes in optimizing for speed.
</p>
<p>
<ul>
<li><a href="https://bazzite.gg/">Bazzite</a></li>
<li><a href="https://cachyos.org/">CachyOS</a></li>
</ul>
</p>
</div>
</body>
</html>