SPB Git

spb/worthdoing Public

Autonomous investigation agent that discovers, challenges, and ranks things genuinely worth doing — Claude + Firecrawl, Next.js 16, PostgreSQL

TypeScript 91.5% SQL 5.8% CSS 2.2%
2.3 KB · 67 lines tsx
Raw Blame History
1/**2 * WorthDoing.ai3 * Author: Simon-Pierre Boucher4 * Contact: contact@spboucher.ai5 * File: src/app/explore/page.tsx6 * Description: Explore page — the accumulated opportunity database, ranked by Worth Score.7 */8import { desc, eq } from "drizzle-orm";9import { db } from "@/lib/db/client";10import { opportunities, investigations } from "@/lib/db/schema";11import { OpportunityCard } from "@/components/wd/OpportunityCard";1213export const dynamic = "force-dynamic";1415export default async function ExplorePage() {16  const rows = await db17    .select({18      id: opportunities.id,19      title: opportunities.title,20      summary: opportunities.summary,21      worthScore: opportunities.worthScore,22      evidenceConfidence: opportunities.evidenceConfidence,23      objective: investigations.objective,24      reportMd: opportunities.reportMd,25    })26    .from(opportunities)27    .innerJoin(investigations, eq(investigations.id, opportunities.investigationId))28    .orderBy(desc(opportunities.worthScore))29    .limit(100);3031  return (32    <div className="mx-auto w-full max-w-6xl px-4 py-10 sm:px-6">33      <h1 className="font-heading text-3xl font-semibold tracking-tight text-ink sm:text-4xl">34        The opportunity database35      </h1>36      <p className="mt-2 max-w-2xl text-ink-soft">37        Everything the agent has judged worth doing — ranked by Worth Score, with evidence38        confidence shown separately.39      </p>4041      {rows.length === 0 ? (42        <div className="mt-16 rounded-xl border border-dashed border-line bg-card/50 p-12 text-center">43          <p className="font-heading text-xl text-ink">Nothing here yet</p>44          <p className="mt-2 text-sm text-ink-soft">45            Run an investigation from the home page — validated opportunities land here.46          </p>47        </div>48      ) : (49        <div className="mt-8 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">50          {rows.map((o) => (51            <OpportunityCard52              key={o.id}53              id={o.id}54              title={o.title}55              summary={o.summary}56              worthScore={o.worthScore}57              evidenceConfidence={o.evidenceConfidence}58              objective={o.objective}59              hasReport={!!o.reportMd}60            />61          ))}62        </div>63      )}64    </div>65  );66}67