Skip to content
Back to skills

setup-activity-log

ASecurity

Scaffold an admin activity log feature into a Next.js + Supabase project. Adds an audit_log database table (append-only, admin-only via RLS), a /admin/activity page that shows a feed of who-did-what plus a free-form "log an update" form, an API route at /api/admin/audit-log, and a logAuditEvent() helper that other admin endpoints can call to record events. Use when the user wants to add audit logging, an activity feed, a "what's new" / changelog page, or who-did-what tracking to an existing N...

  • 2 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added May 26, 2026
developmentsqlreactnextjsapidatabase

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 5 files and shows the line behind each finding

Scanned May 27, 2026

npx -y skills add SamDaMan636/claude-skill-activity-log --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of setup-activity-log?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for setup-activity-log
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/samdaman636-setup-activity-log/badge)](https://www.skillsdirectory.com/skills/samdaman636-setup-activity-log)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: setup-activity-log
description: Scaffold an admin activity log feature into a Next.js + Supabase project. Adds an audit_log database table (append-only, admin-only via RLS), a /admin/activity page that shows a feed of who-did-what plus a free-form "log an update" form, an API route at /api/admin/audit-log, and a logAuditEvent() helper that other admin endpoints can call to record events. Use when the user wants to add audit logging, an activity feed, a "what's new" / changelog page, or who-did-what tracking to an existing Next.js + Supabase admin dashboard.
---

# Setup Activity Log

This skill installs a complete admin activity-log feature into the current project. Covers both auto-captured admin actions (settings changes, invites, etc.) and manual "we shipped X" notes typed by an admin.

## Pre-flight checks

Before writing any files, verify the target project:

1. **Stack check** — read `package.json`. The project must have:
   - `next` (app router — confirm by checking for `src/app/` or `app/`)
   - `@supabase/ssr` and `@supabase/supabase-js`
   - shadcn-style UI primitives at `src/components/ui/` (`card.tsx`, `button.tsx`, `input.tsx`, `textarea.tsx`)
   - `lucide-react`
   - `sonner` (for toasts) — if missing, swap toasts for inline error text in `page.tsx`
   - `zod` (for input validation in the API route)

   If any are missing, tell the user and stop. Don't half-install.

2. **Auth pattern detection** — find how admin endpoints check authorization in this project:
   - Search for `requireAdmin`, `isAdmin`, `requireAdminStrict`, or similar in `src/lib/auth.ts` or `src/lib/`
   - Note the exact import path and function name — you'll substitute this into `route.ts`
   - If the project uses a different pattern entirely (e.g. middleware-only, no helper), ask the user how admin endpoints are gated and adapt

3. **Profile/role schema** — the SQL migration assumes a `profiles` table with a `role` column where admins have `role = 'admin'`. Before running it:
   - Search the existing supabase/ folder for the schema
   - If the project uses different names (e.g. `users.is_admin = true`), edit the RLS policies in `templates/add_audit_log.sql` accordingly
   - Note this for the user

4. **Supabase admin client** — confirm `src/lib/supabase/admin.ts` exists and exports `createAdminClient`. If it's at a different path, update the import in `templates/audit-log.ts` and `templates/route.ts`.

5. **Supabase server client** — confirm `src/lib/supabase/server.ts` exists with a `createClient` async function. Update import in `templates/audit-log.ts` if needed.

## Installation

Once pre-flight passes, copy the four template files into place. Read each from `templates/` (in this skill's folder) and write to the target paths below. **Do not modify the templates** other than the small substitutions noted in pre-flight.

| Template | Target path |
|---|---|
| `templates/add_audit_log.sql` | `supabase/add_audit_log.sql` (or wherever this project keeps migrations) |
| `templates/audit-log.ts` | `src/lib/audit-log.ts` |
| `templates/route.ts` | `src/app/api/admin/audit-log/route.ts` |
| `templates/page.tsx` | `src/app/admin/activity/page.tsx` |

Then update the admin sidebar:

- Find the admin sidebar component (commonly `src/components/admin/admin-sidebar.tsx` or `src/components/layout/admin-nav.tsx`)
- Import the `History` icon from `lucide-react`
- Add a nav entry: `{ href: "/admin/activity", label: "Activity", icon: History }` — place it just before the "Settings" entry

Don't instrument any endpoints automatically. The user will add `logAuditEvent()` calls to specific admin endpoints later as needs arise.

## After installation

Tell the user to do exactly two things:

1. **Run the SQL migration**
   - Open https://supabase.com/dashboard → the relevant project
   - SQL Editor → New query → paste the contents of the new `add_audit_log.sql` file → Run
   - Expect "Success. No rows returned."

2. **Refresh and verify**
   - Visit `/admin/activity` while signed in as admin
   - Should see an empty feed and a "Log an update" form
   - Type a test entry, hit "Log entry", confirm it appears

Then offer to walk them through wiring auto-logging into a specific endpoint. The pattern is one line at the end of any admin handler:

```ts
import { logAuditEvent } from "@/lib/audit-log"

await logAuditEvent({
  action: "settings.update",        // domain.verb
  target: "brand_name",              // optional human-readable identifier
  summary: "Updated brand name to X",
  before: oldValue,                  // optional snapshot
  after: newValue,                   // optional snapshot
})
```

For client-side admin pages that write to Supabase directly (e.g. a settings page that does `.from('app_settings').upsert(...)`), they can insert into `audit_log` directly — RLS allows admins to insert their own rows. Pattern:

```ts
const { data: { user } } = await supabase.auth.getUser()
if (user?.email) {
  await supabase.from("audit_log").insert({
    actor_id: user.id,
    actor_email: user.email,
    source: "auto",
    action: "settings.update",
    target: changedKeys.join(", "),
    summary: `Updated settings: ${changedKeys.join(", ")}`,
    before: oldSnapshot,
    after: newSnapshot,
  })
}
```

## Action naming convention

Use `domain.verb` format so the feed groups related events:

- `settings.update` — admin saved settings
- `user.invite` — new user invited
- `user.temp_password` — admin issued a temp password
- `content.upload` / `content.delete` — content management
- `feature.deploy` — code change shipped (insert with `source: 'auto'` so no "manual" badge)
- `manual.note` — free-form admin note via the form (set automatically by the API)

Add new actions to `ACTION_ICONS` and `actionLabel()` in `templates/page.tsx` (or have the user do it once in their copy) so they render with proper icons and human labels.

Files in this skill

  • SKILL.md5.8 KB
  • templates/add_audit_log.sql2.6 KB
  • templates/audit-log.ts2 KB
  • templates/page.tsx8.2 KB
  • templates/route.ts2.6 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.