mirror of
https://github.com/jakejarvis/jarv.is.git
synced 2025-10-27 02:35:50 -04:00
deploy to Vercel
This commit is contained in:
@@ -11,7 +11,7 @@
|
|||||||
"es6": true
|
"es6": true
|
||||||
},
|
},
|
||||||
"overrides": [{
|
"overrides": [{
|
||||||
"files": ["functions/**/*.js"],
|
"files": ["api/**/*.js"],
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
"ecmaVersion": 2018,
|
"ecmaVersion": 2018,
|
||||||
"sourceType": "module"
|
"sourceType": "module"
|
||||||
|
|||||||
100
.github/workflows/ci.yml
vendored
100
.github/workflows/ci.yml
vendored
@@ -1,100 +0,0 @@
|
|||||||
name: CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
# "[skip ci]" also causes Netlify to skip, so these are automatically in harmony
|
|
||||||
# https://docs.netlify.com/site-deploys/manage-deploys/#skip-a-deploy
|
|
||||||
if: "github.actor == 'jakejarvis' && !contains(github.event.head_commit.message, '[skip ci]')"
|
|
||||||
timeout-minutes: 20
|
|
||||||
steps:
|
|
||||||
- name: Wait for Netlify
|
|
||||||
# installing via `npx` each run takes a long time, but deploys always take longer
|
|
||||||
run: npx netlify-cli watch
|
|
||||||
env:
|
|
||||||
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
|
|
||||||
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
|
||||||
|
|
||||||
audit:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: deploy
|
|
||||||
env:
|
|
||||||
LHCI_TOKEN: ${{ secrets.LHCI_TOKEN }}
|
|
||||||
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
fetch-depth: 2
|
|
||||||
lfs: false
|
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: 16.x
|
|
||||||
- name: Install LHCI
|
|
||||||
run: npm install -g @lhci/cli
|
|
||||||
- name: Check LHCI
|
|
||||||
run: |
|
|
||||||
lhci --version
|
|
||||||
lhci healthcheck
|
|
||||||
- name: Audit deploy preview
|
|
||||||
if: "github.event_name == 'pull_request'"
|
|
||||||
continue-on-error: true
|
|
||||||
run: |
|
|
||||||
lhci autorun \
|
|
||||||
--collect.url=https://deploy-preview-${{ github.event.number }}--jakejarvis.netlify.app/ \
|
|
||||||
--collect.url=https://deploy-preview-${{ github.event.number }}--jakejarvis.netlify.app/notes/how-to-pull-request-fork-github/
|
|
||||||
- name: Audit production site
|
|
||||||
if: "github.event_name == 'push' && github.ref == 'refs/heads/main'"
|
|
||||||
continue-on-error: true
|
|
||||||
run: |
|
|
||||||
lhci autorun \
|
|
||||||
--collect.url=https://jarv.is/ \
|
|
||||||
--collect.url=https://jarv.is/notes/how-to-pull-request-fork-github/
|
|
||||||
- name: Upload results as artifact
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
if: success()
|
|
||||||
with:
|
|
||||||
name: lhci-results
|
|
||||||
path: ./.lighthouseci
|
|
||||||
|
|
||||||
lint:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: "!contains(github.event.head_commit.message, '[skip ci]')"
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
fetch-depth: 1
|
|
||||||
lfs: false
|
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: 16.x
|
|
||||||
- name: Get Yarn cache path
|
|
||||||
# https://github.com/actions/cache/blob/master/examples.md#node---yarn
|
|
||||||
# https://github.com/actions/cache/issues/60
|
|
||||||
id: yarn-cache
|
|
||||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
|
||||||
- name: Cache dependencies
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: ${{ steps.yarn-cache.outputs.dir }}
|
|
||||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-yarn-
|
|
||||||
- name: Install dependencies
|
|
||||||
run: yarn install --no-ignore-optional --frozen-lockfile
|
|
||||||
- name: Audit dependencies
|
|
||||||
run: yarn audit || true
|
|
||||||
continue-on-error: true
|
|
||||||
- name: Build preview
|
|
||||||
run: yarn build:hugo --environment development --baseURL / --buildDrafts --buildFuture
|
|
||||||
- name: Lint
|
|
||||||
run: yarn lint
|
|
||||||
- name: Percy snapshots
|
|
||||||
uses: percy/snapshot-action@v0.1.2
|
|
||||||
env:
|
|
||||||
PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }}
|
|
||||||
71
.github/workflows/codeql-analysis.yml
vendored
71
.github/workflows/codeql-analysis.yml
vendored
@@ -1,71 +0,0 @@
|
|||||||
# For most projects, this workflow file will not need changing; you simply need
|
|
||||||
# to commit it to your repository.
|
|
||||||
#
|
|
||||||
# You may wish to alter this file to override the set of languages analyzed,
|
|
||||||
# or to provide custom queries or build logic.
|
|
||||||
#
|
|
||||||
# ******** NOTE ********
|
|
||||||
# We have attempted to detect the languages in your repository. Please check
|
|
||||||
# the `language` matrix defined below to confirm you have the correct set of
|
|
||||||
# supported CodeQL languages.
|
|
||||||
#
|
|
||||||
name: "CodeQL"
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ main ]
|
|
||||||
pull_request:
|
|
||||||
# The branches below must be a subset of the branches above
|
|
||||||
branches: [ main ]
|
|
||||||
schedule:
|
|
||||||
- cron: '41 7 * * 6'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
analyze:
|
|
||||||
name: Analyze
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
actions: read
|
|
||||||
contents: read
|
|
||||||
security-events: write
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
language: [ 'javascript' ]
|
|
||||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
|
||||||
# Learn more:
|
|
||||||
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
|
||||||
- name: Initialize CodeQL
|
|
||||||
uses: github/codeql-action/init@v1
|
|
||||||
with:
|
|
||||||
languages: ${{ matrix.language }}
|
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
|
||||||
# By default, queries listed here will override any specified in a config file.
|
|
||||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
|
||||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
|
||||||
|
|
||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
|
||||||
# If this step fails, then you should remove it and run the build manually (see below)
|
|
||||||
- name: Autobuild
|
|
||||||
uses: github/codeql-action/autobuild@v1
|
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
|
||||||
# 📚 https://git.io/JvXDl
|
|
||||||
|
|
||||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
|
||||||
# and modify them (or add more) to build your code if your project
|
|
||||||
# uses a compiled language
|
|
||||||
|
|
||||||
- run: |
|
|
||||||
yarn install --no-ignore-optional --frozen-lockfile
|
|
||||||
yarn build:functions
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
|
||||||
uses: github/codeql-action/analyze@v1
|
|
||||||
15
.github/workflows/purge-artifacts.yml
vendored
15
.github/workflows/purge-artifacts.yml
vendored
@@ -1,15 +0,0 @@
|
|||||||
name: Purge old artifacts
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 9 * * 3' # every Wednesday at 9 AM UTC == 5 AM EDT
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
purge-artifacts:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: kolpav/purge-artifacts-action@v1
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
expire-in: 0
|
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -11,8 +11,8 @@ npm-debug.log*
|
|||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
|
||||||
# local Netlify config
|
# local Vercel config
|
||||||
.netlify/
|
.vercel/
|
||||||
|
|
||||||
# Lighthouse CI
|
# Lighthouse CI
|
||||||
.lighthouseci/
|
.lighthouseci/
|
||||||
|
|||||||
@@ -16,9 +16,10 @@ postcss.config.js
|
|||||||
devcontainer.json
|
devcontainer.json
|
||||||
|
|
||||||
# miscellaneous
|
# miscellaneous
|
||||||
|
vercel.json
|
||||||
|
.vercel/
|
||||||
.github/
|
.github/
|
||||||
.lighthouseci/
|
.lighthouseci/
|
||||||
.netlify/
|
|
||||||
.vscode/
|
.vscode/
|
||||||
LICENSE.md
|
LICENSE.md
|
||||||
content/notes/dark-mode/example.html
|
content/notes/dark-mode/example.html
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
# 🏡 [jarv.is](https://jarv.is/)
|
# 🏡 [jarv.is](https://jarv.is/)
|
||||||
|
|
||||||
[](https://app.netlify.com/sites/jakejarvis/deploys)
|
|
||||||
[](https://github.com/jakejarvis/jarv.is/actions?query=workflow%3ACI+branch%3Amain)
|
[](https://github.com/jakejarvis/jarv.is/actions?query=workflow%3ACI+branch%3Amain)
|
||||||
[](https://github.com/gohugoio/hugo)
|
[](https://github.com/gohugoio/hugo)
|
||||||
[](LICENSE.md)
|
[](LICENSE.md)
|
||||||
[](https://github.com/jakejarvis/jarv.is)
|
[](https://github.com/jakejarvis/jarv.is)
|
||||||
[](http://jarvis2i2vp4j4tbxjogsnqdemnte5xhzyi7hziiyzxwge3hzmh57zad.onion/)
|
[](http://jarvis2i2vp4j4tbxjogsnqdemnte5xhzyi7hziiyzxwge3hzmh57zad.onion/)
|
||||||
|
|
||||||
Personal website of [@jakejarvis](https://github.com/jakejarvis), created and deployed using [Hugo](https://github.com/gohugoio/hugo), [Netlify](https://www.netlify.com/), [and more](https://jarv.is/uses/).
|
Personal website of [@jakejarvis](https://github.com/jakejarvis), created and deployed using [Hugo](https://github.com/gohugoio/hugo), [Vercel](https://vercel.com/), [and more](https://jarv.is/uses/).
|
||||||
|
|
||||||
I keep an ongoing list of [blog post ideas](https://github.com/jakejarvis/jarv.is/issues/1) and [coding to-dos](https://github.com/jakejarvis/jarv.is/issues/11) as issues in this repo.
|
I keep an ongoing list of [blog post ideas](https://github.com/jakejarvis/jarv.is/issues/1) and [coding to-dos](https://github.com/jakejarvis/jarv.is/issues/11) as issues in this repo.
|
||||||
|
|
||||||
|
|||||||
@@ -6,20 +6,16 @@ const numeral = require("numeral");
|
|||||||
const pluralize = require("pluralize");
|
const pluralize = require("pluralize");
|
||||||
require("dotenv").config();
|
require("dotenv").config();
|
||||||
|
|
||||||
// .....??????
|
module.exports = async (req, res) => {
|
||||||
// https://github.com/netlify/netlify-lambda/issues/201
|
const { slug } = req.query;
|
||||||
require("encoding");
|
|
||||||
|
|
||||||
exports.handler = async (event) => {
|
|
||||||
const { slug } = event.queryStringParameters;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// some rudimentary error handling
|
// some rudimentary error handling
|
||||||
if (!process.env.FAUNADB_SERVER_SECRET) {
|
if (!process.env.FAUNADB_SERVER_SECRET) {
|
||||||
throw new Error("Database credentials aren't set.");
|
throw new Error("Database credentials aren't set.");
|
||||||
}
|
}
|
||||||
if (event.httpMethod !== "GET") {
|
if (req.method !== "GET") {
|
||||||
throw new Error(`Method ${event.httpMethod} not allowed.`);
|
throw new Error(`Method ${req.method} not allowed.`);
|
||||||
}
|
}
|
||||||
if (!slug || slug === "/") {
|
if (!slug || slug === "/") {
|
||||||
throw new Error("Parameter `slug` is required.");
|
throw new Error("Parameter `slug` is required.");
|
||||||
@@ -33,32 +29,21 @@ exports.handler = async (event) => {
|
|||||||
const result = await client.query(q.Call(q.Function("hit"), slug));
|
const result = await client.query(q.Call(q.Function("hit"), slug));
|
||||||
|
|
||||||
// send client the new hit count
|
// send client the new hit count
|
||||||
return {
|
res.setHeader("Cache-Control", "private, no-cache, no-store, must-revalidate");
|
||||||
statusCode: 200,
|
res.setHeader("Expires", 0);
|
||||||
headers: {
|
res.setHeader("Pragma", "no-cache");
|
||||||
"Content-Type": "application/json; charset=utf-8",
|
res.setHeader("Access-Control-Allow-Methods", "GET");
|
||||||
"Cache-Control": "private, no-cache, no-store, must-revalidate",
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
||||||
Expires: "0",
|
return res.json({
|
||||||
Pragma: "no-cache",
|
slug: result.data.slug,
|
||||||
"Access-Control-Allow-Methods": "GET",
|
hits: result.data.hits,
|
||||||
"Access-Control-Allow-Origin": "*",
|
pretty_hits: numeral(result.data.hits).format("0,0"),
|
||||||
},
|
pretty_unit: pluralize("hit", result.data.hits),
|
||||||
body: JSON.stringify({
|
});
|
||||||
slug: result.data.slug,
|
|
||||||
hits: result.data.hits,
|
|
||||||
pretty_hits: numeral(result.data.hits).format("0,0"),
|
|
||||||
pretty_unit: pluralize("hit", result.data.hits),
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
|
||||||
return {
|
return res.status(400).json({ message: error.message });
|
||||||
statusCode: 400,
|
|
||||||
body: JSON.stringify({
|
|
||||||
message: error.message,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -64,11 +64,11 @@ async function fetchRepos(sort, limit) {
|
|||||||
return currentRepos;
|
return currentRepos;
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.handler = async (event) => {
|
module.exports = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
// some rudimentary error handling
|
// some rudimentary error handling
|
||||||
if (event.httpMethod !== "GET") {
|
if (req.method !== "GET") {
|
||||||
throw new Error(`Method ${event.httpMethod} not allowed.`);
|
throw new Error(`Method ${req.method} not allowed.`);
|
||||||
}
|
}
|
||||||
if (!process.env.GH_PUBLIC_TOKEN) {
|
if (!process.env.GH_PUBLIC_TOKEN) {
|
||||||
throw new Error("GitHub API credentials aren't set.");
|
throw new Error("GitHub API credentials aren't set.");
|
||||||
@@ -77,27 +77,18 @@ exports.handler = async (event) => {
|
|||||||
// default to latest repos
|
// default to latest repos
|
||||||
let sortBy = "PUSHED_AT";
|
let sortBy = "PUSHED_AT";
|
||||||
// get most popular repos (/projects?top)
|
// get most popular repos (/projects?top)
|
||||||
if (typeof event.queryStringParameters.top !== "undefined") sortBy = "STARGAZERS";
|
if (typeof req.query.top !== "undefined") sortBy = "STARGAZERS";
|
||||||
|
|
||||||
const repos = await fetchRepos(sortBy, 16);
|
const repos = await fetchRepos(sortBy, 16);
|
||||||
|
|
||||||
return {
|
// let Vercel edge cache results for 10 mins
|
||||||
statusCode: 200,
|
res.setHeader("Cache-Control", "s-maxage=600, stale-while-revalidate");
|
||||||
headers: {
|
res.setHeader("Access-Control-Allow-Methods", "GET");
|
||||||
"Content-Type": "application/json; charset=utf-8",
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
||||||
"Access-Control-Allow-Methods": "GET",
|
return res.json(repos);
|
||||||
"Access-Control-Allow-Origin": "*",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(repos),
|
|
||||||
};
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
|
||||||
return {
|
return res.status(400).json({ message: error.message });
|
||||||
statusCode: 400,
|
|
||||||
body: JSON.stringify({
|
|
||||||
message: error.message,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -9,14 +9,14 @@ require("dotenv").config();
|
|||||||
|
|
||||||
const baseUrl = "https://jarv.is/";
|
const baseUrl = "https://jarv.is/";
|
||||||
|
|
||||||
exports.handler = async (event) => {
|
module.exports = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
// some rudimentary error handling
|
// some rudimentary error handling
|
||||||
if (!process.env.FAUNADB_SERVER_SECRET) {
|
if (!process.env.FAUNADB_SERVER_SECRET) {
|
||||||
throw new Error("Database credentials aren't set.");
|
throw new Error("Database credentials aren't set.");
|
||||||
}
|
}
|
||||||
if (event.httpMethod !== "GET") {
|
if (req.method !== "GET") {
|
||||||
throw new Error(`Method ${event.httpMethod} not allowed.`);
|
throw new Error(`Method ${req.method} not allowed.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const parser = new rssParser({
|
const parser = new rssParser({
|
||||||
@@ -73,23 +73,12 @@ exports.handler = async (event) => {
|
|||||||
stats.total.pretty_hits = numeral(stats.total.hits).format("0,0");
|
stats.total.pretty_hits = numeral(stats.total.hits).format("0,0");
|
||||||
stats.total.pretty_unit = pluralize("hit", stats.total.hits);
|
stats.total.pretty_unit = pluralize("hit", stats.total.hits);
|
||||||
|
|
||||||
return {
|
res.setHeader("Access-Control-Allow-Methods", "GET");
|
||||||
statusCode: 200,
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
||||||
headers: {
|
return res.json(stats);
|
||||||
"Content-Type": "application/json; charset=utf-8",
|
|
||||||
"Access-Control-Allow-Methods": "GET",
|
|
||||||
"Access-Control-Allow-Origin": "*",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(stats),
|
|
||||||
};
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
|
||||||
return {
|
return res.status(400).json({ message: error.message });
|
||||||
statusCode: 400,
|
|
||||||
body: JSON.stringify({
|
|
||||||
message: error.message,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
// this will return an error from the API anyways
|
// this will return an error from the API anyways
|
||||||
if (!slug || slug === "/") return;
|
if (!slug || slug === "/") return;
|
||||||
|
|
||||||
fetch("/api/hits?slug=" + slug)
|
fetch("/api/hits/?slug=" + slug)
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (typeof data.hits !== "undefined") {
|
if (typeof data.hits !== "undefined") {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
var wrapper = document.getElementById("github-cards");
|
var wrapper = document.getElementById("github-cards");
|
||||||
|
|
||||||
if (wrapper) {
|
if (wrapper) {
|
||||||
fetch("/api/projects?top")
|
fetch("/api/projects/?top")
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
data.forEach((repo) => {
|
data.forEach((repo) => {
|
||||||
|
|||||||
28
config.toml
28
config.toml
@@ -21,9 +21,6 @@ disableKinds = ["taxonomy", "term"]
|
|||||||
# don't worry, inserted manually :)
|
# don't worry, inserted manually :)
|
||||||
disableHugoGeneratorInject = true
|
disableHugoGeneratorInject = true
|
||||||
|
|
||||||
# prefer Netlify's _redirects file, see outputs below
|
|
||||||
disableAliases = true
|
|
||||||
|
|
||||||
[params]
|
[params]
|
||||||
description = "Hi there! I'm a frontend web developer based in Boston, Massachusetts specializing in the JAMstack, modern JavaScript frameworks, and progressive web apps."
|
description = "Hi there! I'm a frontend web developer based in Boston, Massachusetts specializing in the JAMstack, modern JavaScript frameworks, and progressive web apps."
|
||||||
image = "img/logo.png" # relative to assetDir root
|
image = "img/logo.png" # relative to assetDir root
|
||||||
@@ -96,7 +93,7 @@ disableAliases = true
|
|||||||
weight = 4
|
weight = 4
|
||||||
|
|
||||||
[outputs]
|
[outputs]
|
||||||
home = ["HTML", "RSS", "ATOM", "MANIFEST", "REDIRECTS", "HEADERS"]
|
home = ["HTML", "RSS", "ATOM", "MANIFEST"]
|
||||||
section = ["HTML"]
|
section = ["HTML"]
|
||||||
page = ["HTML"]
|
page = ["HTML"]
|
||||||
|
|
||||||
@@ -116,24 +113,12 @@ disableAliases = true
|
|||||||
baseName = "site" # /site.webmanifest
|
baseName = "site" # /site.webmanifest
|
||||||
isPlainText = true
|
isPlainText = true
|
||||||
notAlternative = true
|
notAlternative = true
|
||||||
[outputFormats.REDIRECTS]
|
|
||||||
mediaType = "text/netlify"
|
|
||||||
baseName = "_redirects"
|
|
||||||
isPlainText = true
|
|
||||||
notAlternative = true
|
|
||||||
[outputFormats.HEADERS]
|
|
||||||
mediaType = "text/netlify"
|
|
||||||
baseName = "_headers"
|
|
||||||
isPlainText = true
|
|
||||||
notAlternative = true
|
|
||||||
|
|
||||||
[mediaTypes]
|
[mediaTypes]
|
||||||
[mediaTypes."application/atom+xml"]
|
[mediaTypes."application/atom+xml"]
|
||||||
suffixes = ["atom"]
|
suffixes = ["atom"]
|
||||||
[mediaTypes."application/manifest+json"]
|
[mediaTypes."application/manifest+json"]
|
||||||
suffixes = ["webmanifest"]
|
suffixes = ["webmanifest"]
|
||||||
[mediaTypes."text/netlify"]
|
|
||||||
delimiter = "" # no dot/extension for _headers & _redirects files
|
|
||||||
|
|
||||||
[sitemap]
|
[sitemap]
|
||||||
filename = "sitemap.xml"
|
filename = "sitemap.xml"
|
||||||
@@ -183,14 +168,3 @@ disableAliases = true
|
|||||||
writeStats = true
|
writeStats = true
|
||||||
# don't use cache for SCSS compilation, better to throw error than be stale
|
# don't use cache for SCSS compilation, better to throw error than be stale
|
||||||
useResourceCacheWhen = "never"
|
useResourceCacheWhen = "never"
|
||||||
|
|
||||||
[server]
|
|
||||||
# proxy /api requests to netlify-lambda's local server (port 9337) for each function
|
|
||||||
[[server.redirects]]
|
|
||||||
from = "/api/**"
|
|
||||||
to = "http://localhost:9337/"
|
|
||||||
status = 200
|
|
||||||
[[server.headers]]
|
|
||||||
for = "/**"
|
|
||||||
[server.headers.values]
|
|
||||||
Access-Control-Allow-Origin = "*"
|
|
||||||
|
|||||||
@@ -30,8 +30,7 @@
|
|||||||
# TECHNOLOGY
|
# TECHNOLOGY
|
||||||
|
|
||||||
Hugo
|
Hugo
|
||||||
Netlify
|
Vercel
|
||||||
GitHub Actions
|
|
||||||
...and much more: https://jarv.is/uses/
|
...and much more: https://jarv.is/uses/
|
||||||
|
|
||||||
# VIEW SOURCE
|
# VIEW SOURCE
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ This website uses a simple hit counter on each post to tally an aggregate number
|
|||||||
|
|
||||||
## Hosting
|
## Hosting
|
||||||
|
|
||||||
Pages and first-party assets on this website are served by [**Netlify**](https://www.netlify.com/). Refer to their [privacy policy](https://www.netlify.com/privacy/) and [GDPR statement](https://www.netlify.com/gdpr/) for more information.
|
Pages and first-party assets on this website are served by [**Vercel**](https://vercel.com/). Refer to their [privacy policy](https://vercel.com/legal/privacy-policy) for more information.
|
||||||
|
|
||||||
For a likely excessive level of privacy and security, this website is also mirrored on the [🧅 Tor network](https://www.torproject.org/) at: [**jarvis2i2vp4j4tbxjogsnqdemnte5xhzyi7hziiyzxwge3hzmh57zad.onion**](http://jarvis2i2vp4j4tbxjogsnqdemnte5xhzyi7hziiyzxwge3hzmh57zad.onion).
|
For a likely excessive level of privacy and security, this website is also mirrored on the [🧅 Tor network](https://www.torproject.org/) at: [**jarvis2i2vp4j4tbxjogsnqdemnte5xhzyi7hziiyzxwge3hzmh57zad.onion**](http://jarvis2i2vp4j4tbxjogsnqdemnte5xhzyi7hziiyzxwge3hzmh57zad.onion).
|
||||||
|
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ I've been making recent efforts to [de-Google](https://www.stallman.org/google.h
|
|||||||
Other geeky stuff:
|
Other geeky stuff:
|
||||||
|
|
||||||
- [**DNSimple**](https://dnsimple.com/) [(referral link)](https://dnsimple.com/r/eb6ced548f1e0a) & [**Cloudflare**](https://www.cloudflare.com/) for domain DNS.
|
- [**DNSimple**](https://dnsimple.com/) [(referral link)](https://dnsimple.com/r/eb6ced548f1e0a) & [**Cloudflare**](https://www.cloudflare.com/) for domain DNS.
|
||||||
- [**Netlify**](https://www.netlify.com/) for static sites.
|
- [**Netlify**](https://www.netlify.com/) and [**Vercel**](https://vercel.com/) for static sites.
|
||||||
- [**Linode**](https://www.linode.com/) [(referral link)](https://www.linode.com/?r=0c5aeace9bd591be9fbf32f96f58470295f1ee05) and [**DigitalOcean**](https://www.digitalocean.com/) [(referral link)](https://m.do.co/c/afcf288a7dac) for virtual Linux servers.
|
- [**Linode**](https://www.linode.com/) [(referral link)](https://www.linode.com/?r=0c5aeace9bd591be9fbf32f96f58470295f1ee05) and [**DigitalOcean**](https://www.digitalocean.com/) [(referral link)](https://m.do.co/c/afcf288a7dac) for virtual Linux servers.
|
||||||
- [**Backblaze**](https://www.backblaze.com/) [(referral link)](https://secure.backblaze.com/r/00x84e) for off-site MacBook backups.
|
- [**Backblaze**](https://www.backblaze.com/) [(referral link)](https://secure.backblaze.com/r/00x84e) for off-site MacBook backups.
|
||||||
- [**Gitea**](https://gitea.io/en-us/) as a [self-hosted](https://code.jarv.is/) Git backup/mirror.
|
- [**Gitea**](https://gitea.io/en-us/) as a [self-hosted](https://code.jarv.is/) Git backup/mirror.
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
# Cache static assets (webfonts, emojis, etc.) for a long time (1 month)
|
|
||||||
/vendor/*
|
|
||||||
Cache-Control: max-age=2628000
|
|
||||||
|
|
||||||
# Recommended MIME type for PWA manifests:
|
|
||||||
# https://github.com/w3c/manifest/issues/689
|
|
||||||
/site.webmanifest
|
|
||||||
Content-Type: application/manifest+json
|
|
||||||
|
|
||||||
# Set matching Onion-Location headers for each permalink
|
|
||||||
{{- range $page := .Site.Pages }}
|
|
||||||
{{- range .AlternativeOutputFormats }}
|
|
||||||
{{ .RelPermalink }}
|
|
||||||
Onion-Location: {{ $.Site.Params.baseOnionURL }}{{ .RelPermalink }}
|
|
||||||
{{ end -}}
|
|
||||||
{{ end -}}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
/index.php* / 301
|
|
||||||
/feed /feed.xml 301
|
|
||||||
/rss /feed.xml 301
|
|
||||||
/index.xml /feed.xml 301
|
|
||||||
|
|
||||||
{{- with .Site.Params.social.webmentionIO }}
|
|
||||||
/xmlrpc.php https://webmention.io/{{ . }}/xmlrpc 302
|
|
||||||
{{ end -}}
|
|
||||||
|
|
||||||
/favicon.ico /img/favicon.ico 200
|
|
||||||
/favicon-* /img/favicon-:splat 200
|
|
||||||
/apple-touch-icon.png /img/apple-touch-icon.png 200
|
|
||||||
/apple-touch-icon-precomposed.png /img/apple-touch-icon.png 200
|
|
||||||
/safari-pinned-tab.svg /img/safari-pinned-tab.svg 200
|
|
||||||
|
|
||||||
# Hugo aliases: prefer HTTP 301 redirects over meta tags
|
|
||||||
{{- range $page := .Site.Pages }}
|
|
||||||
{{- range .Aliases }}
|
|
||||||
{{ . }} {{ $page.RelPermalink }} 301
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
# Redirect old AMP URLs to the normal HTML page
|
|
||||||
{{- range $page := .Site.Pages }}
|
|
||||||
{{ print .RelPermalink "amp.html" }} {{ .RelPermalink }} 301!
|
|
||||||
{{ end -}}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
{{ if .Site.Params.social.webmentionIO }}
|
{{ with .Site.Params.social.webmentionIO }}
|
||||||
<link rel="pingback" href="{{ "api/ping" | absURL }}">
|
<link rel="webmention" href="https://webmention.io/{{ . }}/webmention">
|
||||||
<link rel="webmention" href="{{ "api/mention" | absURL }}">
|
<link rel="pingback" href="https://webmention.io/{{ . }}/xmlrpc">
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|||||||
253
netlify.toml
253
netlify.toml
@@ -1,253 +0,0 @@
|
|||||||
[build]
|
|
||||||
command = "yarn build"
|
|
||||||
publish = "public"
|
|
||||||
functions = ".netlify/functions"
|
|
||||||
|
|
||||||
[build.environment]
|
|
||||||
NODE_VERSION = "16"
|
|
||||||
YARN_VERSION = "1.22.10"
|
|
||||||
YARN_FLAGS = "--no-ignore-optional --frozen-lockfile"
|
|
||||||
|
|
||||||
# Ensure *only* Pretty URLs are enabled, even though this is already set up in
|
|
||||||
# the Netlify dashboard.
|
|
||||||
[build.processing]
|
|
||||||
skip_processing = false
|
|
||||||
[build.processing.css]
|
|
||||||
bundle = false
|
|
||||||
minify = false
|
|
||||||
[build.processing.js]
|
|
||||||
bundle = false
|
|
||||||
minify = false
|
|
||||||
[build.processing.html]
|
|
||||||
pretty_urls = true
|
|
||||||
[build.processing.images]
|
|
||||||
compress = false
|
|
||||||
|
|
||||||
[context.deploy-preview]
|
|
||||||
command = "yarn build:functions && yarn build:hugo --environment development --baseURL $DEPLOY_PRIME_URL --buildDrafts --buildFuture"
|
|
||||||
|
|
||||||
[context.branch-deploy]
|
|
||||||
command = "yarn build:functions && yarn build:hugo --environment development --baseURL $DEPLOY_PRIME_URL --buildDrafts --buildFuture"
|
|
||||||
|
|
||||||
# https://github.com/netlify/cli/blob/master/docs/netlify-dev.md#netlifytoml-dev-block
|
|
||||||
[dev]
|
|
||||||
framework = "#custom"
|
|
||||||
# only start Hugo, `netlify dev` builds/serves functions itself
|
|
||||||
command = "yarn start:hugo --port=1338 --baseURL=/ --appendPort=false --disableLiveReload"
|
|
||||||
# swap ports to keep consistent w/ normal local server
|
|
||||||
targetPort = 1338
|
|
||||||
port = 1337
|
|
||||||
# don't launch browser automatically
|
|
||||||
autoLaunch = false
|
|
||||||
|
|
||||||
# Enable local Netlify build plugins:
|
|
||||||
[[plugins]]
|
|
||||||
package = "@netlify/plugin-local-install-core"
|
|
||||||
# Cache resoures between builds:
|
|
||||||
# https://github.com/jakejarvis/netlify-plugin-cache
|
|
||||||
[[plugins]]
|
|
||||||
package = "netlify-plugin-cache"
|
|
||||||
[plugins.inputs]
|
|
||||||
paths = ["public", "builds", "_vendor"]
|
|
||||||
# List cached resources for debugging:
|
|
||||||
# [[plugins]]
|
|
||||||
# package = "netlify-plugin-debug-cache"
|
|
||||||
|
|
||||||
# The most important headers and redirects are specified in the _headers and
|
|
||||||
# _redirects files generated by Hugo. These are additional custom rules, mostly
|
|
||||||
# unrelated to the actual website.
|
|
||||||
|
|
||||||
# Global security headers:
|
|
||||||
[[headers]]
|
|
||||||
for = "/*"
|
|
||||||
[headers.values]
|
|
||||||
Content-Security-Policy = '''
|
|
||||||
default-src 'self';
|
|
||||||
base-uri 'none';
|
|
||||||
connect-src 'self' api.github.com platform.twitter.com;
|
|
||||||
font-src 'self';
|
|
||||||
form-action 'none';
|
|
||||||
frame-ancestors 'self';
|
|
||||||
frame-src 'self' jakejarvis.github.io buttons.github.io codepen.io cdpn.io platform.twitter.com www.youtube-nocookie.com;
|
|
||||||
img-src 'self' data: https:;
|
|
||||||
manifest-src 'self';
|
|
||||||
media-src 'self' data: https:;
|
|
||||||
object-src 'none';
|
|
||||||
script-src 'self' buttons.github.io gist.github.com syndication.twitter.com platform.twitter.com 'sha256-1j1MKfE70TTCp5KmiC2YImxw2RMS52uCH5yXl1heG9U=' 'sha256-y3Xr/40/KQnUvqk/kZO5us6t3i/I49BsbYjsH8ELhVg=' 'sha256-JGG0npUp+0ABq/NY1azjpQ0WBtm+m5gU58mzF+2DCXY=';
|
|
||||||
style-src 'self' 'unsafe-inline' github.githubassets.com;
|
|
||||||
worker-src 'self';
|
|
||||||
block-all-mixed-content;
|
|
||||||
report-uri https://jarv.is/api/csp_wizard;
|
|
||||||
report-to default'''
|
|
||||||
NEL = '''
|
|
||||||
{"report_to":"default","max_age":604800}'''
|
|
||||||
Report-To = '''
|
|
||||||
{"group":"default","max_age":604800,"endpoints":[{"url":"https://jarv.is/api/report"}],"include_subdomains":false}'''
|
|
||||||
# More generic security headers:
|
|
||||||
Feature-Policy = "accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; usb 'none'"
|
|
||||||
Permissions-Policy = "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=(), interest-cohort=()"
|
|
||||||
Referrer-Policy = "no-referrer-when-downgrade"
|
|
||||||
X-Content-Type-Options = "nosniff"
|
|
||||||
X-Frame-Options = "SAMEORIGIN"
|
|
||||||
X-XSS-Protection = "1; mode=block"
|
|
||||||
X-Got-Milk = "2%"
|
|
||||||
X-View-Source = "https://github.com/jakejarvis/jarv.is"
|
|
||||||
# PGP key: open in browser, download correctly
|
|
||||||
[[headers]]
|
|
||||||
for = "/pubkey.asc"
|
|
||||||
[headers.values]
|
|
||||||
Cache-Control = "no-cache"
|
|
||||||
Content-Type = "text/plain; charset=UTF-8"
|
|
||||||
Content-Disposition = "inline; filename=\"pubkey.asc\""
|
|
||||||
|
|
||||||
# Redirect Netlify and www subdomains to primary domain:
|
|
||||||
[[redirects]]
|
|
||||||
from = "https://jakejarvis.netlify.com/*"
|
|
||||||
to = "https://jarv.is/:splat"
|
|
||||||
status = 301
|
|
||||||
force = true
|
|
||||||
[[redirects]]
|
|
||||||
from = "https://jakejarvis.netlify.app/*"
|
|
||||||
to = "https://jarv.is/:splat"
|
|
||||||
status = 301
|
|
||||||
force = true
|
|
||||||
[[redirects]]
|
|
||||||
from = "https://www.jarv.is/*"
|
|
||||||
to = "https://jarv.is/:splat"
|
|
||||||
status = 301
|
|
||||||
force = true
|
|
||||||
|
|
||||||
# External API redirects/mirrors:
|
|
||||||
# Must set `force = true` and wildcard /api/* rule goes last.
|
|
||||||
## Report URI endpoints
|
|
||||||
[[redirects]]
|
|
||||||
from = "/api/report"
|
|
||||||
to = "https://jarvis.report-uri.com/a/d/g"
|
|
||||||
status = 200
|
|
||||||
force = true
|
|
||||||
[[redirects]]
|
|
||||||
from = "/api/csp_wizard"
|
|
||||||
to = "https://jarvis.report-uri.com/r/d/csp/enforce"
|
|
||||||
status = 200
|
|
||||||
force = true
|
|
||||||
## Webmention.io endpoints
|
|
||||||
[[redirects]]
|
|
||||||
from = "/api/mention"
|
|
||||||
to = "https://webmention.io/jarv.is/webmention"
|
|
||||||
status = 200
|
|
||||||
force = true
|
|
||||||
[[redirects]]
|
|
||||||
from = "/api/ping"
|
|
||||||
to = "https://webmention.io/jarv.is/xmlrpc"
|
|
||||||
status = 200
|
|
||||||
force = true
|
|
||||||
## Prettier URLs for Netlify Functions
|
|
||||||
[[redirects]]
|
|
||||||
from = "/api/*"
|
|
||||||
to = "/.netlify/functions/:splat"
|
|
||||||
status = 200
|
|
||||||
|
|
||||||
# More miscellaneous mirrors/redirects:
|
|
||||||
[[redirects]]
|
|
||||||
from = "/blog/*"
|
|
||||||
to = "/notes/"
|
|
||||||
status = 301
|
|
||||||
[[redirects]]
|
|
||||||
from = "/archives/*"
|
|
||||||
to = "/notes/"
|
|
||||||
status = 301
|
|
||||||
[[redirects]]
|
|
||||||
from = "/resume"
|
|
||||||
to = "/resume.pdf"
|
|
||||||
status = 302
|
|
||||||
|
|
||||||
# Fix some 404s after moving files around somewhat recklessly:
|
|
||||||
[[redirects]]
|
|
||||||
from = "/keybase.txt"
|
|
||||||
to = "/.well-known/keybase.txt"
|
|
||||||
status = 301
|
|
||||||
[[redirects]]
|
|
||||||
from = "/jarvis.asc"
|
|
||||||
to = "/pubkey.asc"
|
|
||||||
status = 301
|
|
||||||
[[redirects]]
|
|
||||||
from = "/img/logo.svg"
|
|
||||||
to = "/img/favicon.svg"
|
|
||||||
status = 302
|
|
||||||
[[redirects]]
|
|
||||||
from = "/img/me_large.jpg"
|
|
||||||
to = "/img/me.jpg"
|
|
||||||
status = 301
|
|
||||||
[[redirects]]
|
|
||||||
from = "/me.jpg"
|
|
||||||
to = "/img/me.jpg"
|
|
||||||
status = 301
|
|
||||||
[[redirects]]
|
|
||||||
from = "/me_large.jpg"
|
|
||||||
to = "/img/me.jpg"
|
|
||||||
status = 301
|
|
||||||
[[redirects]]
|
|
||||||
from = "/img/me_hu1c1a997e30e234e83718deb8b3f52283_130509_320x320_resize_q90_lanczos.jpg"
|
|
||||||
to = "/img/me.jpg"
|
|
||||||
status = 301
|
|
||||||
[[redirects]]
|
|
||||||
from = "/twemoji/svg/*"
|
|
||||||
to = "/vendor/emoji/svg/:splat"
|
|
||||||
status = 301
|
|
||||||
[[redirects]]
|
|
||||||
from = "/vendor/inter/*"
|
|
||||||
to = "/vendor/fonts/:splat"
|
|
||||||
status = 301
|
|
||||||
|
|
||||||
# Moved these random sites/projects elsewhere (mostly GitHub Pages) to keep
|
|
||||||
# this repo and domain squeaky clean:
|
|
||||||
[[redirects]]
|
|
||||||
from = "/y2k/*"
|
|
||||||
to = "https://jakejarvis.github.io/my-first-website/:splat"
|
|
||||||
status = 302
|
|
||||||
[[redirects]]
|
|
||||||
from = "/ios-trackers/*"
|
|
||||||
to = "https://jakejarvis.github.io/ios-trackers/:splat"
|
|
||||||
status = 302
|
|
||||||
[[redirects]]
|
|
||||||
from = "/awesome/*"
|
|
||||||
to = "https://synonymsforawesome.com/"
|
|
||||||
status = 302
|
|
||||||
[[redirects]]
|
|
||||||
from = "/hugo-node/*"
|
|
||||||
to = "https://github.com/jakejarvis/hugo-extended"
|
|
||||||
status = 302
|
|
||||||
[[redirects]]
|
|
||||||
from = "/comp20/*"
|
|
||||||
to = "https://jakejarvis.github.io/comp20/:splat"
|
|
||||||
status = 302
|
|
||||||
[[redirects]]
|
|
||||||
from = "/scrabble/*"
|
|
||||||
to = "https://jakejarvis.github.io/scrabble/:splat"
|
|
||||||
status = 302
|
|
||||||
|
|
||||||
# H A C K E R M A N ( ͡° ͜ʖ ͡°)
|
|
||||||
[[redirects]]
|
|
||||||
from = "*/wp-admin/*"
|
|
||||||
to = "/403.html"
|
|
||||||
status = 403
|
|
||||||
[[redirects]]
|
|
||||||
from = "*/admin/*"
|
|
||||||
to = "/403.html"
|
|
||||||
status = 403
|
|
||||||
[[redirects]]
|
|
||||||
from = "*/wp-login.php"
|
|
||||||
to = "/403.html"
|
|
||||||
status = 403
|
|
||||||
[[redirects]]
|
|
||||||
from = "*/login.php"
|
|
||||||
to = "/403.html"
|
|
||||||
status = 403
|
|
||||||
[[redirects]]
|
|
||||||
from = "*/wlwmanifest.xml"
|
|
||||||
to = "/403.html"
|
|
||||||
status = 403
|
|
||||||
[[redirects]]
|
|
||||||
from = "*/.git/*"
|
|
||||||
to = "/403.html"
|
|
||||||
status = 403
|
|
||||||
14
package.json
14
package.json
@@ -14,13 +14,10 @@
|
|||||||
"url": "git+https://github.com/jakejarvis/jarv.is.git"
|
"url": "git+https://github.com/jakejarvis/jarv.is.git"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rimraf public/ resources/ builds/ _vendor/ .netlify/{cache,functions}/ $TMPDIR/hugo_cache/ hugo_stats.json",
|
"clean": "rimraf public/ resources/ builds/ _vendor/ .vercel/cache/ $TMPDIR/hugo_cache/ hugo_stats.json",
|
||||||
"start": "run-p start:**",
|
"start": "hugo server --buildDrafts --buildFuture --port=${PORT:-1337} --baseURL=/ --appendPort=false --bind=0.0.0.0 --verbose",
|
||||||
"start:hugo": "hugo server --disableFastRender --buildDrafts --buildFuture --port=1337 --baseURL=/ --appendPort=false --bind=0.0.0.0 --verbose",
|
|
||||||
"start:functions": "netlify-lambda serve --port 9337 functions",
|
|
||||||
"build": "run-s build:** minify:**",
|
"build": "run-s build:** minify:**",
|
||||||
"build:hugo": "hugo --gc --cleanDestinationDir --verbose",
|
"build:hugo": "hugo --gc --cleanDestinationDir --verbose",
|
||||||
"build:functions": "netlify-lambda build functions",
|
|
||||||
"minify:html": "html-minifier --html5 --collapse-whitespace --collapse-boolean-attributes --preserve-line-breaks --minify-css --remove-comments --file-ext html --input-dir public --output-dir public **/*.html",
|
"minify:html": "html-minifier --html5 --collapse-whitespace --collapse-boolean-attributes --preserve-line-breaks --minify-css --remove-comments --file-ext html --input-dir public --output-dir public **/*.html",
|
||||||
"minify:js": "terser --compress passes=3,negate_iife=false,keep_fargs=false,sequences=false,reduce_vars=false --mangle reserved=['sa','sa_event'] --output public/js/app.js -- public/js/app.js",
|
"minify:js": "terser --compress passes=3,negate_iife=false,keep_fargs=false,sequences=false,reduce_vars=false --mangle reserved=['sa','sa_event'] --output public/js/app.js -- public/js/app.js",
|
||||||
"minify:img": "glob-exec --parallel --foreach 'public/**/{img,images}/' -- imagemin '{{file.path}}*' --plugin=mozjpeg --plugin.mozjpeg.progressive --plugin.mozjpeg.quality=85 --plugin=pngquant --plugin.pngquant.quality={0.1,0.3} --plugin.pngquant.speed=1 --plugin.pngquant.strip --plugin=gifsicle --plugin=svgo --out-dir='{{file.path}}'",
|
"minify:img": "glob-exec --parallel --foreach 'public/**/{img,images}/' -- imagemin '{{file.path}}*' --plugin=mozjpeg --plugin.mozjpeg.progressive --plugin.mozjpeg.quality=85 --plugin=pngquant --plugin.pngquant.quality={0.1,0.3} --plugin.pngquant.speed=1 --plugin.pngquant.strip --plugin=gifsicle --plugin=svgo --out-dir='{{file.path}}'",
|
||||||
@@ -37,7 +34,6 @@
|
|||||||
"@fontsource/inter": "4.4.2",
|
"@fontsource/inter": "4.4.2",
|
||||||
"@fontsource/roboto-mono": "4.4.2",
|
"@fontsource/roboto-mono": "4.4.2",
|
||||||
"dotenv": "^10.0.0",
|
"dotenv": "^10.0.0",
|
||||||
"encoding": "^0.1.13",
|
|
||||||
"faunadb": "fauna/faunadb-js#master",
|
"faunadb": "fauna/faunadb-js#master",
|
||||||
"graphql": "^15.5.0",
|
"graphql": "^15.5.0",
|
||||||
"graphql-request": "^3.4.0",
|
"graphql-request": "^3.4.0",
|
||||||
@@ -63,8 +59,6 @@
|
|||||||
"imagemin-cli": "^6.0.0",
|
"imagemin-cli": "^6.0.0",
|
||||||
"lint-staged": "^11.0.0",
|
"lint-staged": "^11.0.0",
|
||||||
"markdownlint-cli": "~0.27.1",
|
"markdownlint-cli": "~0.27.1",
|
||||||
"netlify-lambda": "^2.0.8",
|
|
||||||
"netlify-plugin-cache": "^1.0.3",
|
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"postcss": "^8.3.0",
|
"postcss": "^8.3.0",
|
||||||
"postcss-clean": "jakejarvis/postcss-clean#master",
|
"postcss-clean": "jakejarvis/postcss-clean#master",
|
||||||
@@ -93,10 +87,6 @@
|
|||||||
"imagemin-pngquant": "^9.0.2",
|
"imagemin-pngquant": "^9.0.2",
|
||||||
"imagemin-svgo": "^9.0.0"
|
"imagemin-svgo": "^9.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
|
||||||
"node": "^10 || ^12 || >=14",
|
|
||||||
"yarn": "^1.22.4"
|
|
||||||
},
|
|
||||||
"simple-git-hooks": {
|
"simple-git-hooks": {
|
||||||
"pre-commit": "npx lint-staged"
|
"pre-commit": "npx lint-staged"
|
||||||
},
|
},
|
||||||
|
|||||||
110
vercel.json
Normal file
110
vercel.json
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
{
|
||||||
|
"public": false,
|
||||||
|
"trailingSlash": true,
|
||||||
|
"rewrites": [
|
||||||
|
{ "source": "/favicon.ico", "destination": "/img/favicon.ico" },
|
||||||
|
{ "source": "/favicon-(.*)", "destination": "/img/favicon-$1xxxxxxxx" },
|
||||||
|
{ "source": "/apple-touch-icon.png", "destination": "/img/apple-touch-icon.png" },
|
||||||
|
{ "source": "/apple-touch-icon-precomposed.png", "destination": "/img/apple-touch-icon.png" },
|
||||||
|
{ "source": "/safari-pinned-tab.svg", "destination": "/img/safari-pinned-tab.svg" }
|
||||||
|
],
|
||||||
|
"redirects": [
|
||||||
|
{ "source": "/notes/:slug/amp.html", "destination": "/notes/:slug/", "statusCode": 301 },
|
||||||
|
{ "source": "/blog/(.*)", "destination": "/notes/" },
|
||||||
|
{ "source": "/archives/(.*)", "destination": "/notes/" },
|
||||||
|
{ "source": "/feed", "destination": "/feed.xml" },
|
||||||
|
{ "source": "/rss", "destination": "/feed.xml" },
|
||||||
|
{ "source": "/index.xml", "destination": "/feed.xml" },
|
||||||
|
{ "source": "/resume/", "destination": "/resume.pdf" },
|
||||||
|
{ "source": "/keybase.txt", "destination": "/.well-known/keybase.txt" },
|
||||||
|
{ "source": "/jarvis.asc", "destination": "/pubkey.asc" },
|
||||||
|
{ "source": "/img/logo.svg", "destination": "/img/favicon.svg" },
|
||||||
|
{ "source": "/img/me_large.jpg", "destination": "/img/me.jpg" },
|
||||||
|
{ "source": "/me.jpg", "destination": "/img/me.jpg" },
|
||||||
|
{ "source": "/me_large.jpg", "destination": "/img/me.jpg" },
|
||||||
|
{ "source": "/img/me_hu1c1a997e30e234e83718deb8b3f52283_130509_320x320_resize_q90_lanczos.jpg", "destination": "/img/me.jpg" },
|
||||||
|
{ "source": "/y2k/(.*)", "destination": "https://jakejarvis.github.io/my-first-website/$1" },
|
||||||
|
{ "source": "/ios-trackers/(.*)", "destination": "https://jakejarvis.github.io/ios-trackers/$1" },
|
||||||
|
{ "source": "/awesome/", "destination": "https://synonymsforawesome.com/" },
|
||||||
|
{ "source": "/hugo-node/", "destination": "https://github.com/jakejarvis/hugo-extended" },
|
||||||
|
{ "source": "/comp20/(.*)", "destination": "https://jakejarvis.github.io/comp20/$1" },
|
||||||
|
{ "source": "/scrabble/(.*)", "destination": "https://jakejarvis.github.io/scrabble/$1" }
|
||||||
|
],
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"source": "/vendor/(.*)",
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"key": "Cache-Control",
|
||||||
|
"value": "public, max-age=2628000"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "/pubkey.asc",
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"key": "Cache-Control",
|
||||||
|
"value": "private, no-cache, no-store, must-revalidate"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "text/plain; charset=utf-8"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "/(.*)",
|
||||||
|
"headers" : [
|
||||||
|
{
|
||||||
|
"key": "Onion-Location",
|
||||||
|
"value": "http://jarvis2i2vp4j4tbxjogsnqdemnte5xhzyi7hziiyzxwge3hzmh57zad.onion/$1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Content-Security-Policy",
|
||||||
|
"value": "default-src 'self'; base-uri 'none'; connect-src 'self' api.github.com platform.twitter.com; font-src 'self'; form-action 'none'; frame-ancestors 'self'; frame-src 'self' jakejarvis.github.io buttons.github.io codepen.io cdpn.io platform.twitter.com www.youtube-nocookie.com; img-src 'self' data: https:; manifest-src 'self'; media-src 'self' data: https:; object-src 'none'; script-src 'self' buttons.github.io gist.github.com syndication.twitter.com platform.twitter.com 'sha256-1j1MKfE70TTCp5KmiC2YImxw2RMS52uCH5yXl1heG9U=' 'sha256-y3Xr/40/KQnUvqk/kZO5us6t3i/I49BsbYjsH8ELhVg=' 'sha256-JGG0npUp+0ABq/NY1azjpQ0WBtm+m5gU58mzF+2DCXY='; style-src 'self' 'unsafe-inline' github.githubassets.com; worker-src 'self'; block-all-mixed-content; report-uri https://jarvis.report-uri.com/r/d/csp/enforce; report-to default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Report-To",
|
||||||
|
"value": "{\"group\":\"default\",\"max_age\":604800,\"endpoints\":[{\"url\":\"https://jarvis.report-uri.com/a/d/g\"}],\"include_subdomains\":false}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "NEL",
|
||||||
|
"value": "{\"report_to\":\"default\",\"max_age\":604800}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Feature-Policy",
|
||||||
|
"value": "accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; usb 'none'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Permissions-Policy",
|
||||||
|
"value": "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=(), interest-cohort=()"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Referrer-Policy",
|
||||||
|
"value": "no-referrer-when-downgrade"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "X-Content-Type-Options",
|
||||||
|
"value": "nosniff"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "X-Frame-Options",
|
||||||
|
"value": "SAMEORIGIN"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "X-XSS-Protection",
|
||||||
|
"value": "1; mode=block"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "x-view-source",
|
||||||
|
"value": "https://github.com/jakejarvis/jarv.is"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "x-got-milk",
|
||||||
|
"value" : "2%"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user