diff --git a/data/images/icon.png b/data/images/icon.png
new file mode 100755
index 0000000..8204d8e
Binary files /dev/null and b/data/images/icon.png differ
diff --git a/node_modules b/node_modules
new file mode 120000
index 0000000..8db783c
--- /dev/null
+++ b/node_modules
@@ -0,0 +1 @@
+/nix/store/shdrgyl1s3ljcpbhnzypff3q5y1b5zm8-gen2.space-node-sources/node_modules
\ No newline at end of file
diff --git a/registry.dat b/registry.dat
new file mode 100644
index 0000000..f3f24c2
Binary files /dev/null and b/registry.dat differ
diff --git a/template.html b/template.html
new file mode 100644
index 0000000..d0d51d1
--- /dev/null
+++ b/template.html
@@ -0,0 +1,45 @@
+
+
+
+
+ gen2.space
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/wand.js b/wand.js
new file mode 100644
index 0000000..c415566
--- /dev/null
+++ b/wand.js
@@ -0,0 +1,4 @@
+document.body.innerHTML = ''
+const sourceTarget = document.createElement('script')
+sourceTarget.src = '/main.js'
+document.body.appendChild(sourceTarget)
diff --git a/webpack.config.js b/webpack.config.js
new file mode 100644
index 0000000..12c9500
--- /dev/null
+++ b/webpack.config.js
@@ -0,0 +1,191 @@
+const ROUTES = ["/","/about","/404","/posts","/posts/viveahk","/posts/librebasics"]
+const PRETTY_NAME = "gen2.space"
+const DESCRIPTION = "notgne2's shitty pages"
+const THEME_COLOR = "#004400"
+const BACKGROUND_COLOR = "#220044"
+
+const path = require('path')
+const TerserPlugin = require('terser-webpack-plugin')
+const HtmlWebpackPlugin = require('html-webpack-plugin')
+const CopyPlugin = require('copy-webpack-plugin')
+const { InjectManifest } = require('workbox-webpack-plugin')
+const ImageminPlugin = require('imagemin-webpack-plugin').default
+const ImageminWebpWebpackPlugin = require('imagemin-webp-webpack-plugin')
+const FaviconsWebpackPlugin = require('favicons-webpack-plugin')
+const { JSDOM } = require('jsdom')
+const tempy = require('tempy')
+const fs = require('fs')
+const webpack = require('webpack')
+
+const magicFile = (text) => {
+ const p = tempy.file()
+ fs.writeFileSync(p, text)
+ return p
+}
+
+const jsMin = {
+ mangle: true,
+ compress: {
+ keep_fargs: false,
+ pure_getters: true,
+ pure_funcs: ['F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'],
+ unsafe: true,
+ ecma: 6,
+ unsafe_comps: true,
+ unsafe_arrows: true,
+ }
+}
+
+const htmlMin = {
+ minifyCSS: {
+ compatibility: 'ie9',
+ level: 2
+ },
+ minifyJS: jsMin,
+
+ collapseBooleanAttributes: true,
+ removeRedundantAttributes: true,
+ removeScriptTypeAttributes: true,
+ removeStyleLinkTypeAttributes: true,
+
+ removeComments: true,
+ sortAttributes: true,
+ sortClassName: true,
+}
+
+const productionPlugins = [
+ new InjectManifest({
+ importWorkboxFrom: 'local',
+ swSrc: magicFile(`
+ workbox.core.skipWaiting();
+ workbox.core.clientsClaim();
+ workbox.precaching.cleanupOutdatedCaches()
+ workbox.routing.registerNavigationRoute('/index.html');
+ workbox.precaching.precacheAndRoute(self.__precacheManifest);
+ `),
+ swDest: 'sw.js',
+ }),
+ new ImageminPlugin({
+ jpegtran: { progressive: true },
+ svgo: null,
+ }),
+ new ImageminWebpWebpackPlugin({
+ config: [{
+ test: /\.jpe?g/,
+ options: {
+ force: true,
+ quality: 75
+ }
+ }, {
+ test: /\.l\.png/,
+ options: {
+ force: true,
+ quality: 75
+ }
+ }, {
+ test: /\.png/,
+ options: {
+ force: true,
+ lossless: true
+ }
+ }],
+ overrideExtension: false,
+ detailedLogs: false,
+ silent: true,
+ strict: true,
+ }),
+ new FaviconsWebpackPlugin({
+ logo: path.join(__dirname, 'data', 'images', 'icon.png'),
+ inject: false, // manually in our template for now cos its fuckd
+ mode: 'webapp',
+ prefix: 'appdata',
+ favicons: {
+ appName: PRETTY_NAME,
+ appDescription: DESCRIPTION,
+ background: BACKGROUND_COLOR,
+ theme_color: THEME_COLOR,
+ }
+ }),
+];
+
+let plugins = (env, argv) => [
+ new webpack.HotModuleReplacementPlugin(),
+ new CopyPlugin([{ from: 'data', to: 'data' }, { from: 'wand.js', to: 'wand.js' }]),
+ new HtmlWebpackPlugin({
+ hash: true,
+ inject: true,
+ minify: argv.mode == 'production' ? htmlMin : false,
+ template: './template.html',
+ meta: {
+ viewport: 'width=320, initial-scale=1, maximum-scale=5',
+ description: DESCRIPTION,
+ }
+ }),
+];
+
+module.exports = (env, argv) => ({
+ target: 'web',
+ externals: {
+ svgo: 'svgo'
+ },
+ entry: magicFile(`
+ if ('serviceWorker' in navigator) {
+ window.addEventListener('load', () => navigator.serviceWorker.register('/sw.js'));
+ }
+
+ require('${process.env.PWD}/src/index.js')
+ `),
+ output: {
+ filename: 'main.js',
+ path: path.join(__dirname, 'dist'),
+ publicPath: '/'
+ },
+ module: {
+ rules: [
+ {
+ test: /\.elm$/,
+ exclude: [/elm-stuff/, /node_modules/],
+ use: [
+ {
+ loader: 'elm-hot-webpack-loader',
+ options: {
+ debug: argv.mode != 'production',
+ }
+ },
+ {
+ loader: 'elm-webpack-loader',
+ options: {
+ optimize: argv.mode == 'production',
+ debug: argv.mode != 'production',
+ },
+ },
+ ],
+ },
+ {
+ test: /\.html$/,
+ loader: 'html-loader',
+ options: {
+ minimize: true,
+ ...htmlMin
+ },
+ },
+ {
+ test: /\.css$/i,
+ use: ['style-loader', 'css-loader'],
+ },
+ ],
+ },
+ devServer: {
+ inline: true,
+ hot: true,
+ stats: 'errors-only'
+ },
+ optimization: {
+ minimize: argv.mode == 'production',
+ minimizer: [
+ new TerserPlugin({ terserOptions: jsMin }),
+ new TerserPlugin({ terserOptions: jsMin }),
+ ],
+ },
+ plugins: [...plugins(env, argv), ...(argv.mode == 'production' ? productionPlugins : [])],
+})