# Citation Manager: I built an Uberall competitor with 958 directories — and left auth on three stacks

Source: https://www.michaelchurley.com/blog/citation-manager-uberall-competitor-958-directories  
Published: 2026-08-08  
Author: Michael C. Hurley  
Tags: citation-manager, citations, local-seo, nap, uberall, brightlocal, yext, directories, convex, nextjs, clerk, hurleyus, saas

![Citation Manager dashboard mock. locations, submit, directories, submissions](/blog/citation-manager-uberall-competitor-958-directories/screenshots/dashboard.png)

## Who

I build operator tools for people who get paid when the NAP is right: agencies, multi-location owners, anyone tired of logging into Google, Yelp, and a dozen legacy directories by hand.

Citation Manager is that lane. Business listings out. Tracking what stuck. Skip the academic bibliography frame and the WNC city-guide frame.

If you care about local SEO plumbing, directory registries, or how a two-week SaaS sprint accumulates three auth stacks and a 500 on the homepage URL, these are the field notes.

## What

I shipped `HurleyUS/citation-manager`. Public TypeScript repo, package **0.0.1**, **83** commits, HEAD `78e9fb1`.

GitHub description is blunt: manage business listings across 1000+ directories. **Uberall competitor.** The README narrows it to **958+** directories and names Uberall, BrightLocal, and Yext as the alternatives it wants to undercut on price ($99 vs $500–2000/mo copy in the roadmap).

Stack on the box: **Next.js 16.2**, React 19, **Convex**, Tailwind v4, Bun, Lucide, Puppeteer, Argon2. Clerk and `@convex-dev/auth` sit in `package.json`; Fallow marks both unused while the UI talks to `/api/auth` and `localStorage` tokens.

![Directory registry mock. rank, method, API flags from directories.json](/blog/citation-manager-uberall-competitor-958-directories/screenshots/directories.png)

The real artifact is `data/directories.json`: **958** rows. Rank 1 is Google Business Profile. Methods break down api 88 / form 773 / manual 70 / email 27. `apiAvailable` is true on 219. Convex schema mirrors that world: `locations`, `directories`, `submissions` with pending to submitted to verified to failed, plus `verifications`.

Surfaces that exist: auth, dashboard, locations CRUD, directories browser with "View All 958", bulk submit with search/filter, submissions tracker, seed-directories API, google/yelp/facebook API routes.

What is also true:

- `bulkSubmit` inserts `pending` rows. The schedule helpers flip to `submitted` only if env keys exist. They do **not** call the fetch helpers in that path.
- `generateGoogleJWT` is a documented **placeholder**.
- Login hashes the password with Argon2 again and string-compares to the stored hash. New salt means verify cannot work as written.
- Dashboard copy still says "100+ directories" while the registry is 958.

![Bulk submit mock. location + directory multi-select](/blog/citation-manager-uberall-competitor-958-directories/screenshots/submit.png)

## Where

It is supposed to run on Vercel against Convex. Dev uses Caddy `cm.localhost:8080` to Next on 3000.

Probed 2026-09-08:

- **https://citation-manager-pi.vercel.app** (GitHub homepageUrl) returns **500** `MIDDLEWARE_INVOCATION_FAILED`
- **https://citation-manager.vercel.app** returns **200**, but it is a different "research workflow" citation app with Admin/User portals. **Name collision, not this product.**

Audience: local-SEO operators, agencies replacing BrightLocal/Yext spend, builders watching auth and integration honesty in a Convex/Next SaaS.

![Deploy reality mock. 500 homepage vs name-collision 200](/blog/citation-manager-uberall-competitor-958-directories/screenshots/deploy-reality.png)

## When

Created **2026-03-22**. Same day: scaffold, directory research, API skeletons, Clerk blank-page fix, Convex Auth swap, "FULL PHASE 2 READY FOR 6PM SHIP," Google Maps submission claim, locations wired to Convex.

Late March: Argon2, push-to-directories UI, View All 958, submissions dashboard.

**2026-04-01–02.** Registry expanded 100 to 958, Issue #12 Google/Yelp/Facebook modules, Clerk middleware returns, Phase 2B bypass + test infra, form validation, GBP PR.

**2026-05-14–15.** Seven "Standardize Blacksmith CI gates" commits (same batch pattern as sibling repos) plus deploy verification fixes.

**2026-08-08.** HEAD sets `X-Robots-Tag: index, follow`. Same day pattern as other HurleyUS pushes.

README still says Phase 2A 100% complete and Phase 2B "current" as of early April. Stripe is still Phase 4 fiction.

![Auth whiplash timeline. Clerk to Convex Auth to Argon2 to Clerk middleware to bypass](/blog/citation-manager-uberall-competitor-958-directories/screenshots/auth-whiplash.png)

## Why

Local citations are still a grind. The expensive tools win on coverage and integrations, not on elegance. I wanted an API-first Convex backend, a ranked directory registry I own as JSON, and a submit queue I can reason about in one schema.

I also wanted to ship before the story was clean. That is why the homepage 500s, why login verify is wrong, why Clerk middleware and a bypass flag coexist, and why the integration modules look finished while bulkSubmit mostly writes `pending`.

The registry is real. The competitor framing is real. The production URL on the GitHub homepage is not a product yet. It is an error page.

If you run citations for clients: would you trust a 958-row registry with honest `pending` states more than a vendor dashboard that always says "submitted"? What is the minimum live integration (Google only) before this is worth putting a real domain on?
