-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #40 from stuartlangridge/main
Add past events to the website
- Loading branch information
Showing
215 changed files
with
688 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
_ _ _ _ _ _ ___ ____ ___ _ _ ____ ___ ____ ____ ___ | ||
| | |\ | |_/ | | | | |__| |___ |__] |__| [__ | | ||
|___ | | \| | \_ | |__| | | | |___ | | | ___] | | ||
|
||
# Building "past" versions of the conf.techmids.io.website | ||
|
||
|
||
The conf.techmids.io website ought to have all the previous versions of the website available for browsing, so people can see what went on and who spoke at each previous event. | ||
|
||
That's what this is for. | ||
|
||
Every time there's a new TechMids conference, the website changes to be about that particular conference. This means that the previous conference website disappears. That's a shame, because it's useful to have that previous website around somewhere, so people can still reference it: to see who spoke and what they spoke about and to see details of the previous conference. It's also a small bit of extra advertising: TechMids looks better if the previous events are accessible because it shows that the conference has happened multiple times, which demonstrates consistency and staying power. | ||
|
||
So, that's what this extra script does. | ||
|
||
The idea here is that, when a TechMids event has happened, this script is run to "archive" the current state of the website; it will then be available at conf.techmids.io/past/2023-06/ or similar. The script is run once to archive the current version of the website; after this, the site can then safely be changed to reference and describe the _next_ upcoming event. The script doesn't need to be run every time or on every build; it's a specific action, taken on the day that the website starts being updated for a new event. | ||
|
||
To run the script, do: | ||
|
||
`npm run link-to-the-past 2023-06` | ||
|
||
The date specified there is in `YYYY-MM` format, and is the date that the event on the website actually happened. (In particular, it is not the date that you're running it now.) | ||
|
||
An example may make things clearer. Let's say there was a TechMids conf in June 2023. The website is all about this event, showing the speakers, sponsors, and details. The event has happened, and it's now July 2023, and you're in charge of updating the website to start talking about the _next_ TechMids conf in October 2023. So, before you do that updating, you run `npm run link-to-the-past 2023-06`. This will archive a static copy of the website as it currently looks in `/past/2023-06`, and that static copy will remain untouched forever. You can now update the website to describe the October event, and the July 2023 event's site will remain forever, frozen in carbonite, for people to reference. | ||
|
||
## Technical details | ||
|
||
Here we describe what the script actually _does_. You don't need this information to run the script, although you will do if you want to fiddle with it. | ||
|
||
Essentially, the script's goal is to create a completely static version of the website as it currently exists, and put it in the `public/past` folder. It does this by: | ||
|
||
1. moving `public/past` out of the way, so that the static version of this website does not itself include all the other past versions | ||
2. editing `next.config.js` to describe how static versions of the site should be made | ||
3. running `next build` to create a static version of the site according to the `next.config.js` changes, in a temporary directory | ||
4. putting `public/past` back where it came from | ||
5. undoing its changes to `next.config.js` | ||
6. moving the newly-created static dump into `public/past` under the specified name, which should look like a date | ||
|
||
Most of the script is concerned with reporting on what it's doing, and coping with errors by undoing its invasive changes. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
function complain() { | ||
console.log(`Syntax: npm run link-to-the-past 2023-10 | ||
That is: you run this with a date, in YYYY-MM format. | ||
That will take the current version of the website, and | ||
create a /past/2023-10/ folder which is a static version | ||
of the website, for later viewing. | ||
The date should be the date of the conference, not the date today!`); | ||
process.exit(1); | ||
} | ||
|
||
export function get_valid_output_name() { | ||
// read the command line to get the output folder name | ||
// and complain if it's not right or not present | ||
if (process.argv.length < 3) { | ||
complain(); | ||
} | ||
const dt = process.argv[2]; | ||
if (!/20[0-9][0-9]-[01][0-9]/.test(dt)) { | ||
console.log(`Problem: "${dt}" does not look like a proper YYYY-MM date.\n`); | ||
complain(); | ||
} | ||
return dt; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
const link = ['CCCCCCCCCCCCCCCC', 'CCCCCCJJJJCCCCCC', 'CCCCCJAAFAJJCCCC', | ||
'CCCCJAAFFFFAJCCC', 'CJCJJGAAFAGJAJJC', 'JLJEJJGGGGJJAJLJ', | ||
'JLJEEEJJJJEEJJLJ', 'JDLJEEEEEEEEJLDJ', 'JDJEJJJJJJJJEJDJ', | ||
'CJDJDNNDDNNDJDJC', 'CCJDDNJLLJNDDJCC', 'CCJJDLJLLJLDJJCC', | ||
'CJIBJDLLLLDJBIJC', 'JOJBBJJDDJJBBJOJ', 'JOOJBIBJJBIBJOOJ', | ||
'JHJJBBIIIIIBJJHJ', 'JHHJBBBIIBBBJHHJ', 'JHJBMMJMMJMMBJHJ', | ||
'CJJJBBMMMMBBJJJC', 'CCJKJJBBBBJJKJCC', 'CCCJGKJJJJKGJCCC', | ||
'CCCCJJJCCJJJCCCC', 'CCCCCCCCCCCCCCCC', 'CCCCCCCCCCCCCCCC']; | ||
const cols = {'A': 64, 'B': 66, 'C': 231, 'D': 136, 'E': 169, | ||
'F': 106, 'G': 172, 'H': 173, 'I': 78, 'J': 16, 'K': 124, | ||
'L': 180, 'M': 185, 'N': 188, 'O': 94}; | ||
|
||
const lines = [ | ||
"_ _ _ _ _ _ ___ ____ ___ _ _ ____ ___ ____ ____ ___ ", | ||
"| | |\\ | |_/ | | | | |__| |___ |__] |__| [__ | ", | ||
"|___ | | \\| | \\_ | |__| | | | |___ | | | ___] | ", | ||
"", | ||
"The conf.techmids.io website ought to have all the previous", | ||
"versions of the website available for browsing, so people", | ||
"can see what went on and who spoke at each previous event.", | ||
"", | ||
"That's what this is for.", | ||
"We shall now dump the current website into a folder, ready to", | ||
"move it into the /past/ folder on the website!", | ||
" ...please hold on while we do the necessary..." | ||
] | ||
|
||
export function header() { | ||
const output = []; | ||
for (let i=0; i<link.length; i+=2) { | ||
const outline = []; | ||
for (let x=0; x<link[i].length; x++) { | ||
const top = cols[link[i][x]]; | ||
const bottom = cols[link[i+1][x]]; | ||
outline.push(`\x1b[38;5;${top};48;5;${bottom}m▀\x1b[0m`); | ||
} | ||
output.push(outline.join("") + " " + (lines[i/2] || "")); | ||
} | ||
console.log(output.join("\n")); | ||
console.log(""); | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import path from 'path'; | ||
|
||
import { header } from "./header.mjs"; | ||
import { get_valid_output_name } from './command-line.mjs'; | ||
import { restore_their_config, rollback, copy_config } from './tidyup.mjs'; | ||
import { get_paths, move_past_dir_aside, | ||
move_past_dir_back, move_export_into_past } from './paths.mjs'; | ||
import { export_site, assure_output_dir, write_our_config } from './make-changes.mjs'; | ||
|
||
async function remove_temporary_export(paths) { | ||
console.log(`Removing temporary export directory ${paths.temp_export_dir}`); | ||
await fs.rm(paths.temp_export_dir, {recursive: true}); | ||
} | ||
|
||
async function main() { | ||
const paths = await get_paths(); | ||
try { | ||
header(); | ||
const output_name = get_valid_output_name(); | ||
await copy_config(paths); | ||
await write_our_config(paths, output_name); | ||
await move_past_dir_aside(paths); | ||
await assure_output_dir(paths); | ||
await export_site(paths); | ||
await move_past_dir_back(paths); | ||
await move_export_into_past(paths, output_name); | ||
await restore_their_config(paths); | ||
} catch(e) { | ||
console.error("There was an error, sorry."); | ||
await rollback(e, paths); | ||
console.error("I shall now abort. The error in the script was this:"); | ||
console.log(e); | ||
} | ||
} | ||
|
||
main(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import * as fs from 'node:fs/promises'; | ||
import { R_OK, W_OK } from 'node:fs'; | ||
import { spawn } from 'child_process'; | ||
|
||
export async function write_our_config(paths, output_name) { | ||
/* A custom next.config.js file | ||
There's no provision for passing a separate file, so | ||
we overwrite the main one (and put it back later). | ||
Image optimisation requires a server, so it won't work | ||
in a pure static HTML export, and thus we disable it. | ||
*/ | ||
const ourConfig = ` | ||
/** @type {import('next').NextConfig} */ | ||
const nextConfig = { | ||
// reactStrictMode: true, | ||
output: 'export', | ||
distDir: '${paths.temp_export_dir_short}', | ||
basePath: '/past/${output_name}', | ||
images: { | ||
unoptimized: true, | ||
} | ||
} | ||
module.exports = nextConfig | ||
`; | ||
await fs.writeFile(paths.next_config_js, ourConfig); | ||
console.log("Written our custom link-to-the-past config"); | ||
} | ||
|
||
export async function assure_output_dir(paths) { | ||
console.log(`Confirming that we can write to the output directory ${paths.temp_export_dir}`); | ||
let output_exists; | ||
try { | ||
output_exists = await fs.access(paths.temp_export_dir, R_OK | W_OK); | ||
} catch(e) { | ||
if (e.code == "ENOENT") { | ||
// the output directory doesn't exist; this is fine | ||
} else { | ||
throw new Error( | ||
`We cannot write to ${paths.temp_export_dir}. ` + | ||
"This is not supposed to happen, and is a bug in this script."); | ||
} | ||
} | ||
if (output_exists) { | ||
console.log("Removing output directory"); | ||
await fs.rm(paths.temp_export_dir, {recursive: true}); | ||
} | ||
} | ||
|
||
export function export_site(paths) { | ||
return new Promise((resolve, reject) => { | ||
console.log(`Exporting the website as static to ${paths.temp_export_dir}`); | ||
const proc = spawn("next", ["build"]); | ||
proc.stdout.on("data", data => { console.log(data.toString().trimEnd()); }) | ||
proc.stderr.on("data", data => { console.error(data.toString().trimEnd()); }) | ||
proc.on("close", code => { | ||
if (code === 0) { resolve(); } | ||
reject(); | ||
}) | ||
proc.on("error", err => { reject(err); }) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
/** @type {import('next').NextConfig} */ | ||
const nextConfig = { | ||
// reactStrictMode: true, | ||
} | ||
|
||
module.exports = nextConfig |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { fileURLToPath } from 'url'; | ||
import * as fs from 'node:fs/promises'; | ||
import { R_OK, W_OK } from 'node:fs'; | ||
import path from 'path'; | ||
|
||
export async function get_paths() { | ||
const __filename = fileURLToPath(import.meta.url); | ||
const script_folder = path.dirname(__filename); | ||
const root_folder = path.dirname(script_folder); | ||
const next_config_js = path.resolve(path.join(script_folder, "..", "next.config.js")); | ||
try { | ||
const ncj_exists = await fs.access(next_config_js, R_OK | W_OK); | ||
} catch(e) { | ||
throw new Error( | ||
`Expected to find the next config in ${next_config_js}, but we didn't.\n` + | ||
"This isn't supposed to happen, and is a bug in this script.\n" + | ||
`(The actual error we got was this: ${e})`); | ||
} | ||
const public_dir = path.resolve(path.join(script_folder, "..", "public")); | ||
try { | ||
const public_dir_exists = await fs.access(public_dir, R_OK | W_OK); | ||
} catch(e) { | ||
throw new Error( | ||
`Expected to find the public resources dir in ${public_dir}, but we didn't.\n` + | ||
"This isn't supposed to happen, and is a bug in this script."); | ||
} | ||
const public_past_dir = path.join(public_dir, "past"); | ||
await fs.mkdir(public_past_dir, {recursive: true}); | ||
|
||
const temp_export_dir = path.join(script_folder, "export"); | ||
// the short version of the temp export dir is used in the next.config.js file | ||
// because you can't provide a full path; nextjs assumes the folder supplied is | ||
// inside the project root, so it ends up creating a home/you/blah/whatever/link-to-the-past/export | ||
// folder, irritatingly. So we make the short version here. | ||
const temp_export_dir_short = path.relative(root_folder, temp_export_dir); | ||
const temp_past_location = path.join(script_folder, "temp_past"); | ||
|
||
return { | ||
next_config_js, | ||
next_config_js_backup: path.join(script_folder, "next.config.js.bak"), | ||
script_folder, | ||
public_past_dir, | ||
temp_export_dir, | ||
temp_export_dir_short, | ||
temp_past_location | ||
} | ||
} | ||
|
||
export async function move_past_dir_aside(paths) { | ||
// put the real past dir from public temporarily out of the way | ||
// this ensures that when we generate the static version of | ||
// the website as it looks today, it doesn't have all the other | ||
// past versions in it! | ||
// this also avoids recursive issues where we're generating a static | ||
// version of the website while also writing into it, which causes | ||
// infinite nested /public/past/date/past/date/past/date/... problems | ||
console.log(`Moving the 'past' folder out of the way, from ${paths.public_past_dir} to ${paths.temp_past_location}`); | ||
await fs.rename(paths.public_past_dir, paths.temp_past_location); | ||
} | ||
export async function move_past_dir_back(paths) { | ||
console.log(`Moving the 'past' folder back, from ${paths.temp_past_location} back to ${paths.public_past_dir}`); | ||
await fs.rename(paths.temp_past_location, paths.public_past_dir); | ||
} | ||
export async function move_export_into_past(paths, output_name) { | ||
const output_dir = path.join(paths.public_past_dir, output_name); | ||
console.log(`Moving the newly exported static website to ${output_dir}`); | ||
await fs.rename(paths.temp_export_dir, output_dir); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import * as fs from 'node:fs/promises'; | ||
import { move_past_dir_back } from './paths.mjs'; | ||
|
||
export async function restore_their_config(paths, only_if_older=false) { | ||
const ncj_stat = await fs.stat(paths.next_config_js); | ||
let ncj_bak_stat; | ||
try { | ||
ncj_bak_stat = await fs.stat(paths.next_config_js_backup); | ||
} catch(e) { | ||
ncj_bak_stat = {ctimeMs: 0} | ||
} | ||
if ((only_if_older && ncj_stat.mtimeMs < ncj_bak_stat.mtimeMs) || !only_if_older) { | ||
await fs.copyFile(paths.next_config_js_backup, paths.next_config_js); | ||
console.log("Restored the original next.config.js successfully"); | ||
} | ||
} | ||
|
||
export async function rollback(script_err, paths) { | ||
console.log("I am attempting to restore things after the error."); | ||
try { | ||
await restore_their_config(paths, true); | ||
await move_past_dir_back(paths); | ||
} catch(e) { | ||
console.error("There was an error in the script:"); | ||
console.error(script_err); | ||
console.error("In trying to recover from that error, there was ANOTHER error:"); | ||
console.error(e); | ||
console.error("This is not great, and things may have been left in an inconsistent state."); | ||
console.error("All I can do is abort."); | ||
process.exit(2); | ||
} | ||
} | ||
|
||
export async function copy_config(paths) { | ||
console.log("Backing up the next.config.js before we fiddle with it..."); | ||
await fs.copyFile(paths.next_config_js, paths.next_config_js_backup); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
5017f07
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
conf-techmids-io – ./
conf.techmids.io
conf-techmids-io-git-main-tech-mids.vercel.app
conf-techmids-io-tech-mids.vercel.app
conf-techmids-io.vercel.app