site: editorial tooling, grid masonry fix, new reviews + finds

UI / dev tooling
- /find/ index: sort by file birthtime desc (sub-day chronology even when
  many finds share the same frontmatter date); render the captured-at on
  its own line under the host (~0.65rem mono muted)
- New dev-only filter at the top of /find/: All / Not in lists, persisted
  in localStorage; "not in lists" hides finds referenced by any superpost
- New editorial-tags chip strip on each find card (dev-only): selected
  tags visible by default, full picker on hover/focus-within with a "…"
  button for arbitrary tag entry; clicks copy /edit-find-tag <slug> <tag>
  to the clipboard via the existing EditConfirm singleton
- New optional editorialTags: string[] field on the find collection
- New src/data/editorial-tags.json — master list of available tags (initial
  set: ["delete"]); display order follows file order

/grid/ now uses the JS Masonry component instead of CSS column-count, so
the middle column no longer "dips"; tile hover updated to match the home
page's accent-glow / no-translate style

Content
- New review: apex-markdown-processor (graduated from find of same slug;
  hero reused from the find folder)
- New review: sindre-sorhus-older-mac-apps (graduated; intentionally
  hero-less per the source page's text-only design)
- New review: superkey (added by user; hero wired in src/lib/hero.ts)
- 24 new finds captured by /daily-finds across travel, jokes, quotes,
  product picks, and indie tools
- 2 new finds superposts: 2026-05-04-a-small-atlas, 2026-05-04-off-until-needed

Misc
- daily-finds.log.md and candidate-sources.md updated with the day's runs
- build-finds skill prompt iterated by user
This commit is contained in:
2026-05-04 18:57:04 -04:00
parent 1ecdc10443
commit 7e1b200bea
59 changed files with 927 additions and 75 deletions
+11
View File
@@ -102,6 +102,17 @@
}.`;
}
if (btn.dataset.editAction === 'tag-prompt') {
const slug = btn.dataset.slug || '';
const name = btn.dataset.name || slug;
const raw = window.prompt(`Custom tag for "${name}":`);
if (!raw) return;
const tag = raw.trim().toLowerCase().replace(/\s+/g, '-');
if (!tag) return;
command = `/edit-find-tag ${slug} ${tag}`;
description = `Tag "${name}" with "${tag}".`;
}
openModal({ command, description });
});
</script>
+141 -2
View File
@@ -6,9 +6,22 @@ import SourceBadge from './SourceBadge.astro';
interface Props {
item: FindItem;
inList?: boolean;
capturedAt?: Date;
availableTags?: string[];
}
const { item } = Astro.props;
const { item, inList, capturedAt, availableTags = [] } = Astro.props;
const hero = findHero(item.id);
const showInListAttr = import.meta.env.DEV && inList !== undefined;
const selectedTags: string[] = item.data.editorialTags ?? [];
const selectedSet = new Set(selectedTags);
const fmtCaptured = new Intl.DateTimeFormat('en-US', {
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: '2-digit',
});
function host(url: string) {
try {
@@ -19,7 +32,10 @@ function host(url: string) {
}
---
<article class:list={['find-card', { 'has-hero': !!hero }]}>
<article
class:list={['find-card', { 'has-hero': !!hero }]}
data-in-list={showInListAttr ? String(inList) : undefined}
>
{import.meta.env.DEV && (
<label class="edit-checkbox" aria-label={`Select ${item.data.name}`}>
<input type="checkbox" data-find-checkbox data-slug={item.id} />
@@ -46,6 +62,54 @@ function host(url: string) {
<span class="ext-label">→</span>
<span class="host">{host(item.data.link)}</span>
</p>
{capturedAt && capturedAt.valueOf() > 0 && (
<p class="captured-at-row">
<time datetime={capturedAt.toISOString()} class="captured-at">
{fmtCaptured.format(capturedAt)}
</time>
</p>
)}
{import.meta.env.DEV && (
<div class="edit-tags">
{selectedTags.length > 0 && (
<div class="edit-tags-selected" aria-hidden="true">
{selectedTags.map((tag) => (
<span class={`edit-tag is-selected ${tag === 'delete' ? 'is-delete' : ''}`}>{tag}</span>
))}
</div>
)}
<div class="edit-tags-picker" role="group" aria-label="Editorial tags">
{availableTags.map((tag) => (
<button
type="button"
class:list={[
'edit-tag',
{ 'is-selected': selectedSet.has(tag), 'is-delete': tag === 'delete' },
]}
data-edit-action="copy"
data-command={`/edit-find-tag ${item.id} ${tag}`}
data-confirm={selectedSet.has(tag)
? `Remove "${tag}" from "${item.data.name}".`
: `Tag "${item.data.name}" with "${tag}".`}
>
{tag}
</button>
))}
<button
type="button"
class="edit-tag edit-tag-prompt"
data-edit-action="tag-prompt"
data-slug={item.id}
data-name={item.data.name}
aria-label="Add custom tag"
title="Add custom tag"
>
</button>
</div>
</div>
)}
</div>
</article>
@@ -124,6 +188,81 @@ function host(url: string) {
}
.ext-label { color: var(--accent); font-family: ui-sans-serif, system-ui, sans-serif; }
.captured-at-row {
margin: 0.25rem 0 0;
line-height: 1;
}
.captured-at {
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
font-size: 0.65rem;
color: var(--muted);
white-space: nowrap;
}
/* Editorial tags (dev-only) */
.edit-tags {
margin-top: 0.55rem;
position: relative;
z-index: 2;
}
.edit-tags-selected,
.edit-tags-picker {
display: flex;
flex-wrap: wrap;
gap: 0.3rem;
}
.edit-tags-picker { display: none; }
.find-card:hover .edit-tags-selected,
.find-card:focus-within .edit-tags-selected { display: none; }
.find-card:hover .edit-tags-picker,
.find-card:focus-within .edit-tags-picker { display: flex; }
.edit-tag {
font-family: ui-sans-serif, system-ui, -apple-system, 'Helvetica Neue', sans-serif;
font-size: 0.68rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
line-height: 1;
padding: 0.28rem 0.55rem;
margin: 0;
border-radius: 999px;
border: 1px solid var(--rule);
background: transparent;
color: var(--muted);
cursor: pointer;
transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
button.edit-tag { font: inherit; font-size: 0.68rem; font-weight: 600; }
.edit-tag:hover {
color: var(--accent);
border-color: color-mix(in srgb, var(--accent) 40%, var(--rule));
}
.edit-tag.is-selected {
color: var(--bg);
background: var(--fg);
border-color: var(--fg);
}
.edit-tag.is-selected:hover {
background: color-mix(in srgb, var(--fg) 85%, var(--accent));
color: var(--bg);
border-color: color-mix(in srgb, var(--fg) 85%, var(--accent));
}
.edit-tag.is-delete {
color: #c0392b;
border-color: color-mix(in srgb, #c0392b 35%, var(--rule));
}
.edit-tag.is-delete.is-selected {
background: #c0392b;
color: #fff;
border-color: #c0392b;
}
.edit-tag-prompt {
font-size: 0.85rem;
padding: 0.1rem 0.6rem 0.18rem;
color: var(--muted);
}
.edit-checkbox {
position: absolute;
top: 0.5rem;