summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmacsConf <emacsconf-org@gnu.org>2023-12-03 15:10:20 -0500
committerEmacsConf <emacsconf-org@gnu.org>2023-12-03 15:10:20 -0500
commit3de085ca5bcda4562941e4c83c3e2cee8cb0f065 (patch)
tree0e0a0ea65ba0a44e8a8a7bb319e89a693ca0bb5f
parent3fed62923c09a06b4f676adaa42877c33008911a (diff)
downloademacsconf-wiki-3de085ca5bcda4562941e4c83c3e2cee8cb0f065.tar.xz
emacsconf-wiki-3de085ca5bcda4562941e4c83c3e2cee8cb0f065.zip
Automated commit
-rw-r--r--2023/captions/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei--main--chapters.vtt38
-rw-r--r--2023/captions/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei--main.vtt1629
-rw-r--r--2023/info/web-after.md544
-rw-r--r--2023/info/web-before.md16
4 files changed, 2226 insertions, 1 deletions
diff --git a/2023/captions/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei--main--chapters.vtt b/2023/captions/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei--main--chapters.vtt
new file mode 100644
index 00000000..f94dbab5
--- /dev/null
+++ b/2023/captions/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei--main--chapters.vtt
@@ -0,0 +1,38 @@
+WEBVTT
+
+
+00:00:00.000 --> 00:00:35.679
+Overview
+
+00:00:35.680 --> 00:05:31.939
+Background problems
+
+00:05:31.940 --> 00:09:46.380
+Solutions outside of Emacs
+
+00:09:46.480 --> 00:09:54.599
+Emacs solutions
+
+00:09:54.600 --> 00:12:43.020
+Free clients in Emacs
+
+00:12:43.021 --> 00:16:52.379
+Web browsers in Emacs
+
+00:16:52.380 --> 00:17:30.379
+emacs-web-server - overview
+
+00:17:30.380 --> 00:18:17.579
+emacs-web-server - hello emacs!
+
+00:18:17.580 --> 00:23:06.439
+emacs-web-server - yolo
+
+00:23:07.940 --> 00:29:40.419
+emacs-web-server - emacs web framework
+
+00:29:40.420 --> 00:31:25.359
+Firefox with emacs for extensions
+
+00:31:25.360 --> 00:31:31.440
+Thank you
diff --git a/2023/captions/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei--main.vtt b/2023/captions/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei--main.vtt
new file mode 100644
index 00000000..60bafffd
--- /dev/null
+++ b/2023/captions/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei--main.vtt
@@ -0,0 +1,1629 @@
+WEBVTT captioned by ken, checked by sachac
+
+NOTE Overview
+
+00:00:00.000 --> 00:00:03.199
+Hello, I am Yuchen, and I will be talking about
+
+00:00:03.200 --> 00:00:06.839
+how Emacs may be used to save user freedom on the web.
+
+00:00:06.840 --> 00:00:09.679
+I will begin by describing the background issues,
+
+00:00:09.680 --> 00:00:12.359
+followed by solutions outside of Emacs.
+
+00:00:12.360 --> 00:00:14.879
+Then I will move into the main business of describing
+
+00:00:14.880 --> 00:00:17.799
+several ways to address the issues using Emacs,
+
+00:00:17.800 --> 00:00:20.599
+including free clients in Emacs, web browsers,
+
+00:00:20.600 --> 00:00:23.399
+also known as universal clients in Emacs,
+
+00:00:23.400 --> 00:00:27.119
+approaches using Emacs web server and Emacs web framework,
+
+00:00:27.120 --> 00:00:29.319
+which allows one to write an Emacs package
+
+00:00:29.320 --> 00:00:30.759
+and get a web app for free,
+
+00:00:30.760 --> 00:00:35.679
+as well as using Emacs as a Firefox extension.
+
+NOTE Background problems
+
+00:00:35.680 --> 00:00:37.159
+OK, let's now move on to
+
+00:00:37.160 --> 00:00:39.559
+the background issues for this topic.
+
+00:00:39.560 --> 00:00:42.639
+Many of you probably already know what is free software.
+
+00:00:42.640 --> 00:00:45.480
+It is software that respects four user freedoms,
+
+00:00:45.481 --> 00:00:48.999
+including freedom 0, which is the freedom to use,
+
+00:00:49.000 --> 00:00:52.179
+freedom 1 is the freedom to study and modify a program,
+
+00:00:52.279 --> 00:00:53.988
+freedom 2 is the freedom to
+
+00:00:54.488 --> 00:00:57.239
+distribute exact copies of a program,
+
+00:00:57.240 --> 00:01:01.679
+and freedom 3 is the freedom to distribute modified copies.
+
+00:01:01.680 --> 00:01:04.039
+Different environments have different norms
+
+00:01:04.040 --> 00:01:06.819
+with regards to user freedom.
+
+00:01:06.820 --> 00:01:11.239
+For example, GNU/Linux distributions
+
+00:01:11.240 --> 00:01:13.439
+default to free software,
+
+00:01:13.440 --> 00:01:15.519
+even though the official kernel Linux
+
+00:01:15.520 --> 00:01:18.419
+contains non-free code, like non-free firmware.
+
+00:01:18.420 --> 00:01:23.059
+What I mean is, people generally expect free software
+
+00:01:23.060 --> 00:01:25.759
+in these environments.
+
+00:01:25.760 --> 00:01:27.359
+There's plenty of free software
+
+00:01:27.360 --> 00:01:29.039
+built on other free software,
+
+00:01:29.040 --> 00:01:31.219
+so generally people can accomplish tasks
+
+00:01:31.220 --> 00:01:33.599
+using free software only.
+
+00:01:33.600 --> 00:01:37.279
+Emacs, by comparison, is even better.
+
+00:01:37.280 --> 00:01:41.219
+It has freedom built-in, as it is highly customizable
+
+00:01:41.220 --> 00:01:44.679
+with self-documenting configurations.
+
+00:01:44.680 --> 00:01:49.599
+When a Lisp form is evaluated by the user in Emacs,
+
+00:01:49.600 --> 00:01:53.159
+the change is instantly reflected in the environment.
+
+00:01:53.160 --> 00:01:56.719
+Thus, it converts users to hackers effortlessly.
+
+00:01:56.720 --> 00:01:58.439
+From writing setq statements,
+
+00:01:58.440 --> 00:02:00.639
+which is similar to configurations
+
+00:02:00.640 --> 00:02:01.959
+in the majority of other programs,
+
+00:02:01.960 --> 00:02:03.399
+to writing functions,
+
+00:02:03.400 --> 00:02:05.439
+which are building blocks of Elisp features,
+
+00:02:05.440 --> 00:02:08.139
+to writing features and publishing packages,
+
+00:02:08.140 --> 00:02:09.799
+it is a natural progression.
+
+00:02:10.099 --> 00:02:15.039
+In this sense, Emacs perhaps has
+
+00:02:15.040 --> 00:02:18.839
+the most gentle learning curve for hackers.
+
+00:02:18.840 --> 00:02:21.099
+On the other hand, the default license
+
+00:02:21.100 --> 00:02:22.599
+in the Emacs community
+
+00:02:22.600 --> 00:02:26.100
+is GNU General Public License version 3 or later,
+
+00:02:26.200 --> 00:02:29.039
+which is the best free software license
+
+00:02:29.040 --> 00:02:32.299
+apart from the Affero license.
+
+00:02:32.300 --> 00:02:35.019
+Now let's move on to web browsers,
+
+00:02:35.020 --> 00:02:39.239
+which by contrast does not default to freedom.
+
+00:02:39.240 --> 00:02:42.199
+For one thing, free software JavaScript projects
+
+00:02:42.200 --> 00:02:45.779
+default to Expat license,
+
+00:02:45.780 --> 00:02:49.399
+which is also commonly known as the MIT license,
+
+00:02:49.400 --> 00:02:53.279
+which is a lax permissive license that could be exploited
+
+00:02:53.280 --> 00:02:55.919
+as developers could write non-free derivatives
+
+00:02:55.920 --> 00:02:59.679
+and subjugate user freedom.
+
+00:02:59.680 --> 00:03:03.159
+This also contributes to the JavaScript trap.
+
+00:03:03.160 --> 00:03:06.719
+Most popular web browsers nowadays simply download and run
+
+00:03:06.720 --> 00:03:10.819
+any JavaScript code requested by the web page.
+
+00:03:10.820 --> 00:03:15.319
+Generally speaking, there are two camps on this issue.
+
+00:03:15.320 --> 00:03:19.039
+One side would say JavaScript is simply part of life,
+
+00:03:19.040 --> 00:03:22.039
+and an integral part of the so-called modern web.
+
+00:03:22.040 --> 00:03:25.299
+Just accept it, and there is no point in fighting it.
+
+00:03:25.300 --> 00:03:28.288
+Indeed, it can be frustrating when greeted by
+
+00:03:28.388 --> 00:03:31.799
+"This page requires JavaScript and cookies to continue,"
+
+00:03:31.800 --> 00:03:34.719
+or even a blank page when opening a web page
+
+00:03:34.720 --> 00:03:38.439
+while disabling JavaScript.
+
+00:03:38.440 --> 00:03:42.159
+The other camp takes a more principled position
+
+00:03:42.160 --> 00:03:44.839
+and says JavaScript is unnecessary.
+
+00:03:44.840 --> 00:03:47.279
+I mean, people use the web mainly for
+
+00:03:47.280 --> 00:03:48.519
+database-like operations
+
+00:03:48.520 --> 00:03:51.679
+to interact with data stored on other people's computers,
+
+00:03:51.680 --> 00:03:55.359
+like querying, creating, updating, deleting.
+
+00:03:55.360 --> 00:03:58.959
+I mean, 99% of the things happen in getting data,
+
+00:03:58.960 --> 00:04:01.239
+including reading news, watching videos,
+
+00:04:01.240 --> 00:04:03.339
+downloading images, etc.,
+
+00:04:03.340 --> 00:04:06.079
+and posting data, including publishing
+
+00:04:06.080 --> 00:04:10.479
+this sort of materials, publishing news comments, videos.
+
+00:04:10.480 --> 00:04:12.399
+Why does this need any programs
+
+00:04:12.400 --> 00:04:16.199
+to do funny computations, right?
+
+00:04:16.200 --> 00:04:18.980
+Modern web browsers are also a pain to use.
+
+00:04:19.080 --> 00:04:20.980
+They are the opposite to Emacs
+
+00:04:21.080 --> 00:04:26.759
+in terms of customization capabilities.
+
+00:04:26.760 --> 00:04:29.359
+Such problems on the client side
+
+00:04:29.360 --> 00:04:31.919
+is the main focus of this talk.
+
+00:04:31.920 --> 00:04:34.319
+On the server side, the issue is known as SaaSS,
+
+00:04:34.320 --> 00:04:38.460
+service as a software substitute.
+
+00:04:38.760 --> 00:04:42.420
+It is about doing computing for users
+
+00:04:42.421 --> 00:04:44.540
+on other people's computers,
+
+00:04:44.541 --> 00:04:48.439
+which the user has no visibility, let alone control.
+
+00:04:48.440 --> 00:04:51.940
+Examples include translation or photo editing
+
+00:04:51.941 --> 00:04:55.359
+in so-called web applications.
+
+00:04:55.360 --> 00:04:59.919
+Another example would be web applications
+
+00:04:59.920 --> 00:05:02.159
+make recommendations based on user data
+
+00:05:02.160 --> 00:05:05.959
+and suggest what the users read or watch next.
+
+00:05:05.960 --> 00:05:09.959
+On the one hand, SaaSS is an intractable problem
+
+00:05:09.960 --> 00:05:11.799
+because free software is all about user freedom
+
+00:05:11.800 --> 00:05:13.759
+on one's own computer,
+
+00:05:13.760 --> 00:05:16.079
+not someone else's computer.
+
+00:05:16.080 --> 00:05:18.780
+On the other hand, this is also a lesser problem
+
+00:05:18.880 --> 00:05:21.599
+because it has trivial solutions,
+
+00:05:21.600 --> 00:05:25.839
+which is self-hosting and keeping computations local.
+
+00:05:25.840 --> 00:05:28.679
+Wouldn't it be nice to use a photo editing web application,
+
+00:05:28.680 --> 00:05:31.939
+but without the web?
+
+NOTE Solutions outside of Emacs
+
+00:05:31.940 --> 00:05:36.400
+Right, now let's move on to solutions outside of Emacs
+
+00:05:36.401 --> 00:05:39.039
+that tackle these problems.
+
+00:05:39.040 --> 00:05:42.959
+There are generally two ways to fix this issue.
+
+00:05:42.960 --> 00:05:45.399
+One is blocking non-free JavaScript,
+
+00:05:45.400 --> 00:05:48.979
+and the other is substituting with free programs.
+
+00:05:48.980 --> 00:05:50.439
+Let's start with blocking.
+
+00:05:50.440 --> 00:05:54.859
+LibreJS, for example, is a Firefox extension
+
+00:05:54.860 --> 00:05:56.919
+blocking non-free, non-trivial JavaScript.
+
+00:05:56.920 --> 00:05:59.820
+It works by intercepting, filtering
+
+00:05:59.821 --> 00:06:01.759
+all requests for JavaScript,
+
+00:06:01.760 --> 00:06:05.599
+recognizing the ones that are trivial or free,
+
+00:06:05.600 --> 00:06:10.999
+and blocking the execution of the others.
+
+00:06:11.000 --> 00:06:13.879
+As an experiment, I logged the LibreJS output
+
+00:06:13.880 --> 00:06:15.559
+for about two weeks,
+
+00:06:15.560 --> 00:06:19.739
+and during which, of all the web pages I loaded,
+
+00:06:19.740 --> 00:06:25.000
+23 domains have at least some LibreJS-compliant scripts.
+
+00:06:25.001 --> 00:06:28.679
+That is not much, though I did use other means
+
+00:06:28.680 --> 00:06:30.819
+to reduce the scenarios
+
+00:06:30.920 --> 00:06:35.399
+where I need to load web pages with JavaScript in Firefox,
+
+00:06:35.400 --> 00:06:40.719
+like using a text browser like Lynx.
+
+00:06:40.720 --> 00:06:44.239
+Then there's also NoScript, which is like LibreJS,
+
+00:06:44.240 --> 00:06:49.499
+but it blocks all scripts, whether free or non-free,
+trivial or non-trivial.
+
+00:06:49.500 --> 00:06:54.359
+So the problem with blocking is that
+
+00:06:54.360 --> 00:06:57.559
+blocking with certain scripts and accepting others,
+
+00:06:57.560 --> 00:07:00.579
+there are like... I can think of two problems.
+
+00:07:00.679 --> 00:07:02.779
+One is that it does not help with Freedom 1,
+
+00:07:02.879 --> 00:07:07.959
+which is the freedom to allow users to modify a program
+
+00:07:07.960 --> 00:07:13.079
+and use it in place of the original program.
+
+00:07:13.080 --> 00:07:15.839
+And also it does not help
+
+00:07:15.840 --> 00:07:18.859
+when the non-free JavaScript is mandatory
+
+00:07:18.860 --> 00:07:20.719
+for the functioning of the web page.
+
+00:07:20.720 --> 00:07:22.839
+For example, some pages are blank
+
+00:07:22.840 --> 00:07:27.079
+when non-free JavaScript is not executed.
+
+00:07:27.080 --> 00:07:35.180
+So now let's move on to the substitution, the other method.
+
+00:07:36.280 --> 00:07:38.919
+Let's start with userscript.
+
+00:07:38.920 --> 00:07:41.760
+It is a script, it is a user-specified JavaScript
+
+00:07:41.761 --> 00:07:43.039
+injected to a web page.
+
+00:07:43.040 --> 00:07:48.480
+A typical example of userscript tool is GreaseMonkey.
+
+00:07:48.481 --> 00:07:53.159
+Another idea is a proxy that replaces scripts in place,
+
+00:07:53.160 --> 00:07:55.819
+that is, sending user-specified scripts
+
+00:07:55.919 --> 00:08:00.899
+as a response to requests for such scripts.
+
+00:08:00.900 --> 00:08:04.759
+So one example would be Haketilo, however you pronounce it.
+
+00:08:04.760 --> 00:08:09.619
+It's a tool that's built on top of mitmproxy.
+
+00:08:09.620 --> 00:08:11.719
+It is supposed to do this.
+
+00:08:11.720 --> 00:08:14.599
+I haven't used GreaseMonkey nor Haketilo
+
+00:08:14.600 --> 00:08:16.599
+for these purposes yet,
+
+00:08:16.600 --> 00:08:20.779
+so I can't say much about these options.
+
+00:08:20.780 --> 00:08:24.359
+So then there are also free clients
+
+00:08:24.360 --> 00:08:26.479
+which replace the whole frontend,
+
+00:08:26.480 --> 00:08:30.660
+instead of a script requested by web pages
+
+00:08:30.661 --> 00:08:32.499
+from the official web clients.
+
+00:08:32.500 --> 00:08:37.359
+People often refer to them as alternative frontend.
+
+00:08:37.360 --> 00:08:39.359
+YouTube is perhaps the best example
+
+00:08:39.360 --> 00:08:41.279
+as there are so many free clients,
+
+00:08:41.280 --> 00:08:43.621
+including Invidious for the web,
+
+00:08:43.622 --> 00:08:46.239
+youtube-dl and yt-dlp on the command line,
+
+00:08:46.240 --> 00:08:50.279
+MPV and VLC as GUI desktop, LibreTube
+
+00:08:50.280 --> 00:08:53.259
+and NewPipe for Android and so on.
+
+00:08:53.260 --> 00:08:56.759
+Youtube-dl and yt-dlp are especially versatile
+
+00:08:56.760 --> 00:08:59.459
+as they work with many video and audio sites
+
+00:08:59.460 --> 00:09:02.520
+with extractors written in Python,
+
+00:09:02.620 --> 00:09:06.299
+so people can add extractors like extensions.
+
+00:09:06.300 --> 00:09:09.421
+A similar tool would be woob,
+
+00:09:09.422 --> 00:09:12.739
+short for web outside of the browsers.
+
+00:09:12.740 --> 00:09:16.820
+It is a command-line and GUI program
+
+00:09:16.920 --> 00:09:23.199
+that interacts with many web services, even banks.
+
+00:09:23.200 --> 00:09:25.839
+And there are browser extensions
+
+00:09:25.840 --> 00:09:28.859
+that automatically redirect to these clients.
+
+00:09:28.860 --> 00:09:31.639
+For example, Redirector and Libredirect
+
+00:09:31.640 --> 00:09:35.199
+redirect to the free web clients.
+
+00:09:35.200 --> 00:09:39.699
+One could use OpenWith, another extension,
+
+00:09:39.700 --> 00:09:42.159
+to redirect to free non-web clients,
+
+00:09:42.160 --> 00:09:46.380
+for example by opening YouTube links with MPV.
+
+NOTE Emacs solutions
+
+00:09:46.480 --> 00:09:50.999
+Now let us move to Emacs-based solutions.
+
+00:09:51.000 --> 00:09:54.599
+They are based on the same ideas but using Emacs.
+
+NOTE Free clients in Emacs
+
+00:09:54.600 --> 00:09:57.479
+First, free clients in Emacs.
+
+00:09:57.480 --> 00:10:00.639
+Basically alternative frontends written in Elisp.
+
+00:10:00.640 --> 00:10:03.359
+There are several advantages.
+
+00:10:03.360 --> 00:10:06.199
+For example, integration with other Emacs tools,
+
+00:10:06.200 --> 00:10:09.559
+good for archiving, making use of Emacs libraries,
+
+00:10:09.560 --> 00:10:12.488
+extensibility, thanks to Emacs' own
+
+00:10:12.489 --> 00:10:14.900
+extensibility and customizability.
+
+00:10:15.000 --> 00:10:18.619
+Examples include mastodon.el for mastodon,
+
+00:10:18.620 --> 00:10:22.679
+or mastorg for viewing and archiving toots with org,
+
+00:10:22.680 --> 00:10:28.899
+sx for Stack Exchange, buildbot.el for buildbot, etc.
+
+00:10:28.900 --> 00:10:31.900
+Here's an example of mastorg displaying
+
+00:10:31.901 --> 00:10:34.420
+the hierarchy of a toot in org.
+
+00:10:34.520 --> 00:10:39.820
+Just wait. Right.
+
+00:10:39.920 --> 00:10:43.900
+So this is the toot itself, this is a first reply,
+
+00:10:44.000 --> 00:10:48.479
+this is a reply to the reply, and so on.
+
+00:10:48.480 --> 00:10:53.079
+And here is an example of
+
+00:10:53.080 --> 00:11:05.719
+opening a Stack Exchange link using sx.
+
+00:11:05.720 --> 00:11:07.020
+Let's check out the tag.
+
+00:11:11.120 --> 00:11:28.399
+So we can browse the Stack Exchange Emacs site
+with ease.
+
+00:11:28.400 --> 00:11:31.079
+The idea is quite simple.
+
+00:11:31.080 --> 00:11:35.620
+Just use APIs to get data and display it in Emacs,
+
+00:11:35.720 --> 00:11:40.819
+or just to scrape, like requesting HTML and processing it.
+
+00:11:40.820 --> 00:11:42.079
+An example of scraping is hnreader,
+
+00:11:44.180 --> 00:11:47.199
+which scrapes Hacker News web pages
+
+00:11:47.299 --> 00:11:49.779
+and renders them in Org buffers.
+
+00:11:49.780 --> 00:11:52.379
+Here's how hnreader fetches
+
+00:11:52.380 --> 00:11:56.319
+and displays the Hacker News front page.
+
+00:11:58.520 --> 00:12:03.999
+And one could go into the comments,
+
+00:12:04.000 --> 00:12:09.159
+which shows a similar hierarchy to mastorg's output.
+
+00:12:14.360 --> 00:12:19.000
+And of course, there are limitations for this method,
+
+00:12:19.001 --> 00:12:22.539
+which is not limited to Emacs.
+
+00:12:22.540 --> 00:12:24.521
+There are basically limitations
+
+00:12:24.522 --> 00:12:28.419
+to any ad hoc bespoke clients,
+
+00:12:28.420 --> 00:12:31.519
+which is catch-up games with remote server,
+
+00:12:31.520 --> 00:12:34.559
+which may change the API interface endpoints
+
+00:12:34.560 --> 00:12:37.539
+or even structure of the responses.
+
+00:12:37.540 --> 00:12:43.020
+This brings us to web browsers in Emacs.
+
+NOTE Web browsers in Emacs
+
+00:12:43.021 --> 00:12:45.159
+Web browsers are universal clients
+
+00:12:45.160 --> 00:12:47.199
+because all sites support browsers.
+
+00:12:47.200 --> 00:12:48.919
+So in a world of no JavaScript,
+
+00:12:48.920 --> 00:12:52.739
+there will be no need to write bespoke clients.
+
+00:12:52.740 --> 00:12:53.479
+In such a world,
+
+00:12:53.480 --> 00:12:56.739
+instead of using JavaScript code to fetch JSON,
+
+00:12:56.740 --> 00:13:00.119
+web developers make server do the heavy lifting
+
+00:13:00.120 --> 00:13:02.859
+and just send the complete HTML over.
+
+00:13:02.860 --> 00:13:05.479
+Okay, back to reality.
+
+00:13:05.480 --> 00:13:07.659
+EWW, the default Emacs browser,
+
+00:13:07.660 --> 00:13:11.379
+is what people refer to as a text browser,
+
+00:13:11.380 --> 00:13:16.899
+even though it is not text only and it supports images too.
+
+00:13:16.900 --> 00:13:20.679
+It is a good solid browser that supports forms, etc.
+
+00:13:20.680 --> 00:13:24.079
+The downside is that it does not support CSS,
+
+00:13:24.080 --> 00:13:28.159
+so the formatting could be a bit ugly sometimes.
+
+00:13:28.160 --> 00:13:30.119
+There are some other browsers in Emacs too,
+
+00:13:30.120 --> 00:13:34.279
+like emacs-w3m, which is backed by w3m,
+
+00:13:34.280 --> 00:13:36.439
+and Luwak, which is backed by Lynx.
+
+00:13:36.440 --> 00:13:39.099
+Sorry for the naming, by the way.
+
+00:13:39.100 --> 00:13:41.519
+They often consist of a backend
+
+00:13:41.520 --> 00:13:44.879
+that fetches URL and parses HTML.
+
+00:13:44.880 --> 00:13:47.199
+For example, the built-in URL package
+
+00:13:47.200 --> 00:13:50.599
+and the libxml2 binding in Emacs are decent enough.
+
+00:13:50.600 --> 00:13:53.188
+And the frontend that renders the HTML,
+
+00:13:53.189 --> 00:13:56.599
+like shr or lynx, etc.
+
+00:13:56.699 --> 00:14:04.739
+There is also an xwidget-webkit,
+
+00:14:04.740 --> 00:14:07.759
+but this browser executes JavaScript,
+
+00:14:07.760 --> 00:14:10.539
+so it does not really help in this case.
+
+00:14:10.540 --> 00:14:14.239
+Browser extensions on Emacs are effortless,
+
+00:14:14.240 --> 00:14:17.459
+as they can be written as Emacs packages.
+
+00:14:17.460 --> 00:14:19.279
+For example, one could easily write
+
+00:14:19.280 --> 00:14:21.959
+Elisp scripts with similar functionalities
+
+00:14:21.960 --> 00:14:24.921
+to libredirect and openwith
+
+00:14:24.922 --> 00:14:29.881
+to redirect links, to rewrite URLs,
+
+00:14:30.181 --> 00:14:36.860
+or to open, say, a YouTube URL with MPV,
+
+00:14:37.061 --> 00:14:39.700
+but with even more flexibility.
+
+00:14:39.800 --> 00:14:41.779
+For example, here's how one could
+
+00:14:41.780 --> 00:14:44.839
+transform a Zoom link to a dial-in number
+
+00:14:44.840 --> 00:14:47.479
+so that it is easier to join a Zoom meeting
+
+00:14:47.480 --> 00:14:50.359
+without running non-free JavaScript.
+
+00:14:50.360 --> 00:14:53.039
+This might still be bad for privacy,
+
+00:14:53.040 --> 00:14:55.999
+but at least it's good for freedom.
+
+00:14:58.699 --> 00:15:00.279
+As mentioned before,
+
+00:15:00.379 --> 00:15:03.919
+one shortcoming of these Emacs-based browsers,
+
+00:15:03.920 --> 00:15:08.079
+Emacs web browsers, is no support for CSS,
+
+00:15:08.080 --> 00:15:11.319
+so the formatting could leave a lot to be desired.
+
+00:15:11.320 --> 00:15:12.959
+Maybe someone would write
+
+00:15:12.960 --> 00:15:17.159
+an Emacs browser package backed by wkhtmltopdf,
+
+00:15:17.160 --> 00:15:20.639
+which, when opening a URL,
+
+00:15:20.640 --> 00:15:26.380
+it calls wkhtmltopdf to convert the web page to PDF
+
+00:15:26.480 --> 00:15:29.540
+and opens in, say, pdf-view-mode of the pdf-tools,
+
+00:15:29.640 --> 00:15:31.039
+thus containing formatting,
+
+00:15:31.040 --> 00:15:33.999
+and all the URL clicks resolve to the same actions.
+
+00:15:34.000 --> 00:15:42.399
+Also, wkhtmltopdf contains a flag that disables JavaScript.
+
+00:15:43.300 --> 00:15:45.239
+Another idea would be to use Firefox
+
+00:15:45.240 --> 00:15:49.679
+as a processor to fetch URLs.
+
+00:15:50.280 --> 00:15:54.559
+Maybe it can be used to pass back the HTML
+
+00:15:54.560 --> 00:15:56.519
+after executing free JavaScript,
+
+00:15:56.520 --> 00:16:01.439
+say, if Firefox has LibreJS installed.
+
+00:16:01.440 --> 00:16:04.940
+This requires Firefox to send back the DOM,
+
+00:16:05.040 --> 00:16:08.039
+which could be achieved using native messaging.
+
+00:16:08.040 --> 00:16:09.719
+More on that later.
+
+00:16:09.720 --> 00:16:14.239
+Alternatively, one could also write a Firefox extension
+
+00:16:14.240 --> 00:16:17.639
+that sends the DOM in an existing tab back to Emacs.
+
+00:16:17.640 --> 00:16:20.079
+But thinking more about it,
+
+00:16:20.080 --> 00:16:22.959
+I don't think this is actually a useful idea,
+
+00:16:23.059 --> 00:16:27.039
+because most of the sites that work under LibreJS
+
+00:16:27.139 --> 00:16:34.419
+also are useful when all JavaScript is blocked.
+
+00:16:34.420 --> 00:16:37.039
+So, this means these sites are viewable
+
+00:16:37.040 --> 00:16:42.159
+under EWW, Luwak, etc.
+
+00:16:42.160 --> 00:16:43.639
+And another issue is that
+
+00:16:43.640 --> 00:16:46.559
+this could also make running non-free JavaScript easier,
+
+00:16:46.560 --> 00:16:52.379
+which is harmful to user freedom.
+
+NOTE emacs-web-server - overview
+
+00:16:52.380 --> 00:16:54.239
+OK, let's move on to the idea
+
+00:16:54.240 --> 00:16:55.679
+of running Emacs as a web server,
+
+00:16:55.680 --> 00:16:58.559
+so that Emacs client packages are web apps
+
+00:16:58.560 --> 00:17:00.319
+serving as alternative frontends.
+
+00:17:00.320 --> 00:17:02.239
+Why would we want to do this?
+
+00:17:02.240 --> 00:17:06.079
+Well, as much as one wants to be always in Emacs,
+
+00:17:06.080 --> 00:17:08.339
+it is not always feasible.
+
+00:17:08.340 --> 00:17:10.719
+For example, one may be on the go
+
+00:17:10.720 --> 00:17:12.519
+and needs to look up something on the phone.
+
+00:17:12.520 --> 00:17:14.879
+On the other hand, Emacs client packages
+
+00:17:14.880 --> 00:17:16.159
+are just alternative frontends
+
+00:17:16.160 --> 00:17:18.119
+but written in Elisp and run in Emacs.
+
+00:17:18.120 --> 00:17:20.759
+With the help of emacs-web-server package,
+
+00:17:20.760 --> 00:17:23.579
+we can access Emacs packages on the web.
+
+00:17:23.580 --> 00:17:26.439
+emacs-web-server package is not something new,
+
+00:17:26.440 --> 00:17:30.379
+but seems to be underused in the community somehow.
+
+NOTE emacs-web-server - hello emacs!
+
+00:17:30.380 --> 00:17:33.359
+OK, let's start with a simple example called hello-emacs.
+
+00:17:33.360 --> 00:17:35.239
+It is pretty straightforward.
+
+00:17:35.240 --> 00:17:38.639
+Just require the web server feature
+
+00:17:38.640 --> 00:17:40.999
+and run ws-start to start a server process
+
+00:17:41.000 --> 00:17:43.359
+and send the string "hello emacs"
+
+00:17:43.360 --> 00:17:45.539
+to the process regardless of the request.
+
+00:17:45.540 --> 00:17:48.479
+As you can see, it is going to be available
+
+00:17:48.480 --> 00:17:51.219
+at port 9000 of localhost.
+
+00:17:51.319 --> 00:17:52.999
+Let's try it out.
+
+00:17:53.000 --> 00:18:01.839
+We need to first evaluate this code block.
+
+00:18:01.840 --> 00:18:03.939
+And it works.
+
+00:18:03.940 --> 00:18:10.839
+To stop a server, just run ws-stop on the web server object.
+
+00:18:10.840 --> 00:18:14.959
+Let's evaluate.
+
+00:18:14.960 --> 00:18:17.579
+Yep, it stopped.
+
+NOTE emacs-web-server - yolo
+
+00:18:17.580 --> 00:18:19.999
+OK, now let's move on to something funny
+
+00:18:20.000 --> 00:18:22.219
+that you should never run on the public web.
+
+00:18:22.220 --> 00:18:23.919
+I call it yolo.el.
+
+00:18:23.920 --> 00:18:25.359
+It uses htmlize
+
+00:18:25.360 --> 00:18:28.159
+to make any Emacs buffer available on the web.
+
+00:18:28.160 --> 00:18:28.999
+Let's try it out.
+
+00:18:29.000 --> 00:18:32.999
+Just require the thing and start the server by yolo-start.
+
+00:18:33.000 --> 00:18:38.119
+And it's available at port 9999.
+
+00:18:38.120 --> 00:18:41.599
+By default, the root domain shows the splash screen
+
+00:18:41.600 --> 00:18:42.919
+which needs to be available.
+
+00:18:42.920 --> 00:18:46.719
+Running display-splash-screen ensures that,
+
+00:18:47.219 --> 00:18:48.839
+but here I've already run it.
+
+00:18:48.939 --> 00:18:54.359
+So let's have a look.
+
+00:18:54.560 --> 00:18:56.639
+And here we have the splash screen.
+
+00:18:56.640 --> 00:19:00.239
+Emacs tutorial and such.
+
+00:19:00.240 --> 00:19:03.279
+Unfortunately, none of these links work,
+
+00:19:05.480 --> 00:19:08.000
+which is something we will revisit later.
+
+00:19:10.000 --> 00:19:15.381
+So, to show an arbitrary buffer,
+
+00:19:15.481 --> 00:19:19.981
+just use the buffer name as a path.
+
+00:19:20.081 --> 00:19:24.761
+For example, the slide has the buffer named web.org,
+
+00:19:24.861 --> 00:19:28.080
+so we can display it.
+
+00:19:34.581 --> 00:19:36.540
+Let's try something fancier,
+
+00:19:36.941 --> 00:19:40.000
+like the man page of ffmpeg.
+
+00:19:40.880 --> 00:19:44.719
+So this is the man page of ffmpeg.
+
+00:19:45.120 --> 00:19:48.420
+And the buffer name is a bit more complicated.
+
+00:19:48.520 --> 00:19:51.639
+I have the URL available here.
+
+00:19:59.140 --> 00:20:05.979
+It's missing a star.
+
+00:20:05.980 --> 00:20:10.659
+It's pretty neat if you ask me.
+
+00:20:12.560 --> 00:20:14.879
+And, yeah, what else?
+
+00:20:14.880 --> 00:20:22.699
+Well, we can also browse EWW in Firefox.
+
+00:20:22.700 --> 00:20:30.599
+For example, let's check out gnu.org,
+
+00:20:30.600 --> 00:20:33.679
+and note that the buffer name is EWW with stars.
+
+00:20:39.080 --> 00:20:41.879
+So, ah, it works.
+
+00:20:41.979 --> 00:20:50.899
+And it has all the graphics even.
+
+00:20:50.900 --> 00:20:55.639
+Now, how about we do it the other way around?
+
+00:20:55.640 --> 00:21:10.779
+So we load the current slide web.org using this funny thing.
+
+00:21:10.780 --> 00:21:12.239
+And it works.
+
+00:21:14.040 --> 00:21:19.939
+Not as nice as the Org buffer, though.
+
+00:21:19.940 --> 00:21:27.439
+Right, and now that gives me some funny idea.
+
+00:21:27.440 --> 00:21:31.359
+So I'm a firm believer that memes are meant to be enjoyed
+
+00:21:31.360 --> 00:21:33.199
+in silence rather than read out loud.
+
+00:21:33.200 --> 00:21:38.759
+So I will jump straight to trying this idea,
+
+00:21:38.760 --> 00:21:48.959
+which is loading the EWW buffer URL with EWW itself.
+
+00:21:49.860 --> 00:21:53.839
+Loading, loading, loading.
+
+00:21:53.840 --> 00:21:56.199
+Spoiler alert, it never loads.
+
+00:21:59.100 --> 00:22:03.120
+So that concludes the demo.
+
+00:22:03.220 --> 00:22:06.439
+And so we can stop the server, web server, with `yolo-stop`.
+
+00:22:06.440 --> 00:22:13.399
+So one could extend yolo to serve arbitrary Emacs commands,
+
+00:22:13.400 --> 00:22:15.439
+making it even more dangerous.
+
+00:22:15.440 --> 00:22:26.019
+That is, for example, `localhost:9000/m-x/magit-status`
+
+00:22:26.119 --> 00:22:27.720
+would run `magit-status`
+
+00:22:27.820 --> 00:22:33.499
+and show the magit-status buffer in the web browser.
+
+00:22:34.500 --> 00:22:43.119
+Or localhost:9000/m-x/eww/
+
+00:22:43.120 --> 00:22:46.759
+any arbitrary URL to browse arbitrary URL
+
+00:22:46.760 --> 00:22:50.819
+with EWW inside of Firefox.
+
+00:22:50.820 --> 00:22:53.879
+It can serve as a way to block all JavaScript,
+
+00:22:53.880 --> 00:22:56.799
+because EWW does not support JavaScript.
+
+00:22:56.800 --> 00:23:00.079
+And enforce preferred colorscheme in Firefox,
+
+00:23:00.080 --> 00:23:02.839
+since htmlize, as you have noticed,
+
+00:23:02.840 --> 00:23:06.439
+faithfully reflects the theme used in Emacs.
+
+NOTE emacs-web-server - emacs web framework
+
+00:23:07.940 --> 00:23:10.239
+Okay, so we know that yolo is unsafe
+
+00:23:10.339 --> 00:23:11.440
+and needs to be refined.
+
+00:23:11.540 --> 00:23:13.439
+In fact, we don't necessarily want
+
+00:23:13.440 --> 00:23:15.599
+to run Emacs on a web browser.
+
+00:23:15.600 --> 00:23:17.279
+After all, a modern web browser is
+
+00:23:17.280 --> 00:23:19.079
+something one has to fight all the time
+
+00:23:19.080 --> 00:23:21.600
+and should be avoided whenever possible.
+
+00:23:21.601 --> 00:23:24.479
+We want to instead be able to access things
+
+00:23:24.480 --> 00:23:26.459
+when forced to be in a web browser,
+
+00:23:26.460 --> 00:23:28.359
+in which case only the motivations
+
+00:23:28.360 --> 00:23:31.299
+of an alternative frontend apply.
+
+00:23:31.300 --> 00:23:35.360
+Moreover, the ideal situation is an Emacs web framework,
+
+00:23:35.460 --> 00:23:36.799
+a tool that automatically
+
+00:23:36.800 --> 00:23:39.199
+transforms Emacs packages to web apps,
+
+00:23:39.200 --> 00:23:41.799
+so that one does not need to write extra code
+
+00:23:41.800 --> 00:23:45.559
+to get a web app that does the same thing as the package.
+
+00:23:45.560 --> 00:23:49.099
+We also need all links in the web pages to work.
+
+00:23:49.100 --> 00:23:52.399
+As noted before, the links on the yolo Emacs splash screen
+
+00:23:52.400 --> 00:23:53.839
+do not work.
+
+00:23:53.840 --> 00:23:58.199
+So here's a proof-of-concept example. It's called bom.el.
+
+00:23:58.200 --> 00:24:00.119
+It gets some weather forecast data
+
+00:24:00.120 --> 00:24:03.079
+from the Australian Bureau of Meteorology
+
+00:24:03.080 --> 00:24:05.559
+and displays it in an org buffer.
+
+00:24:05.560 --> 00:24:09.279
+So let's try it out. One could do `M-x bom`,
+
+00:24:09.280 --> 00:24:15.219
+which shows an org buffer with links to each state.
+
+00:24:15.220 --> 00:24:17.199
+So based in Melbourne, naturally,
+
+00:24:17.200 --> 00:24:21.839
+I would like to find out the weather of Victoria.
+
+00:24:21.840 --> 00:24:27.839
+And yes, to execute this command. Wait, wait, wait. Right.
+
+00:24:27.840 --> 00:24:33.459
+And we are at a buffer that shows
+
+00:24:33.460 --> 00:24:36.119
+the weather forecast of the whole of Victoria
+
+00:24:36.120 --> 00:24:39.379
+in the hierarchy. Note that this back button
+
+00:24:39.479 --> 00:24:46.639
+takes you to the previous page.
+
+00:24:46.640 --> 00:24:47.919
+So here are the regions of Victoria.
+
+00:24:47.920 --> 00:24:53.799
+I think Melbourne is in Central.
+
+00:24:53.800 --> 00:24:54.719
+And yeah, it shows
+
+00:24:54.720 --> 00:24:57.259
+the seven-day weather forecast of Melbourne.
+
+00:24:57.260 --> 00:25:00.359
+You can also reach this page by running,
+
+00:25:00.360 --> 00:25:08.199
+let's see, directly `M-x bom-state`.
+
+00:25:08.600 --> 00:25:09.759
+Vic.
+
+00:25:13.960 --> 00:25:18.399
+OK. So this works.
+
+00:25:18.400 --> 00:25:21.280
+And this is bom as an Emacs package.
+
+00:25:21.380 --> 00:25:23.980
+Now let's check out bom as a web app
+
+00:25:23.981 --> 00:25:28.039
+transformed by Emacs web framework.
+
+00:25:28.040 --> 00:25:30.319
+So start the web server with bom-start.
+
+00:25:33.020 --> 00:25:39.559
+And let's try it out. It's at 9000 again.
+
+00:25:39.560 --> 00:25:42.359
+Oops. Invalid path. Oh, that's because
+
+00:25:42.360 --> 00:25:46.119
+it makes exactly one command to one path.
+
+00:25:46.120 --> 00:25:49.300
+So remember that we used the bom command
+
+00:25:49.301 --> 00:25:50.719
+to show the landing page.
+
+00:25:50.720 --> 00:25:54.340
+So here we need the bom in the path as well.
+
+00:25:54.440 --> 00:26:00.679
+And it shows the same landing page, except in HTML.
+
+00:26:00.680 --> 00:26:07.259
+Let's check out Victoria weather forecast as before.
+
+00:26:07.260 --> 00:26:12.279
+And it shows an HTML converted from the org buffer
+
+00:26:12.280 --> 00:26:17.559
+using ox export HTML, whatever.
+
+00:26:17.560 --> 00:26:20.259
+And you can see even the back button is here.
+
+00:26:20.359 --> 00:26:26.219
+That takes you to /bom.
+
+00:26:26.220 --> 00:26:29.139
+So let's have a look at Melbourne. Here it is.
+
+00:26:29.140 --> 00:26:31.379
+Hooray, it works.
+
+00:26:31.380 --> 00:26:33.860
+So, yeah, as usual,
+
+00:26:33.960 --> 00:26:40.559
+you can stop the web server with `M-x bom-stop`.
+
+00:26:40.560 --> 00:26:43.660
+Right. And alternatively,
+
+00:26:43.760 --> 00:26:48.499
+it can also be deployed directly in terminal
+
+00:26:48.500 --> 00:26:56.099
+in a dedicated Emacs daemon.
+
+00:26:56.100 --> 00:26:58.279
+So you can see that there's a one-one correspondence
+
+00:26:58.280 --> 00:27:03.099
+between the Emacs package interface and the web interface.
+
+00:27:03.100 --> 00:27:06.039
+And that implies some restrictions to the Emacs package
+
+00:27:06.040 --> 00:27:09.159
+for the Emacs web framework to be able to do its job. Right.
+
+00:27:09.160 --> 00:27:13.439
+For example, the package needs to have an Org interface
+
+00:27:13.440 --> 00:27:15.519
+and the links that trigger other commands
+
+00:27:15.520 --> 00:27:17.799
+need to be in Elisp links
+
+00:27:17.800 --> 00:27:20.759
+so that the Emacs web framework
+
+00:27:20.760 --> 00:27:24.799
+can translate it to web server URL path.
+
+00:27:24.800 --> 00:27:28.919
+Note that Emacs web server framework is not a real package.
+
+00:27:28.920 --> 00:27:33.339
+I wrote some functions in bom.el serving the purpose,
+
+00:27:33.340 --> 00:27:35.719
+and they should be separated out eventually
+
+00:27:35.720 --> 00:27:37.759
+without much trouble.
+
+00:27:37.760 --> 00:27:39.999
+One could get weather forecast
+
+00:27:40.000 --> 00:27:42.219
+without running JavaScript anyway,
+
+00:27:42.220 --> 00:27:45.199
+which makes bom.el less important
+
+00:27:45.200 --> 00:27:48.319
+as an alternative web client.
+
+00:27:48.320 --> 00:27:50.519
+Though it does provide, dare I say,
+
+00:27:50.520 --> 00:27:52.380
+a clean and minimal interface
+
+00:27:52.480 --> 00:27:55.719
+compared to common weather forecast web pages.
+
+00:27:55.720 --> 00:27:58.639
+Other more relevant use cases could be Mastodon,
+
+00:27:58.640 --> 00:28:01.319
+whose official web client requires JavaScript
+
+00:28:01.320 --> 00:28:03.479
+to display a post.
+
+00:28:03.480 --> 00:28:08.559
+The mastorg package that shows an Org hierarchy of toots
+
+00:28:08.560 --> 00:28:12.079
+rooted as a given toot could be a low-hanging fruit.
+
+00:28:12.179 --> 00:28:15.199
+The limitation of Org interface requirements
+
+00:28:15.200 --> 00:28:17.879
+can also be relaxed in further work,
+
+00:28:17.880 --> 00:28:21.639
+if one could extend Emacs web framework
+
+00:28:21.640 --> 00:28:24.199
+to translate back and forth between Emacs widgets,
+
+00:28:24.200 --> 00:28:28.639
+say, including buttons and web page widgets,
+
+00:28:28.640 --> 00:28:30.599
+including links.
+
+00:28:30.600 --> 00:28:32.599
+Another more far-fetched idea would be
+
+00:28:32.600 --> 00:28:35.799
+to translate to other types of interfaces,
+
+00:28:35.800 --> 00:28:42.120
+like GNU/Linux or Android GUI.
+
+00:28:44.020 --> 00:28:47.479
+How about animations? Say, M-x butterfly,
+
+00:28:47.480 --> 00:28:53.999
+or even web games from Emacs games?
+
+00:28:54.000 --> 00:29:00.099
+Possibilities are unlimited in this, as always, in Emacs.
+
+00:29:00.100 --> 00:29:03.159
+I also noticed some limitations
+
+00:29:03.160 --> 00:29:07.439
+when trying to actually host bom.el on the public web.
+
+00:29:07.440 --> 00:29:12.939
+Given the limited access to the Emacs server,
+
+00:29:13.540 --> 00:29:16.719
+I was comfortable enough to give bom.el a go
+
+00:29:16.720 --> 00:29:18.799
+to serve it on the public web.
+
+00:29:18.800 --> 00:29:20.559
+However, I immediately stopped
+
+00:29:20.560 --> 00:29:22.879
+after noticing how slow it is.
+
+00:29:22.880 --> 00:29:24.719
+It can take more than 30 seconds
+
+00:29:24.720 --> 00:29:27.839
+to load a page of weather forecast for a state.
+
+00:29:27.840 --> 00:29:30.999
+I am also not sure how many simultaneous connections
+
+00:29:31.000 --> 00:29:32.379
+it can handle.
+
+00:29:32.380 --> 00:29:36.439
+In any case, I think the package emacs-web-server
+
+00:29:36.440 --> 00:29:40.419
+could do with some performance enhancement.
+
+NOTE Firefox with emacs for extensions
+
+00:29:40.420 --> 00:29:43.999
+Right. Because of the time constraints,
+
+00:29:44.000 --> 00:29:45.759
+I will briefly touch one final idea,
+
+00:29:45.760 --> 00:29:50.320
+which is to use Emacs as a Firefox browser extension.
+
+00:29:50.420 --> 00:29:52.800
+We already have org-protocol,
+
+00:29:52.900 --> 00:29:54.439
+which allows Firefox to communicate
+
+00:29:54.440 --> 00:29:55.919
+with a running Emacs server
+
+00:29:55.920 --> 00:29:59.779
+by sending an org-protocol URL to the latter.
+
+00:29:59.780 --> 00:30:03.159
+It can be used not just for capturing or storing links,
+
+00:30:03.160 --> 00:30:10.119
+but to execute arbitrary code on any component of the URL.
+
+00:30:10.120 --> 00:30:11.679
+However, it is fire and forget,
+
+00:30:11.680 --> 00:30:16.479
+and Emacs cannot tell Firefox what to do.
+
+00:30:16.480 --> 00:30:17.919
+There may be a length restriction, too.
+
+00:30:17.920 --> 00:30:20.399
+For example, Firefox may not be able to send back
+
+00:30:20.400 --> 00:30:22.419
+the whole DOM.
+
+00:30:22.420 --> 00:30:26.219
+This claim needs to be verified, though.
+
+00:30:26.220 --> 00:30:30.019
+Native messaging is one solution to this problem.
+
+00:30:30.020 --> 00:30:31.639
+It is a two-way communication channel
+
+00:30:31.640 --> 00:30:35.319
+between a Firefox web extension and a local system process
+
+00:30:35.320 --> 00:30:37.839
+started by the web extension.
+
+00:30:37.840 --> 00:30:40.399
+The process could be an Emacs server,
+
+00:30:40.400 --> 00:30:42.399
+which would make Emacs effectively
+
+00:30:42.400 --> 00:30:48.679
+a Firefox web browser extension.
+
+00:30:48.680 --> 00:30:51.999
+In this case, Elisp would be the main extension language,
+
+00:30:52.000 --> 00:30:53.619
+rather than JavaScript.
+
+00:30:53.620 --> 00:30:56.159
+However, JavaScript is still needed at the Firefox end
+
+00:30:56.160 --> 00:30:59.220
+of the communication channel.
+
+00:30:59.320 --> 00:31:01.159
+As a simple example of this idea,
+
+00:31:01.160 --> 00:31:04.439
+Firefox could ask Emacs to redirect a URL
+
+00:31:04.440 --> 00:31:08.319
+by removing tracking and using alternative frontend, etc.
+
+00:31:08.320 --> 00:31:12.479
+However, I was not able to implement this
+
+00:31:12.480 --> 00:31:14.279
+due to some tricky business
+
+00:31:14.280 --> 00:31:15.639
+with enforcing synchronicity
+
+00:31:15.640 --> 00:31:17.119
+that allows the web extension
+
+00:31:17.120 --> 00:31:20.199
+to wait for responses from Emacs.
+
+00:31:20.200 --> 00:31:25.359
+Some further work, I suppose.
+
+NOTE Thank you
+
+00:31:25.360 --> 00:31:28.154
+That concludes my talk.
+
+00:31:28.254 --> 00:31:31.440
+Thank you for your attention.
diff --git a/2023/info/web-after.md b/2023/info/web-after.md
index 8bbf8942..fa6981a8 100644
--- a/2023/info/web-after.md
+++ b/2023/info/web-after.md
@@ -1,6 +1,550 @@
<!-- Automatically generated by emacsconf-publish-after-page -->
+<a name="web-mainVideo-transcript"></a>
+# Transcript
+
+[[!template new="1" text="""Hello, I am Yuchen, and I will be talking about""" start="00:00:00.000" video="mainVideo-web" id="subtitle"]]
+[[!template text="""how Emacs may be used to save user freedom on the web.""" start="00:00:03.200" video="mainVideo-web" id="subtitle"]]
+[[!template text="""I will begin by describing the background issues,""" start="00:00:06.840" video="mainVideo-web" id="subtitle"]]
+[[!template text="""followed by solutions outside of Emacs.""" start="00:00:09.680" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Then I will move into the main business of describing""" start="00:00:12.360" video="mainVideo-web" id="subtitle"]]
+[[!template text="""several ways to address the issues using Emacs,""" start="00:00:14.880" video="mainVideo-web" id="subtitle"]]
+[[!template text="""including free clients in Emacs, web browsers,""" start="00:00:17.800" video="mainVideo-web" id="subtitle"]]
+[[!template text="""also known as universal clients in Emacs,""" start="00:00:20.600" video="mainVideo-web" id="subtitle"]]
+[[!template text="""approaches using Emacs web server and Emacs web framework,""" start="00:00:23.400" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which allows one to write an Emacs package""" start="00:00:27.120" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and get a web app for free,""" start="00:00:29.320" video="mainVideo-web" id="subtitle"]]
+[[!template text="""as well as using Emacs as a Firefox extension.""" start="00:00:30.760" video="mainVideo-web" id="subtitle"]]
+[[!template new="1" text="""OK, let's now move on to""" start="00:00:35.680" video="mainVideo-web" id="subtitle"]]
+[[!template text="""the background issues for this topic.""" start="00:00:37.160" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Many of you probably already know what is free software.""" start="00:00:39.560" video="mainVideo-web" id="subtitle"]]
+[[!template text="""It is software that respects four user freedoms,""" start="00:00:42.640" video="mainVideo-web" id="subtitle"]]
+[[!template text="""including freedom 0, which is the freedom to use,""" start="00:00:45.481" video="mainVideo-web" id="subtitle"]]
+[[!template text="""freedom 1 is the freedom to study and modify a program,""" start="00:00:49.000" video="mainVideo-web" id="subtitle"]]
+[[!template text="""freedom 2 is the freedom to""" start="00:00:52.279" video="mainVideo-web" id="subtitle"]]
+[[!template text="""distribute exact copies of a program,""" start="00:00:54.488" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and freedom 3 is the freedom to distribute modified copies.""" start="00:00:57.240" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Different environments have different norms""" start="00:01:01.680" video="mainVideo-web" id="subtitle"]]
+[[!template text="""with regards to user freedom.""" start="00:01:04.040" video="mainVideo-web" id="subtitle"]]
+[[!template text="""For example, GNU/Linux distributions""" start="00:01:06.820" video="mainVideo-web" id="subtitle"]]
+[[!template text="""default to free software,""" start="00:01:11.240" video="mainVideo-web" id="subtitle"]]
+[[!template text="""even though the official kernel Linux""" start="00:01:13.440" video="mainVideo-web" id="subtitle"]]
+[[!template text="""contains non-free code, like non-free firmware.""" start="00:01:15.520" video="mainVideo-web" id="subtitle"]]
+[[!template text="""What I mean is, people generally expect free software""" start="00:01:18.420" video="mainVideo-web" id="subtitle"]]
+[[!template text="""in these environments.""" start="00:01:23.060" video="mainVideo-web" id="subtitle"]]
+[[!template text="""There's plenty of free software""" start="00:01:25.760" video="mainVideo-web" id="subtitle"]]
+[[!template text="""built on other free software,""" start="00:01:27.360" video="mainVideo-web" id="subtitle"]]
+[[!template text="""so generally people can accomplish tasks""" start="00:01:29.040" video="mainVideo-web" id="subtitle"]]
+[[!template text="""using free software only.""" start="00:01:31.220" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Emacs, by comparison, is even better.""" start="00:01:33.600" video="mainVideo-web" id="subtitle"]]
+[[!template text="""It has freedom built-in, as it is highly customizable""" start="00:01:37.280" video="mainVideo-web" id="subtitle"]]
+[[!template text="""with self-documenting configurations.""" start="00:01:41.220" video="mainVideo-web" id="subtitle"]]
+[[!template text="""When a Lisp form is evaluated by the user in Emacs,""" start="00:01:44.680" video="mainVideo-web" id="subtitle"]]
+[[!template text="""the change is instantly reflected in the environment.""" start="00:01:49.600" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Thus, it converts users to hackers effortlessly.""" start="00:01:53.160" video="mainVideo-web" id="subtitle"]]
+[[!template text="""From writing setq statements,""" start="00:01:56.720" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which is similar to configurations""" start="00:01:58.440" video="mainVideo-web" id="subtitle"]]
+[[!template text="""in the majority of other programs,""" start="00:02:00.640" video="mainVideo-web" id="subtitle"]]
+[[!template text="""to writing functions,""" start="00:02:01.960" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which are building blocks of Elisp features,""" start="00:02:03.400" video="mainVideo-web" id="subtitle"]]
+[[!template text="""to writing features and publishing packages,""" start="00:02:05.440" video="mainVideo-web" id="subtitle"]]
+[[!template text="""it is a natural progression.""" start="00:02:08.140" video="mainVideo-web" id="subtitle"]]
+[[!template text="""In this sense, Emacs perhaps has""" start="00:02:10.099" video="mainVideo-web" id="subtitle"]]
+[[!template text="""the most gentle learning curve for hackers.""" start="00:02:15.040" video="mainVideo-web" id="subtitle"]]
+[[!template text="""On the other hand, the default license""" start="00:02:18.840" video="mainVideo-web" id="subtitle"]]
+[[!template text="""in the Emacs community""" start="00:02:21.100" video="mainVideo-web" id="subtitle"]]
+[[!template text="""is GNU General Public License version 3 or later,""" start="00:02:22.600" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which is the best free software license""" start="00:02:26.200" video="mainVideo-web" id="subtitle"]]
+[[!template text="""apart from the Affero license.""" start="00:02:29.040" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Now let's move on to web browsers,""" start="00:02:32.300" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which by contrast does not default to freedom.""" start="00:02:35.020" video="mainVideo-web" id="subtitle"]]
+[[!template text="""For one thing, free software JavaScript projects""" start="00:02:39.240" video="mainVideo-web" id="subtitle"]]
+[[!template text="""default to Expat license,""" start="00:02:42.200" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which is also commonly known as the MIT license,""" start="00:02:45.780" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which is a lax permissive license that could be exploited""" start="00:02:49.400" video="mainVideo-web" id="subtitle"]]
+[[!template text="""as developers could write non-free derivatives""" start="00:02:53.280" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and subjugate user freedom.""" start="00:02:55.920" video="mainVideo-web" id="subtitle"]]
+[[!template text="""This also contributes to the JavaScript trap.""" start="00:02:59.680" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Most popular web browsers nowadays simply download and run""" start="00:03:03.160" video="mainVideo-web" id="subtitle"]]
+[[!template text="""any JavaScript code requested by the web page.""" start="00:03:06.720" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Generally speaking, there are two camps on this issue.""" start="00:03:10.820" video="mainVideo-web" id="subtitle"]]
+[[!template text="""One side would say JavaScript is simply part of life,""" start="00:03:15.320" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and an integral part of the so-called modern web.""" start="00:03:19.040" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Just accept it, and there is no point in fighting it.""" start="00:03:22.040" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Indeed, it can be frustrating when greeted by""" start="00:03:25.300" video="mainVideo-web" id="subtitle"]]
+[[!template text="""&quot;This page requires JavaScript and cookies to continue,&quot;""" start="00:03:28.388" video="mainVideo-web" id="subtitle"]]
+[[!template text="""or even a blank page when opening a web page""" start="00:03:31.800" video="mainVideo-web" id="subtitle"]]
+[[!template text="""while disabling JavaScript.""" start="00:03:34.720" video="mainVideo-web" id="subtitle"]]
+[[!template text="""The other camp takes a more principled position""" start="00:03:38.440" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and says JavaScript is unnecessary.""" start="00:03:42.160" video="mainVideo-web" id="subtitle"]]
+[[!template text="""I mean, people use the web mainly for""" start="00:03:44.840" video="mainVideo-web" id="subtitle"]]
+[[!template text="""database-like operations""" start="00:03:47.280" video="mainVideo-web" id="subtitle"]]
+[[!template text="""to interact with data stored on other people's computers,""" start="00:03:48.520" video="mainVideo-web" id="subtitle"]]
+[[!template text="""like querying, creating, updating, deleting.""" start="00:03:51.680" video="mainVideo-web" id="subtitle"]]
+[[!template text="""I mean, 99% of the things happen in getting data,""" start="00:03:55.360" video="mainVideo-web" id="subtitle"]]
+[[!template text="""including reading news, watching videos,""" start="00:03:58.960" video="mainVideo-web" id="subtitle"]]
+[[!template text="""downloading images, etc.,""" start="00:04:01.240" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and posting data, including publishing""" start="00:04:03.340" video="mainVideo-web" id="subtitle"]]
+[[!template text="""this sort of materials, publishing news comments, videos.""" start="00:04:06.080" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Why does this need any programs""" start="00:04:10.480" video="mainVideo-web" id="subtitle"]]
+[[!template text="""to do funny computations, right?""" start="00:04:12.400" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Modern web browsers are also a pain to use.""" start="00:04:16.200" video="mainVideo-web" id="subtitle"]]
+[[!template text="""They are the opposite to Emacs""" start="00:04:19.080" video="mainVideo-web" id="subtitle"]]
+[[!template text="""in terms of customization capabilities.""" start="00:04:21.080" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Such problems on the client side""" start="00:04:26.760" video="mainVideo-web" id="subtitle"]]
+[[!template text="""is the main focus of this talk.""" start="00:04:29.360" video="mainVideo-web" id="subtitle"]]
+[[!template text="""On the server side, the issue is known as SaaSS,""" start="00:04:31.920" video="mainVideo-web" id="subtitle"]]
+[[!template text="""service as a software substitute.""" start="00:04:34.320" video="mainVideo-web" id="subtitle"]]
+[[!template text="""It is about doing computing for users""" start="00:04:38.760" video="mainVideo-web" id="subtitle"]]
+[[!template text="""on other people's computers,""" start="00:04:42.421" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which the user has no visibility, let alone control.""" start="00:04:44.541" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Examples include translation or photo editing""" start="00:04:48.440" video="mainVideo-web" id="subtitle"]]
+[[!template text="""in so-called web applications.""" start="00:04:51.941" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Another example would be web applications""" start="00:04:55.360" video="mainVideo-web" id="subtitle"]]
+[[!template text="""make recommendations based on user data""" start="00:04:59.920" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and suggest what the users read or watch next.""" start="00:05:02.160" video="mainVideo-web" id="subtitle"]]
+[[!template text="""On the one hand, SaaSS is an intractable problem""" start="00:05:05.960" video="mainVideo-web" id="subtitle"]]
+[[!template text="""because free software is all about user freedom""" start="00:05:09.960" video="mainVideo-web" id="subtitle"]]
+[[!template text="""on one's own computer,""" start="00:05:11.800" video="mainVideo-web" id="subtitle"]]
+[[!template text="""not someone else's computer.""" start="00:05:13.760" video="mainVideo-web" id="subtitle"]]
+[[!template text="""On the other hand, this is also a lesser problem""" start="00:05:16.080" video="mainVideo-web" id="subtitle"]]
+[[!template text="""because it has trivial solutions,""" start="00:05:18.880" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which is self-hosting and keeping computations local.""" start="00:05:21.600" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Wouldn't it be nice to use a photo editing web application,""" start="00:05:25.840" video="mainVideo-web" id="subtitle"]]
+[[!template text="""but without the web?""" start="00:05:28.680" video="mainVideo-web" id="subtitle"]]
+[[!template new="1" text="""Right, now let's move on to solutions outside of Emacs""" start="00:05:31.940" video="mainVideo-web" id="subtitle"]]
+[[!template text="""that tackle these problems.""" start="00:05:36.401" video="mainVideo-web" id="subtitle"]]
+[[!template text="""There are generally two ways to fix this issue.""" start="00:05:39.040" video="mainVideo-web" id="subtitle"]]
+[[!template text="""One is blocking non-free JavaScript,""" start="00:05:42.960" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and the other is substituting with free programs.""" start="00:05:45.400" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Let's start with blocking.""" start="00:05:48.980" video="mainVideo-web" id="subtitle"]]
+[[!template text="""LibreJS, for example, is a Firefox extension""" start="00:05:50.440" video="mainVideo-web" id="subtitle"]]
+[[!template text="""blocking non-free, non-trivial JavaScript.""" start="00:05:54.860" video="mainVideo-web" id="subtitle"]]
+[[!template text="""It works by intercepting, filtering""" start="00:05:56.920" video="mainVideo-web" id="subtitle"]]
+[[!template text="""all requests for JavaScript,""" start="00:05:59.821" video="mainVideo-web" id="subtitle"]]
+[[!template text="""recognizing the ones that are trivial or free,""" start="00:06:01.760" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and blocking the execution of the others.""" start="00:06:05.600" video="mainVideo-web" id="subtitle"]]
+[[!template text="""As an experiment, I logged the LibreJS output""" start="00:06:11.000" video="mainVideo-web" id="subtitle"]]
+[[!template text="""for about two weeks,""" start="00:06:13.880" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and during which, of all the web pages I loaded,""" start="00:06:15.560" video="mainVideo-web" id="subtitle"]]
+[[!template text="""23 domains have at least some LibreJS-compliant scripts.""" start="00:06:19.740" video="mainVideo-web" id="subtitle"]]
+[[!template text="""That is not much, though I did use other means""" start="00:06:25.001" video="mainVideo-web" id="subtitle"]]
+[[!template text="""to reduce the scenarios""" start="00:06:28.680" video="mainVideo-web" id="subtitle"]]
+[[!template text="""where I need to load web pages with JavaScript in Firefox,""" start="00:06:30.920" video="mainVideo-web" id="subtitle"]]
+[[!template text="""like using a text browser like Lynx.""" start="00:06:35.400" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Then there's also NoScript, which is like LibreJS,""" start="00:06:40.720" video="mainVideo-web" id="subtitle"]]
+[[!template text="""but it blocks all scripts, whether free or non-free,
+trivial or non-trivial.""" start="00:06:44.240" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So the problem with blocking is that""" start="00:06:49.500" video="mainVideo-web" id="subtitle"]]
+[[!template text="""blocking with certain scripts and accepting others,""" start="00:06:54.360" video="mainVideo-web" id="subtitle"]]
+[[!template text="""there are like... I can think of two problems.""" start="00:06:57.560" video="mainVideo-web" id="subtitle"]]
+[[!template text="""One is that it does not help with Freedom 1,""" start="00:07:00.679" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which is the freedom to allow users to modify a program""" start="00:07:02.879" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and use it in place of the original program.""" start="00:07:07.960" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And also it does not help""" start="00:07:13.080" video="mainVideo-web" id="subtitle"]]
+[[!template text="""when the non-free JavaScript is mandatory""" start="00:07:15.840" video="mainVideo-web" id="subtitle"]]
+[[!template text="""for the functioning of the web page.""" start="00:07:18.860" video="mainVideo-web" id="subtitle"]]
+[[!template text="""For example, some pages are blank""" start="00:07:20.720" video="mainVideo-web" id="subtitle"]]
+[[!template text="""when non-free JavaScript is not executed.""" start="00:07:22.840" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So now let's move on to the substitution, the other method.""" start="00:07:27.080" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Let's start with userscript.""" start="00:07:36.280" video="mainVideo-web" id="subtitle"]]
+[[!template text="""It is a script, it is a user-specified JavaScript""" start="00:07:38.920" video="mainVideo-web" id="subtitle"]]
+[[!template text="""injected to a web page.""" start="00:07:41.761" video="mainVideo-web" id="subtitle"]]
+[[!template text="""A typical example of userscript tool is GreaseMonkey.""" start="00:07:43.040" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Another idea is a proxy that replaces scripts in place,""" start="00:07:48.481" video="mainVideo-web" id="subtitle"]]
+[[!template text="""that is, sending user-specified scripts""" start="00:07:53.160" video="mainVideo-web" id="subtitle"]]
+[[!template text="""as a response to requests for such scripts.""" start="00:07:55.919" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So one example would be Haketilo, however you pronounce it.""" start="00:08:00.900" video="mainVideo-web" id="subtitle"]]
+[[!template text="""It's a tool that's built on top of mitmproxy.""" start="00:08:04.760" video="mainVideo-web" id="subtitle"]]
+[[!template text="""It is supposed to do this.""" start="00:08:09.620" video="mainVideo-web" id="subtitle"]]
+[[!template text="""I haven't used GreaseMonkey nor Haketilo""" start="00:08:11.720" video="mainVideo-web" id="subtitle"]]
+[[!template text="""for these purposes yet,""" start="00:08:14.600" video="mainVideo-web" id="subtitle"]]
+[[!template text="""so I can't say much about these options.""" start="00:08:16.600" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So then there are also free clients""" start="00:08:20.780" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which replace the whole frontend,""" start="00:08:24.360" video="mainVideo-web" id="subtitle"]]
+[[!template text="""instead of a script requested by web pages""" start="00:08:26.480" video="mainVideo-web" id="subtitle"]]
+[[!template text="""from the official web clients.""" start="00:08:30.661" video="mainVideo-web" id="subtitle"]]
+[[!template text="""People often refer to them as alternative frontend.""" start="00:08:32.500" video="mainVideo-web" id="subtitle"]]
+[[!template text="""YouTube is perhaps the best example""" start="00:08:37.360" video="mainVideo-web" id="subtitle"]]
+[[!template text="""as there are so many free clients,""" start="00:08:39.360" video="mainVideo-web" id="subtitle"]]
+[[!template text="""including Invidious for the web,""" start="00:08:41.280" video="mainVideo-web" id="subtitle"]]
+[[!template text="""youtube-dl and yt-dlp on the command line,""" start="00:08:43.622" video="mainVideo-web" id="subtitle"]]
+[[!template text="""MPV and VLC as GUI desktop, LibreTube""" start="00:08:46.240" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and NewPipe for Android and so on.""" start="00:08:50.280" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Youtube-dl and yt-dlp are especially versatile""" start="00:08:53.260" video="mainVideo-web" id="subtitle"]]
+[[!template text="""as they work with many video and audio sites""" start="00:08:56.760" video="mainVideo-web" id="subtitle"]]
+[[!template text="""with extractors written in Python,""" start="00:08:59.460" video="mainVideo-web" id="subtitle"]]
+[[!template text="""so people can add extractors like extensions.""" start="00:09:02.620" video="mainVideo-web" id="subtitle"]]
+[[!template text="""A similar tool would be woob,""" start="00:09:06.300" video="mainVideo-web" id="subtitle"]]
+[[!template text="""short for web outside of the browsers.""" start="00:09:09.422" video="mainVideo-web" id="subtitle"]]
+[[!template text="""It is a command-line and GUI program""" start="00:09:12.740" video="mainVideo-web" id="subtitle"]]
+[[!template text="""that interacts with many web services, even banks.""" start="00:09:16.920" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And there are browser extensions""" start="00:09:23.200" video="mainVideo-web" id="subtitle"]]
+[[!template text="""that automatically redirect to these clients.""" start="00:09:25.840" video="mainVideo-web" id="subtitle"]]
+[[!template text="""For example, Redirector and Libredirect""" start="00:09:28.860" video="mainVideo-web" id="subtitle"]]
+[[!template text="""redirect to the free web clients.""" start="00:09:31.640" video="mainVideo-web" id="subtitle"]]
+[[!template text="""One could use OpenWith, another extension,""" start="00:09:35.200" video="mainVideo-web" id="subtitle"]]
+[[!template text="""to redirect to free non-web clients,""" start="00:09:39.700" video="mainVideo-web" id="subtitle"]]
+[[!template text="""for example by opening YouTube links with MPV.""" start="00:09:42.160" video="mainVideo-web" id="subtitle"]]
+[[!template new="1" text="""Now let us move to Emacs-based solutions.""" start="00:09:46.480" video="mainVideo-web" id="subtitle"]]
+[[!template text="""They are based on the same ideas but using Emacs.""" start="00:09:51.000" video="mainVideo-web" id="subtitle"]]
+[[!template new="1" text="""First, free clients in Emacs.""" start="00:09:54.600" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Basically alternative frontends written in Elisp.""" start="00:09:57.480" video="mainVideo-web" id="subtitle"]]
+[[!template text="""There are several advantages.""" start="00:10:00.640" video="mainVideo-web" id="subtitle"]]
+[[!template text="""For example, integration with other Emacs tools,""" start="00:10:03.360" video="mainVideo-web" id="subtitle"]]
+[[!template text="""good for archiving, making use of Emacs libraries,""" start="00:10:06.200" video="mainVideo-web" id="subtitle"]]
+[[!template text="""extensibility, thanks to Emacs' own""" start="00:10:09.560" video="mainVideo-web" id="subtitle"]]
+[[!template text="""extensibility and customizability.""" start="00:10:12.489" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Examples include mastodon.el for mastodon,""" start="00:10:15.000" video="mainVideo-web" id="subtitle"]]
+[[!template text="""or mastorg for viewing and archiving toots with org,""" start="00:10:18.620" video="mainVideo-web" id="subtitle"]]
+[[!template text="""sx for Stack Exchange, buildbot.el for buildbot, etc.""" start="00:10:22.680" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Here's an example of mastorg displaying""" start="00:10:28.900" video="mainVideo-web" id="subtitle"]]
+[[!template text="""the hierarchy of a toot in org.""" start="00:10:31.901" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Just wait. Right.""" start="00:10:34.520" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So this is the toot itself, this is a first reply,""" start="00:10:39.920" video="mainVideo-web" id="subtitle"]]
+[[!template text="""this is a reply to the reply, and so on.""" start="00:10:44.000" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And here is an example of""" start="00:10:48.480" video="mainVideo-web" id="subtitle"]]
+[[!template text="""opening a Stack Exchange link using sx.""" start="00:10:53.080" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Let's check out the tag.""" start="00:11:05.720" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So we can browse the Stack Exchange Emacs site
+with ease.""" start="00:11:11.120" video="mainVideo-web" id="subtitle"]]
+[[!template text="""The idea is quite simple.""" start="00:11:28.400" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Just use APIs to get data and display it in Emacs,""" start="00:11:31.080" video="mainVideo-web" id="subtitle"]]
+[[!template text="""or just to scrape, like requesting HTML and processing it.""" start="00:11:35.720" video="mainVideo-web" id="subtitle"]]
+[[!template text="""An example of scraping is hnreader,""" start="00:11:40.820" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which scrapes Hacker News web pages""" start="00:11:44.180" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and renders them in Org buffers.""" start="00:11:47.299" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Here's how hnreader fetches""" start="00:11:49.780" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and displays the Hacker News front page.""" start="00:11:52.380" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And one could go into the comments,""" start="00:11:58.520" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which shows a similar hierarchy to mastorg's output.""" start="00:12:04.000" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And of course, there are limitations for this method,""" start="00:12:14.360" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which is not limited to Emacs.""" start="00:12:19.001" video="mainVideo-web" id="subtitle"]]
+[[!template text="""There are basically limitations""" start="00:12:22.540" video="mainVideo-web" id="subtitle"]]
+[[!template text="""to any ad hoc bespoke clients,""" start="00:12:24.522" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which is catch-up games with remote server,""" start="00:12:28.420" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which may change the API interface endpoints""" start="00:12:31.520" video="mainVideo-web" id="subtitle"]]
+[[!template text="""or even structure of the responses.""" start="00:12:34.560" video="mainVideo-web" id="subtitle"]]
+[[!template text="""This brings us to web browsers in Emacs.""" start="00:12:37.540" video="mainVideo-web" id="subtitle"]]
+[[!template new="1" text="""Web browsers are universal clients""" start="00:12:43.021" video="mainVideo-web" id="subtitle"]]
+[[!template text="""because all sites support browsers.""" start="00:12:45.160" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So in a world of no JavaScript,""" start="00:12:47.200" video="mainVideo-web" id="subtitle"]]
+[[!template text="""there will be no need to write bespoke clients.""" start="00:12:48.920" video="mainVideo-web" id="subtitle"]]
+[[!template text="""In such a world,""" start="00:12:52.740" video="mainVideo-web" id="subtitle"]]
+[[!template text="""instead of using JavaScript code to fetch JSON,""" start="00:12:53.480" video="mainVideo-web" id="subtitle"]]
+[[!template text="""web developers make server do the heavy lifting""" start="00:12:56.740" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and just send the complete HTML over.""" start="00:13:00.120" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Okay, back to reality.""" start="00:13:02.860" video="mainVideo-web" id="subtitle"]]
+[[!template text="""EWW, the default Emacs browser,""" start="00:13:05.480" video="mainVideo-web" id="subtitle"]]
+[[!template text="""is what people refer to as a text browser,""" start="00:13:07.660" video="mainVideo-web" id="subtitle"]]
+[[!template text="""even though it is not text only and it supports images too.""" start="00:13:11.380" video="mainVideo-web" id="subtitle"]]
+[[!template text="""It is a good solid browser that supports forms, etc.""" start="00:13:16.900" video="mainVideo-web" id="subtitle"]]
+[[!template text="""The downside is that it does not support CSS,""" start="00:13:20.680" video="mainVideo-web" id="subtitle"]]
+[[!template text="""so the formatting could be a bit ugly sometimes.""" start="00:13:24.080" video="mainVideo-web" id="subtitle"]]
+[[!template text="""There are some other browsers in Emacs too,""" start="00:13:28.160" video="mainVideo-web" id="subtitle"]]
+[[!template text="""like emacs-w3m, which is backed by w3m,""" start="00:13:30.120" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and Luwak, which is backed by Lynx.""" start="00:13:34.280" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Sorry for the naming, by the way.""" start="00:13:36.440" video="mainVideo-web" id="subtitle"]]
+[[!template text="""They often consist of a backend""" start="00:13:39.100" video="mainVideo-web" id="subtitle"]]
+[[!template text="""that fetches URL and parses HTML.""" start="00:13:41.520" video="mainVideo-web" id="subtitle"]]
+[[!template text="""For example, the built-in URL package""" start="00:13:44.880" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and the libxml2 binding in Emacs are decent enough.""" start="00:13:47.200" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And the frontend that renders the HTML,""" start="00:13:50.600" video="mainVideo-web" id="subtitle"]]
+[[!template text="""like shr or lynx, etc.""" start="00:13:53.189" video="mainVideo-web" id="subtitle"]]
+[[!template text="""There is also an xwidget-webkit,""" start="00:13:56.699" video="mainVideo-web" id="subtitle"]]
+[[!template text="""but this browser executes JavaScript,""" start="00:14:04.740" video="mainVideo-web" id="subtitle"]]
+[[!template text="""so it does not really help in this case.""" start="00:14:07.760" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Browser extensions on Emacs are effortless,""" start="00:14:10.540" video="mainVideo-web" id="subtitle"]]
+[[!template text="""as they can be written as Emacs packages.""" start="00:14:14.240" video="mainVideo-web" id="subtitle"]]
+[[!template text="""For example, one could easily write""" start="00:14:17.460" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Elisp scripts with similar functionalities""" start="00:14:19.280" video="mainVideo-web" id="subtitle"]]
+[[!template text="""to libredirect and openwith""" start="00:14:21.960" video="mainVideo-web" id="subtitle"]]
+[[!template text="""to redirect links, to rewrite URLs,""" start="00:14:24.922" video="mainVideo-web" id="subtitle"]]
+[[!template text="""or to open, say, a YouTube URL with MPV,""" start="00:14:30.181" video="mainVideo-web" id="subtitle"]]
+[[!template text="""but with even more flexibility.""" start="00:14:37.061" video="mainVideo-web" id="subtitle"]]
+[[!template text="""For example, here's how one could""" start="00:14:39.800" video="mainVideo-web" id="subtitle"]]
+[[!template text="""transform a Zoom link to a dial-in number""" start="00:14:41.780" video="mainVideo-web" id="subtitle"]]
+[[!template text="""so that it is easier to join a Zoom meeting""" start="00:14:44.840" video="mainVideo-web" id="subtitle"]]
+[[!template text="""without running non-free JavaScript.""" start="00:14:47.480" video="mainVideo-web" id="subtitle"]]
+[[!template text="""This might still be bad for privacy,""" start="00:14:50.360" video="mainVideo-web" id="subtitle"]]
+[[!template text="""but at least it's good for freedom.""" start="00:14:53.040" video="mainVideo-web" id="subtitle"]]
+[[!template text="""As mentioned before,""" start="00:14:58.699" video="mainVideo-web" id="subtitle"]]
+[[!template text="""one shortcoming of these Emacs-based browsers,""" start="00:15:00.379" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Emacs web browsers, is no support for CSS,""" start="00:15:03.920" video="mainVideo-web" id="subtitle"]]
+[[!template text="""so the formatting could leave a lot to be desired.""" start="00:15:08.080" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Maybe someone would write""" start="00:15:11.320" video="mainVideo-web" id="subtitle"]]
+[[!template text="""an Emacs browser package backed by wkhtmltopdf,""" start="00:15:12.960" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which, when opening a URL,""" start="00:15:17.160" video="mainVideo-web" id="subtitle"]]
+[[!template text="""it calls wkhtmltopdf to convert the web page to PDF""" start="00:15:20.640" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and opens in, say, pdf-view-mode of the pdf-tools,""" start="00:15:26.480" video="mainVideo-web" id="subtitle"]]
+[[!template text="""thus containing formatting,""" start="00:15:29.640" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and all the URL clicks resolve to the same actions.""" start="00:15:31.040" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Also, wkhtmltopdf contains a flag that disables JavaScript.""" start="00:15:34.000" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Another idea would be to use Firefox""" start="00:15:43.300" video="mainVideo-web" id="subtitle"]]
+[[!template text="""as a processor to fetch URLs.""" start="00:15:45.240" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Maybe it can be used to pass back the HTML""" start="00:15:50.280" video="mainVideo-web" id="subtitle"]]
+[[!template text="""after executing free JavaScript,""" start="00:15:54.560" video="mainVideo-web" id="subtitle"]]
+[[!template text="""say, if Firefox has LibreJS installed.""" start="00:15:56.520" video="mainVideo-web" id="subtitle"]]
+[[!template text="""This requires Firefox to send back the DOM,""" start="00:16:01.440" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which could be achieved using native messaging.""" start="00:16:05.040" video="mainVideo-web" id="subtitle"]]
+[[!template text="""More on that later.""" start="00:16:08.040" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Alternatively, one could also write a Firefox extension""" start="00:16:09.720" video="mainVideo-web" id="subtitle"]]
+[[!template text="""that sends the DOM in an existing tab back to Emacs.""" start="00:16:14.240" video="mainVideo-web" id="subtitle"]]
+[[!template text="""But thinking more about it,""" start="00:16:17.640" video="mainVideo-web" id="subtitle"]]
+[[!template text="""I don't think this is actually a useful idea,""" start="00:16:20.080" video="mainVideo-web" id="subtitle"]]
+[[!template text="""because most of the sites that work under LibreJS""" start="00:16:23.059" video="mainVideo-web" id="subtitle"]]
+[[!template text="""also are useful when all JavaScript is blocked.""" start="00:16:27.139" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So, this means these sites are viewable""" start="00:16:34.420" video="mainVideo-web" id="subtitle"]]
+[[!template text="""under EWW, Luwak, etc.""" start="00:16:37.040" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And another issue is that""" start="00:16:42.160" video="mainVideo-web" id="subtitle"]]
+[[!template text="""this could also make running non-free JavaScript easier,""" start="00:16:43.640" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which is harmful to user freedom.""" start="00:16:46.560" video="mainVideo-web" id="subtitle"]]
+[[!template new="1" text="""OK, let's move on to the idea""" start="00:16:52.380" video="mainVideo-web" id="subtitle"]]
+[[!template text="""of running Emacs as a web server,""" start="00:16:54.240" video="mainVideo-web" id="subtitle"]]
+[[!template text="""so that Emacs client packages are web apps""" start="00:16:55.680" video="mainVideo-web" id="subtitle"]]
+[[!template text="""serving as alternative frontends.""" start="00:16:58.560" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Why would we want to do this?""" start="00:17:00.320" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Well, as much as one wants to be always in Emacs,""" start="00:17:02.240" video="mainVideo-web" id="subtitle"]]
+[[!template text="""it is not always feasible.""" start="00:17:06.080" video="mainVideo-web" id="subtitle"]]
+[[!template text="""For example, one may be on the go""" start="00:17:08.340" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and needs to look up something on the phone.""" start="00:17:10.720" video="mainVideo-web" id="subtitle"]]
+[[!template text="""On the other hand, Emacs client packages""" start="00:17:12.520" video="mainVideo-web" id="subtitle"]]
+[[!template text="""are just alternative frontends""" start="00:17:14.880" video="mainVideo-web" id="subtitle"]]
+[[!template text="""but written in Elisp and run in Emacs.""" start="00:17:16.160" video="mainVideo-web" id="subtitle"]]
+[[!template text="""With the help of emacs-web-server package,""" start="00:17:18.120" video="mainVideo-web" id="subtitle"]]
+[[!template text="""we can access Emacs packages on the web.""" start="00:17:20.760" video="mainVideo-web" id="subtitle"]]
+[[!template text="""emacs-web-server package is not something new,""" start="00:17:23.580" video="mainVideo-web" id="subtitle"]]
+[[!template text="""but seems to be underused in the community somehow.""" start="00:17:26.440" video="mainVideo-web" id="subtitle"]]
+[[!template new="1" text="""OK, let's start with a simple example called hello-emacs.""" start="00:17:30.380" video="mainVideo-web" id="subtitle"]]
+[[!template text="""It is pretty straightforward.""" start="00:17:33.360" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Just require the web server feature""" start="00:17:35.240" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and run ws-start to start a server process""" start="00:17:38.640" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and send the string &quot;hello emacs&quot;""" start="00:17:41.000" video="mainVideo-web" id="subtitle"]]
+[[!template text="""to the process regardless of the request.""" start="00:17:43.360" video="mainVideo-web" id="subtitle"]]
+[[!template text="""As you can see, it is going to be available""" start="00:17:45.540" video="mainVideo-web" id="subtitle"]]
+[[!template text="""at port 9000 of localhost.""" start="00:17:48.480" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Let's try it out.""" start="00:17:51.319" video="mainVideo-web" id="subtitle"]]
+[[!template text="""We need to first evaluate this code block.""" start="00:17:53.000" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And it works.""" start="00:18:01.840" video="mainVideo-web" id="subtitle"]]
+[[!template text="""To stop a server, just run ws-stop on the web server object.""" start="00:18:03.940" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Let's evaluate.""" start="00:18:10.840" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Yep, it stopped.""" start="00:18:14.960" video="mainVideo-web" id="subtitle"]]
+[[!template new="1" text="""OK, now let's move on to something funny""" start="00:18:17.580" video="mainVideo-web" id="subtitle"]]
+[[!template text="""that you should never run on the public web.""" start="00:18:20.000" video="mainVideo-web" id="subtitle"]]
+[[!template text="""I call it yolo.el.""" start="00:18:22.220" video="mainVideo-web" id="subtitle"]]
+[[!template text="""It uses htmlize""" start="00:18:23.920" video="mainVideo-web" id="subtitle"]]
+[[!template text="""to make any Emacs buffer available on the web.""" start="00:18:25.360" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Let's try it out.""" start="00:18:28.160" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Just require the thing and start the server by yolo-start.""" start="00:18:29.000" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And it's available at port 9999.""" start="00:18:33.000" video="mainVideo-web" id="subtitle"]]
+[[!template text="""By default, the root domain shows the splash screen""" start="00:18:38.120" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which needs to be available.""" start="00:18:41.600" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Running display-splash-screen ensures that,""" start="00:18:42.920" video="mainVideo-web" id="subtitle"]]
+[[!template text="""but here I've already run it.""" start="00:18:47.219" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So let's have a look.""" start="00:18:48.939" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And here we have the splash screen.""" start="00:18:54.560" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Emacs tutorial and such.""" start="00:18:56.640" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Unfortunately, none of these links work,""" start="00:19:00.240" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which is something we will revisit later.""" start="00:19:05.480" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So, to show an arbitrary buffer,""" start="00:19:10.000" video="mainVideo-web" id="subtitle"]]
+[[!template text="""just use the buffer name as a path.""" start="00:19:15.481" video="mainVideo-web" id="subtitle"]]
+[[!template text="""For example, the slide has the buffer named web.org,""" start="00:19:20.081" video="mainVideo-web" id="subtitle"]]
+[[!template text="""so we can display it.""" start="00:19:24.861" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Let's try something fancier,""" start="00:19:34.581" video="mainVideo-web" id="subtitle"]]
+[[!template text="""like the man page of ffmpeg.""" start="00:19:36.941" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So this is the man page of ffmpeg.""" start="00:19:40.880" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And the buffer name is a bit more complicated.""" start="00:19:45.120" video="mainVideo-web" id="subtitle"]]
+[[!template text="""I have the URL available here.""" start="00:19:48.520" video="mainVideo-web" id="subtitle"]]
+[[!template text="""It's missing a star.""" start="00:19:59.140" video="mainVideo-web" id="subtitle"]]
+[[!template text="""It's pretty neat if you ask me.""" start="00:20:05.980" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And, yeah, what else?""" start="00:20:12.560" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Well, we can also browse EWW in Firefox.""" start="00:20:14.880" video="mainVideo-web" id="subtitle"]]
+[[!template text="""For example, let's check out gnu.org,""" start="00:20:22.700" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and note that the buffer name is EWW with stars.""" start="00:20:30.600" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So, ah, it works.""" start="00:20:39.080" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And it has all the graphics even.""" start="00:20:41.979" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Now, how about we do it the other way around?""" start="00:20:50.900" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So we load the current slide web.org using this funny thing.""" start="00:20:55.640" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And it works.""" start="00:21:10.780" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Not as nice as the Org buffer, though.""" start="00:21:14.040" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Right, and now that gives me some funny idea.""" start="00:21:19.940" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So I'm a firm believer that memes are meant to be enjoyed""" start="00:21:27.440" video="mainVideo-web" id="subtitle"]]
+[[!template text="""in silence rather than read out loud.""" start="00:21:31.360" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So I will jump straight to trying this idea,""" start="00:21:33.200" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which is loading the EWW buffer URL with EWW itself.""" start="00:21:38.760" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Loading, loading, loading.""" start="00:21:49.860" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Spoiler alert, it never loads.""" start="00:21:53.840" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So that concludes the demo.""" start="00:21:59.100" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And so we can stop the server, web server, with `yolo-stop`.""" start="00:22:03.220" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So one could extend yolo to serve arbitrary Emacs commands,""" start="00:22:06.440" video="mainVideo-web" id="subtitle"]]
+[[!template text="""making it even more dangerous.""" start="00:22:13.400" video="mainVideo-web" id="subtitle"]]
+[[!template text="""That is, for example, `localhost:9000/m-x/magit-status`""" start="00:22:15.440" video="mainVideo-web" id="subtitle"]]
+[[!template text="""would run `magit-status`""" start="00:22:26.119" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and show the magit-status buffer in the web browser.""" start="00:22:27.820" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Or localhost:9000/m-x/eww/""" start="00:22:34.500" video="mainVideo-web" id="subtitle"]]
+[[!template text="""any arbitrary URL to browse arbitrary URL""" start="00:22:43.120" video="mainVideo-web" id="subtitle"]]
+[[!template text="""with EWW inside of Firefox.""" start="00:22:46.760" video="mainVideo-web" id="subtitle"]]
+[[!template text="""It can serve as a way to block all JavaScript,""" start="00:22:50.820" video="mainVideo-web" id="subtitle"]]
+[[!template text="""because EWW does not support JavaScript.""" start="00:22:53.880" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And enforce preferred colorscheme in Firefox,""" start="00:22:56.800" video="mainVideo-web" id="subtitle"]]
+[[!template text="""since htmlize, as you have noticed,""" start="00:23:00.080" video="mainVideo-web" id="subtitle"]]
+[[!template text="""faithfully reflects the theme used in Emacs.""" start="00:23:02.840" video="mainVideo-web" id="subtitle"]]
+[[!template new="1" text="""Okay, so we know that yolo is unsafe""" start="00:23:07.940" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and needs to be refined.""" start="00:23:10.339" video="mainVideo-web" id="subtitle"]]
+[[!template text="""In fact, we don't necessarily want""" start="00:23:11.540" video="mainVideo-web" id="subtitle"]]
+[[!template text="""to run Emacs on a web browser.""" start="00:23:13.440" video="mainVideo-web" id="subtitle"]]
+[[!template text="""After all, a modern web browser is""" start="00:23:15.600" video="mainVideo-web" id="subtitle"]]
+[[!template text="""something one has to fight all the time""" start="00:23:17.280" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and should be avoided whenever possible.""" start="00:23:19.080" video="mainVideo-web" id="subtitle"]]
+[[!template text="""We want to instead be able to access things""" start="00:23:21.601" video="mainVideo-web" id="subtitle"]]
+[[!template text="""when forced to be in a web browser,""" start="00:23:24.480" video="mainVideo-web" id="subtitle"]]
+[[!template text="""in which case only the motivations""" start="00:23:26.460" video="mainVideo-web" id="subtitle"]]
+[[!template text="""of an alternative frontend apply.""" start="00:23:28.360" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Moreover, the ideal situation is an Emacs web framework,""" start="00:23:31.300" video="mainVideo-web" id="subtitle"]]
+[[!template text="""a tool that automatically""" start="00:23:35.460" video="mainVideo-web" id="subtitle"]]
+[[!template text="""transforms Emacs packages to web apps,""" start="00:23:36.800" video="mainVideo-web" id="subtitle"]]
+[[!template text="""so that one does not need to write extra code""" start="00:23:39.200" video="mainVideo-web" id="subtitle"]]
+[[!template text="""to get a web app that does the same thing as the package.""" start="00:23:41.800" video="mainVideo-web" id="subtitle"]]
+[[!template text="""We also need all links in the web pages to work.""" start="00:23:45.560" video="mainVideo-web" id="subtitle"]]
+[[!template text="""As noted before, the links on the yolo Emacs splash screen""" start="00:23:49.100" video="mainVideo-web" id="subtitle"]]
+[[!template text="""do not work.""" start="00:23:52.400" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So here's a proof-of-concept example. It's called bom.el.""" start="00:23:53.840" video="mainVideo-web" id="subtitle"]]
+[[!template text="""It gets some weather forecast data""" start="00:23:58.200" video="mainVideo-web" id="subtitle"]]
+[[!template text="""from the Australian Bureau of Meteorology""" start="00:24:00.120" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and displays it in an org buffer.""" start="00:24:03.080" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So let's try it out. One could do `M-x bom`,""" start="00:24:05.560" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which shows an org buffer with links to each state.""" start="00:24:09.280" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So based in Melbourne, naturally,""" start="00:24:15.220" video="mainVideo-web" id="subtitle"]]
+[[!template text="""I would like to find out the weather of Victoria.""" start="00:24:17.200" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And yes, to execute this command. Wait, wait, wait. Right.""" start="00:24:21.840" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And we are at a buffer that shows""" start="00:24:27.840" video="mainVideo-web" id="subtitle"]]
+[[!template text="""the weather forecast of the whole of Victoria""" start="00:24:33.460" video="mainVideo-web" id="subtitle"]]
+[[!template text="""in the hierarchy. Note that this back button""" start="00:24:36.120" video="mainVideo-web" id="subtitle"]]
+[[!template text="""takes you to the previous page.""" start="00:24:39.479" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So here are the regions of Victoria.""" start="00:24:46.640" video="mainVideo-web" id="subtitle"]]
+[[!template text="""I think Melbourne is in Central.""" start="00:24:47.920" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And yeah, it shows""" start="00:24:53.800" video="mainVideo-web" id="subtitle"]]
+[[!template text="""the seven-day weather forecast of Melbourne.""" start="00:24:54.720" video="mainVideo-web" id="subtitle"]]
+[[!template text="""You can also reach this page by running,""" start="00:24:57.260" video="mainVideo-web" id="subtitle"]]
+[[!template text="""let's see, directly `M-x bom-state`.""" start="00:25:00.360" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Vic.""" start="00:25:08.600" video="mainVideo-web" id="subtitle"]]
+[[!template text="""OK. So this works.""" start="00:25:13.960" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And this is bom as an Emacs package.""" start="00:25:18.400" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Now let's check out bom as a web app""" start="00:25:21.380" video="mainVideo-web" id="subtitle"]]
+[[!template text="""transformed by Emacs web framework.""" start="00:25:23.981" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So start the web server with bom-start.""" start="00:25:28.040" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And let's try it out. It's at 9000 again.""" start="00:25:33.020" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Oops. Invalid path. Oh, that's because""" start="00:25:39.560" video="mainVideo-web" id="subtitle"]]
+[[!template text="""it makes exactly one command to one path.""" start="00:25:42.360" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So remember that we used the bom command""" start="00:25:46.120" video="mainVideo-web" id="subtitle"]]
+[[!template text="""to show the landing page.""" start="00:25:49.301" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So here we need the bom in the path as well.""" start="00:25:50.720" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And it shows the same landing page, except in HTML.""" start="00:25:54.440" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Let's check out Victoria weather forecast as before.""" start="00:26:00.680" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And it shows an HTML converted from the org buffer""" start="00:26:07.260" video="mainVideo-web" id="subtitle"]]
+[[!template text="""using ox export HTML, whatever.""" start="00:26:12.280" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And you can see even the back button is here.""" start="00:26:17.560" video="mainVideo-web" id="subtitle"]]
+[[!template text="""That takes you to /bom.""" start="00:26:20.359" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So let's have a look at Melbourne. Here it is.""" start="00:26:26.220" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Hooray, it works.""" start="00:26:29.140" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So, yeah, as usual,""" start="00:26:31.380" video="mainVideo-web" id="subtitle"]]
+[[!template text="""you can stop the web server with `M-x bom-stop`.""" start="00:26:33.960" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Right. And alternatively,""" start="00:26:40.560" video="mainVideo-web" id="subtitle"]]
+[[!template text="""it can also be deployed directly in terminal""" start="00:26:43.760" video="mainVideo-web" id="subtitle"]]
+[[!template text="""in a dedicated Emacs daemon.""" start="00:26:48.500" video="mainVideo-web" id="subtitle"]]
+[[!template text="""So you can see that there's a one-one correspondence""" start="00:26:56.100" video="mainVideo-web" id="subtitle"]]
+[[!template text="""between the Emacs package interface and the web interface.""" start="00:26:58.280" video="mainVideo-web" id="subtitle"]]
+[[!template text="""And that implies some restrictions to the Emacs package""" start="00:27:03.100" video="mainVideo-web" id="subtitle"]]
+[[!template text="""for the Emacs web framework to be able to do its job. Right.""" start="00:27:06.040" video="mainVideo-web" id="subtitle"]]
+[[!template text="""For example, the package needs to have an Org interface""" start="00:27:09.160" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and the links that trigger other commands""" start="00:27:13.440" video="mainVideo-web" id="subtitle"]]
+[[!template text="""need to be in Elisp links""" start="00:27:15.520" video="mainVideo-web" id="subtitle"]]
+[[!template text="""so that the Emacs web framework""" start="00:27:17.800" video="mainVideo-web" id="subtitle"]]
+[[!template text="""can translate it to web server URL path.""" start="00:27:20.760" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Note that Emacs web server framework is not a real package.""" start="00:27:24.800" video="mainVideo-web" id="subtitle"]]
+[[!template text="""I wrote some functions in bom.el serving the purpose,""" start="00:27:28.920" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and they should be separated out eventually""" start="00:27:33.340" video="mainVideo-web" id="subtitle"]]
+[[!template text="""without much trouble.""" start="00:27:35.720" video="mainVideo-web" id="subtitle"]]
+[[!template text="""One could get weather forecast""" start="00:27:37.760" video="mainVideo-web" id="subtitle"]]
+[[!template text="""without running JavaScript anyway,""" start="00:27:40.000" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which makes bom.el less important""" start="00:27:42.220" video="mainVideo-web" id="subtitle"]]
+[[!template text="""as an alternative web client.""" start="00:27:45.200" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Though it does provide, dare I say,""" start="00:27:48.320" video="mainVideo-web" id="subtitle"]]
+[[!template text="""a clean and minimal interface""" start="00:27:50.520" video="mainVideo-web" id="subtitle"]]
+[[!template text="""compared to common weather forecast web pages.""" start="00:27:52.480" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Other more relevant use cases could be Mastodon,""" start="00:27:55.720" video="mainVideo-web" id="subtitle"]]
+[[!template text="""whose official web client requires JavaScript""" start="00:27:58.640" video="mainVideo-web" id="subtitle"]]
+[[!template text="""to display a post.""" start="00:28:01.320" video="mainVideo-web" id="subtitle"]]
+[[!template text="""The mastorg package that shows an Org hierarchy of toots""" start="00:28:03.480" video="mainVideo-web" id="subtitle"]]
+[[!template text="""rooted as a given toot could be a low-hanging fruit.""" start="00:28:08.560" video="mainVideo-web" id="subtitle"]]
+[[!template text="""The limitation of Org interface requirements""" start="00:28:12.179" video="mainVideo-web" id="subtitle"]]
+[[!template text="""can also be relaxed in further work,""" start="00:28:15.200" video="mainVideo-web" id="subtitle"]]
+[[!template text="""if one could extend Emacs web framework""" start="00:28:17.880" video="mainVideo-web" id="subtitle"]]
+[[!template text="""to translate back and forth between Emacs widgets,""" start="00:28:21.640" video="mainVideo-web" id="subtitle"]]
+[[!template text="""say, including buttons and web page widgets,""" start="00:28:24.200" video="mainVideo-web" id="subtitle"]]
+[[!template text="""including links.""" start="00:28:28.640" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Another more far-fetched idea would be""" start="00:28:30.600" video="mainVideo-web" id="subtitle"]]
+[[!template text="""to translate to other types of interfaces,""" start="00:28:32.600" video="mainVideo-web" id="subtitle"]]
+[[!template text="""like GNU/Linux or Android GUI.""" start="00:28:35.800" video="mainVideo-web" id="subtitle"]]
+[[!template text="""How about animations? Say, M-x butterfly,""" start="00:28:44.020" video="mainVideo-web" id="subtitle"]]
+[[!template text="""or even web games from Emacs games?""" start="00:28:47.480" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Possibilities are unlimited in this, as always, in Emacs.""" start="00:28:54.000" video="mainVideo-web" id="subtitle"]]
+[[!template text="""I also noticed some limitations""" start="00:29:00.100" video="mainVideo-web" id="subtitle"]]
+[[!template text="""when trying to actually host bom.el on the public web.""" start="00:29:03.160" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Given the limited access to the Emacs server,""" start="00:29:07.440" video="mainVideo-web" id="subtitle"]]
+[[!template text="""I was comfortable enough to give bom.el a go""" start="00:29:13.540" video="mainVideo-web" id="subtitle"]]
+[[!template text="""to serve it on the public web.""" start="00:29:16.720" video="mainVideo-web" id="subtitle"]]
+[[!template text="""However, I immediately stopped""" start="00:29:18.800" video="mainVideo-web" id="subtitle"]]
+[[!template text="""after noticing how slow it is.""" start="00:29:20.560" video="mainVideo-web" id="subtitle"]]
+[[!template text="""It can take more than 30 seconds""" start="00:29:22.880" video="mainVideo-web" id="subtitle"]]
+[[!template text="""to load a page of weather forecast for a state.""" start="00:29:24.720" video="mainVideo-web" id="subtitle"]]
+[[!template text="""I am also not sure how many simultaneous connections""" start="00:29:27.840" video="mainVideo-web" id="subtitle"]]
+[[!template text="""it can handle.""" start="00:29:31.000" video="mainVideo-web" id="subtitle"]]
+[[!template text="""In any case, I think the package emacs-web-server""" start="00:29:32.380" video="mainVideo-web" id="subtitle"]]
+[[!template text="""could do with some performance enhancement.""" start="00:29:36.440" video="mainVideo-web" id="subtitle"]]
+[[!template new="1" text="""Right. Because of the time constraints,""" start="00:29:40.420" video="mainVideo-web" id="subtitle"]]
+[[!template text="""I will briefly touch one final idea,""" start="00:29:44.000" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which is to use Emacs as a Firefox browser extension.""" start="00:29:45.760" video="mainVideo-web" id="subtitle"]]
+[[!template text="""We already have org-protocol,""" start="00:29:50.420" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which allows Firefox to communicate""" start="00:29:52.900" video="mainVideo-web" id="subtitle"]]
+[[!template text="""with a running Emacs server""" start="00:29:54.440" video="mainVideo-web" id="subtitle"]]
+[[!template text="""by sending an org-protocol URL to the latter.""" start="00:29:55.920" video="mainVideo-web" id="subtitle"]]
+[[!template text="""It can be used not just for capturing or storing links,""" start="00:29:59.780" video="mainVideo-web" id="subtitle"]]
+[[!template text="""but to execute arbitrary code on any component of the URL.""" start="00:30:03.160" video="mainVideo-web" id="subtitle"]]
+[[!template text="""However, it is fire and forget,""" start="00:30:10.120" video="mainVideo-web" id="subtitle"]]
+[[!template text="""and Emacs cannot tell Firefox what to do.""" start="00:30:11.680" video="mainVideo-web" id="subtitle"]]
+[[!template text="""There may be a length restriction, too.""" start="00:30:16.480" video="mainVideo-web" id="subtitle"]]
+[[!template text="""For example, Firefox may not be able to send back""" start="00:30:17.920" video="mainVideo-web" id="subtitle"]]
+[[!template text="""the whole DOM.""" start="00:30:20.400" video="mainVideo-web" id="subtitle"]]
+[[!template text="""This claim needs to be verified, though.""" start="00:30:22.420" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Native messaging is one solution to this problem.""" start="00:30:26.220" video="mainVideo-web" id="subtitle"]]
+[[!template text="""It is a two-way communication channel""" start="00:30:30.020" video="mainVideo-web" id="subtitle"]]
+[[!template text="""between a Firefox web extension and a local system process""" start="00:30:31.640" video="mainVideo-web" id="subtitle"]]
+[[!template text="""started by the web extension.""" start="00:30:35.320" video="mainVideo-web" id="subtitle"]]
+[[!template text="""The process could be an Emacs server,""" start="00:30:37.840" video="mainVideo-web" id="subtitle"]]
+[[!template text="""which would make Emacs effectively""" start="00:30:40.400" video="mainVideo-web" id="subtitle"]]
+[[!template text="""a Firefox web browser extension.""" start="00:30:42.400" video="mainVideo-web" id="subtitle"]]
+[[!template text="""In this case, Elisp would be the main extension language,""" start="00:30:48.680" video="mainVideo-web" id="subtitle"]]
+[[!template text="""rather than JavaScript.""" start="00:30:52.000" video="mainVideo-web" id="subtitle"]]
+[[!template text="""However, JavaScript is still needed at the Firefox end""" start="00:30:53.620" video="mainVideo-web" id="subtitle"]]
+[[!template text="""of the communication channel.""" start="00:30:56.160" video="mainVideo-web" id="subtitle"]]
+[[!template text="""As a simple example of this idea,""" start="00:30:59.320" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Firefox could ask Emacs to redirect a URL""" start="00:31:01.160" video="mainVideo-web" id="subtitle"]]
+[[!template text="""by removing tracking and using alternative frontend, etc.""" start="00:31:04.440" video="mainVideo-web" id="subtitle"]]
+[[!template text="""However, I was not able to implement this""" start="00:31:08.320" video="mainVideo-web" id="subtitle"]]
+[[!template text="""due to some tricky business""" start="00:31:12.480" video="mainVideo-web" id="subtitle"]]
+[[!template text="""with enforcing synchronicity""" start="00:31:14.280" video="mainVideo-web" id="subtitle"]]
+[[!template text="""that allows the web extension""" start="00:31:15.640" video="mainVideo-web" id="subtitle"]]
+[[!template text="""to wait for responses from Emacs.""" start="00:31:17.120" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Some further work, I suppose.""" start="00:31:20.200" video="mainVideo-web" id="subtitle"]]
+[[!template new="1" text="""That concludes my talk.""" start="00:31:25.360" video="mainVideo-web" id="subtitle"]]
+[[!template text="""Thank you for your attention.""" start="00:31:28.254" video="mainVideo-web" id="subtitle"]]
+
+
+
+Captioner: ken
+
Questions or comments? Please e-mail [id@ypei.org](mailto:id@ypei.org?subject=Comment%20for%20EmacsConf%202022%20web%3A%20Emacs%20saves%20the%20Web%20%28maybe%29)
diff --git a/2023/info/web-before.md b/2023/info/web-before.md
index 09fb6743..3677391f 100644
--- a/2023/info/web-before.md
+++ b/2023/info/web-before.md
@@ -8,12 +8,26 @@ The following image shows where the talk is in the schedule for Sun 2023-12-03.
Format: 32-min talk; Q&A: BigBlueButton conference room <https://media.emacsconf.org/2023/current/bbb-web.html>
Etherpad: <https://pad.emacsconf.org/2023-web>
Discuss on IRC: [#emacsconf-gen](https://chat.emacsconf.org/?join=emacsconf,emacsconf-gen)
-Status: Ready to stream
+Status: Now playing on the conference livestream
<div>Times in different timezones:</div><div class="times" start="2023-12-03T20:10:00Z" end="2023-12-03T20:40:00Z"><div class="conf-time">Sunday, Dec 3 2023, ~3:10 PM - 3:40 PM EST (US/Eastern)</div><div class="others"><div>which is the same as:</div>Sunday, Dec 3 2023, ~2:10 PM - 2:40 PM CST (US/Central)<br />Sunday, Dec 3 2023, ~1:10 PM - 1:40 PM MST (US/Mountain)<br />Sunday, Dec 3 2023, ~12:10 PM - 12:40 PM PST (US/Pacific)<br />Sunday, Dec 3 2023, ~8:10 PM - 8:40 PM UTC <br />Sunday, Dec 3 2023, ~9:10 PM - 9:40 PM CET (Europe/Paris)<br />Sunday, Dec 3 2023, ~10:10 PM - 10:40 PM EET (Europe/Athens)<br />Monday, Dec 4 2023, ~1:40 AM - 2:10 AM IST (Asia/Kolkata)<br />Monday, Dec 4 2023, ~4:10 AM - 4:40 AM +08 (Asia/Singapore)<br />Monday, Dec 4 2023, ~5:10 AM - 5:40 AM JST (Asia/Tokyo)</div></div><div><strong><a href="/2023/watch/gen/">Find out how to watch and participate</a></strong></div>
+<div class="vid"><video controls preload="none" id="web-mainVideo"><source src="https://media.emacsconf.org/2023/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei--main.webm" />captions="""<track label="English" kind="captions" srclang="en" src="/2023/captions/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei--main.vtt" default />"""<track kind="chapters" label="Chapters" src="/2023/captions/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei--main--chapters.vtt" /><p><em>Your browser does not support the video tag. Please download the video instead.</em></p></video>[[!template id="chapters" vidid="web-mainVideo" data="""
+00:00.000 Overview
+00:35.680 Background problems
+05:31.940 Solutions outside of Emacs
+09:46.480 Emacs solutions
+09:54.600 Free clients in Emacs
+12:43.021 Web browsers in Emacs
+16:52.380 emacs-web-server - overview
+17:30.380 emacs-web-server - hello emacs!
+18:17.580 emacs-web-server - yolo
+23:07.940 emacs-web-server - emacs web framework
+29:40.420 Firefox with emacs for extensions
+31:25.360 Thank you
+"""]]<div></div>Duration: 31:33 minutes<div class="files resources"><ul><li><a href="https://pad.emacsconf.org/2023-web">Open Etherpad</a></li><li><a href="https://media.emacsconf.org/2023/current/bbb-web.html">Open public Q&A</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei--final.webm">Download --final.webm (53MB)</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei--intro.vtt">Download --intro.vtt</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei--intro.webm">Download --intro.webm</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei--main--chapters.vtt">Download --main--chapters.vtt</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei--main.opus">Download --main.opus (17MB)</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei--main.txt">Download --main.txt</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei--main.vtt">Download --main.vtt</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei--main.webm">Download --main.webm (53MB)</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei--normalized.opus">Download --normalized.opus (27MB)</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei--original.mkv">Download --original.mkv (57MB)</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei--reencoded.webm">Download --reencoded.webm (43MB)</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-web--emacs-saves-the-web-maybe--yuchen-pei.org">Download .org</a></li><li><a href="https://toobnix.org/w/fvzGU4cQQ2meZVKNGEHMht">View on Toobnix</a></li></ul></div></div>
# Description
<!-- End of emacsconf-publish-before-page --> \ No newline at end of file