#!/usr/bin/env bash set -euo pipefail ############################################################################### # DCREATE — dmenu content creator for krisyotam.com # # Maintainer: Kris Yotam # License: MIT # Created: 2026-02-15 # Updated: 2026-02-26 # Description: Create new content entries via dmenu. Collects title + preview, # auto-generates slug, validates uniqueness against ~/content/, # then spawns Claude in st terminal to determine metadata and # write a YAML-frontmatter .mdx file. ############################################################################### CONTENT_DIR="$HOME/content" declare -A TYPE_ICONS=( [papers]="󰈙" [blog]="󰬞" [essays]="󰬝" [notes]="󰏪" [diary]="󰃮" [progymnasmata]="󰑴" [reviews]="󰓥" [fiction]="󰗊" [verse]="󰊈" [news]="󰎕" [ocs]="󰚥" ) ALL_TYPES=(blog diary essays fiction news notes ocs papers progymnasmata reviews verse) notify() { notify-send "dcreate" "$1" 2>/dev/null || true; } slugify() { echo "$1" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9 -]//g' | sed 's/ */ /g; s/ /-/g; s/--*/-/g; s/^-//; s/-$//' } # Check if slug.mdx already exists in any content subdirectory check_slug_globally() { local slug="$1" for dir in "$CONTENT_DIR"/*/; do [ -d "$dir" ] || continue if [ -f "$dir/${slug}.mdx" ]; then echo "$(basename "$dir"):${slug}.mdx" return fi done } # Select type type_menu() { local entries="" for t in "${ALL_TYPES[@]}"; do entries+="${TYPE_ICONS[$t]:-󰈙} $t"$'\n' done echo "$entries" | dmenu -i -l 12 -p "create:" | awk '{print $2}' } # Main type="$(type_menu)" [[ -z "$type" ]] && exit 0 # Get title title="$(echo "" | dmenu -p "title:")" [[ -z "$title" ]] && exit 0 # Generate and validate slug slug="$(slugify "$title")" collision="$(check_slug_globally "$slug")" if [[ -n "$collision" ]]; then notify "Slug collision: $slug ($collision)" slug="$(echo "$slug" | dmenu -p "collision! alt slug:")" [[ -z "$slug" ]] && exit 0 slug="$(slugify "$slug")" collision="$(check_slug_globally "$slug")" if [[ -n "$collision" ]]; then notify "Still colliding: $slug. Aborting." exit 1 fi fi # Get preview preview="$(echo "" | dmenu -p "preview:")" # Type-specific extra fields extra_prompt="" if [[ "$type" == "verse" ]]; then verse_type="$(printf 'haiku\nsonnet\nfree-verse\node\nlimerick\nvillanelle\nother' | dmenu -i -l 7 -p "verse type:")" [[ -n "$verse_type" ]] && extra_prompt="verse_type: $verse_type" fi # Ensure target directory exists target_dir="$CONTENT_DIR/$type" mkdir -p "$target_dir" date="$(date +%Y-%m-%d)" target_file="$target_dir/${slug}.mdx" # Build Claude instruction instruction="You are creating a new $type entry as a YAML-frontmatter .mdx file. === USER INPUT === Type: $type Title: $title Preview: ${preview:-"(none)"} Slug: $slug Date: $date ${extra_prompt:+Extra: $extra_prompt} === TARGET FILE === $target_file === YAML FORMAT === The file MUST use this exact YAML frontmatter structure: --- title: $title slug: $slug type: $type category: start_date: '$date' end_date: '' state: active preview: ${preview:-""} status: Draft confidence: importance: <1-10> tags: - - - --- Content goes here... === YOUR TASK === 1. ANALYZE the title and preview to determine: category, tags, confidence, importance. 2. WRITE the .mdx file to: $target_file 3. Use the Write tool to create the file with proper YAML frontmatter. 4. VERIFY the file was created. Execute this now without asking for confirmation." # Spawn Claude in st terminal notify "Creating: $title ($slug)" st -e bash -c "claude -p '$(echo "$instruction" | sed "s/'/'\\\\''/g")'; echo; echo 'Press Enter to close...'; read" & disown