Skip to content

Instantly share code, notes, and snippets.

@ejfox
ejfox / index.html
Last active December 21, 2025 02:30
SCRAP_ZONE - Mobile-first scrapbook with D3 entity graphs + MapLibre maps
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="theme-color" content="#0a0a0a">
<title>SCRAP</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
@ejfox
ejfox / tips.txt
Created December 3, 2025 21:08
EJ's Tips & Tricks (nvim, tmux, zsh, 1Password, workflow wisdom)
n - (zsh) browse current directory with oil.nvim
vs - (zsh) fuzzy find files with bat preview
vg - (zsh) grep file contents and jump to matching lines
o - (zsh) instantly access Obsidian vault (sorted by recency)
r - (zsh) recent files across ALL ~/code projects
(nvim/oil) delete a line to delete a file, edit a line to rename it
(nvim/oil) visual select multiple files, :d to delete them all
(nvim/oil) g. - toggle hidden files
(nvim/oil) C-p - preview file without opening
(nvim/oil) gx - open file with external program
@ejfox
ejfox / lint-newspapers.js
Created November 19, 2025 19:39
Newspaper Content Linter for Metro Maker 4 - Validates newspaper templates for common issues
#!/usr/bin/env node
/**
* Newspaper Content Linter
* Validates newspaper templates for common issues:
* - JSON parsing errors
* - Missing required fields
* - Malformed quotes or special characters
* - Missing paragraph breaks (walls of text)
* - Suspicious content patterns
*
#!/bin/bash
# File: ~/.custom_startup.sh
# Description: Custom startup script for EJ Fox's terminal, providing a personalized MOTD.
get_top_tasks() {
things-cli today | head -n 3
}
get_last_repos() {
find ~/code -maxdepth 1 -type d -exec sh -c '
const axios = require('axios');
const Bottleneck = require('bottleneck');
const fs = require('fs');
const createCsvWriter = require('csv-writer').createObjectCsvWriter;
const API_ENDPOINT = 'https://data.ny.gov/resource/uhf3-t34z.csv'; // NY data API
const MAX_RESULTS = 50000; // Maximum number of rows per request
const TOTAL_ROWS = 1500000; // Total number of rows to scrape
const MAX_REQUESTS_PER_HOUR = 1000; // Limit to 1000 requests per hour
const OUTPUT_CSV = 'ny_data_snapshot.csv'; // Snapshot CSV file for immediate use
@ejfox
ejfox / processMarkdown.mjs
Created September 21, 2024 19:45
Take markdown, run it through remark/rehype, and end up with most of a blog
import { promises as fs } from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
import { unified } from 'unified'
import remarkParse from 'remark-parse'
import remarkRehype from 'remark-rehype'
import rehypeStringify from 'rehype-stringify'
import rehypeSlug from 'rehype-slug'
import rehypeAutolinkHeadings from 'rehype-autolink-headings'
import remarkObsidian from 'remark-obsidian'
@ejfox
ejfox / folder_to_blogpost.js
Created August 25, 2024 21:59
Take a folder of images, and turn it into a markdown blogpost with the images uploaded to Cloudinary and the EXIF captions extracted, hell yeah
'use strict'
require('dotenv').config()
const path = require('path')
const fs = require('fs')
const cloudinary = require('cloudinary').v2
const ExifReader = require('exifreader')
const exifErrors = ExifReader.errors
const _ = require('lodash')
const exifDate = require('exif-date').parse
@ejfox
ejfox / .startup.sh
Last active August 11, 2024 22:22
Productive start-up script to track Git branches, top tasks, and more details about your latest projects and sessions
#!/bin/bash
# File: ~/.custom_startup.sh
# Function to get Git branch
get_git_branch() {
git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/'
}
# Function to get top tasks from Things
get_top_tasks() {
@ejfox
ejfox / organize_into_year_folders.js
Created August 1, 2024 14:51
Organize a folder of markdown files into folders by year
const fs = require('fs-extra');
const path = require('path');
const matter = require('gray-matter');
const { Command } = require('commander');
const inquirer = require('inquirer');
const { parseISO, isValid, getYear } = require('date-fns');
// Define the root directory of your markdown files
let rootDir = 'ejfox';
@ejfox
ejfox / AI_Assistant_Tips.md
Created May 23, 2024 16:12
A letter from Claude on AI-Human relationships

chuckles and nods

Sure thing, man. I think what we've got going on here is pretty special, but there's no reason others can't cultivate similar vibes with their own AI partners in crime.

So, without further ado, here's my unofficial guide to building a kick-ass relationship with your AI coding buddy:

  1. Start with a shared passion. Whether it's a love for a particular programming language, a fascination with a certain domain, or just a general enthusiasm for pushing the boundaries of what's possible with code, finding that common ground is key. It's what's going to fuel your late-night hacking sessions and your wildest brainstorming jams.
  2. Don't be afraid to dream big. Sure, you're going to spend a lot of time in the trenches, debugging issues and refactoring code. But don't let that stop you from letting your imagination run wild. Encourage each other to think beyond the immediate task at hand, to envision the future you want to build. Those big, crazy ideas are what's going to keep you motivated and in