Skip to content

feat: GitHub auth + Turso persistence (saved graphs & testimonials)#111

Merged
DataDave-Dev merged 2 commits into
mainfrom
feat/auth-turso-persistence
Jun 18, 2026
Merged

feat: GitHub auth + Turso persistence (saved graphs & testimonials)#111
DataDave-Dev merged 2 commits into
mainfrom
feat/auth-turso-persistence

Conversation

@DataDave-Dev

@DataDave-Dev DataDave-Dev commented Jun 18, 2026

Copy link
Copy Markdown
Owner

Resumen

Añade autenticación con GitHub y persistencia con Turso (libSQL) para guardar grafos por usuario y un muro de testimonios.

Qué incluye

  • Auth.js v5 + GitHub provider con adapter de Drizzle (sesiones en BD).
  • Turso / libSQL vía Drizzle: tablas user, account, session, verificationToken, graph, testimonial.
  • Grafos privados por usuario con historial en /[lang]/graphs y vista en /[lang]/graphs/[id] (reusa <Diagram>).
  • Muro de testimonios público en la landing.
  • Server actions validadas con Zod (src/lib/validation.ts) para grafos, testimonios y auth.
  • Header: sign in / avatar + sign out; botón "Guardar grafo" en el workspace.
  • i18n (auth.*) en los 6 idiomas.
  • CSP: permite avatares de GitHub en img-src.
  • Migración generada en drizzle/ (el SQL a aplicar en producción).
  • Fix: pnpm-workspace.yaml al formato estándar onlyBuiltDependencies (estaba con un placeholder roto que bloqueaba instalar/scripts).

Sin middleware de auth

Next.js solo admite un middleware y src/proxy.ts ya hace locale-routing + CSP nonce. La protección se hace server-side (auth() en Server Components/Actions).

Configuración requerida (no en el repo)

Variables de entorno: AUTH_SECRET, AUTH_GITHUB_ID, AUTH_GITHUB_SECRET, TURSO_DATABASE_URL, TURSO_AUTH_TOKEN.

  • OAuth App de GitHub con callback …/api/auth/callback/github (una para local, otra para prod).
  • BD Turso de producción + esquema aplicado (drizzle/0000_*.sql).

Verificación

  • pnpm typecheck
  • pnpm lint
  • pnpm test ✓ (55 tests, incluye validación de schemas)
  • pnpm build ✓ (todas las rutas, incl. /api/auth/[...nextauth] y /[lang]/graphs)
  • Probado en local: login con GitHub, guardar grafo, historial, testimonio.

Fuera de alcance (YAGNI)

Compartir grafos por link, comentarios por grafo, otros providers (Google/email).

Summary by CodeRabbit

Release Notes

  • New Features

    • Added user authentication with GitHub sign-in.
    • Introduced ability to save and manage diagrams—view, open, and delete saved work.
    • Added testimonials section on the homepage for user feedback.
    • New "My graphs" page displaying saved diagrams by user.
    • Implemented authentication UI in the header with sign-in/sign-out controls.
  • Chores

    • Set up database infrastructure and schema.
    • Added database management CLI commands.
    • Updated environment configuration.
    • Added validation for user inputs.
  • Tests

    • Added input validation tests.

…imonials

- Auth.js v5 with GitHub provider and Drizzle adapter (database sessions)
- Turso/libSQL via Drizzle: users, accounts, sessions, graphs, testimonials
- Save graphs per user (private) with history pages under /[lang]/graphs
- Public testimonial wall on the landing page
- Zod-validated server actions for graphs, testimonials and auth
- Header sign in/out + avatar; save button in the workspace
- i18n keys (auth.*) across all six locales
- CSP: allow GitHub avatars in img-src
- Fix pnpm-workspace.yaml to standard onlyBuiltDependencies format
@ecc-tools

ecc-tools Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 64466bd1-0969-4fde-b0ef-5e00d8d1a5ee

📥 Commits

Reviewing files that changed from the base of the PR and between 3fd45c2 and efd9654.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (34)
  • .env.example
  • .gitignore
  • drizzle.config.ts
  • drizzle/0000_colossal_hex.sql
  • drizzle/meta/0000_snapshot.json
  • drizzle/meta/_journal.json
  • package.json
  • pnpm-workspace.yaml
  • src/app/[lang]/app/page.tsx
  • src/app/[lang]/graphs/[id]/page.tsx
  • src/app/[lang]/graphs/page.tsx
  • src/app/[lang]/layout.tsx
  • src/app/[lang]/page.tsx
  • src/app/api/auth/[...nextauth]/route.ts
  • src/auth.ts
  • src/components/layout/Header.tsx
  • src/components/sections/TestimonialForm.tsx
  • src/components/sections/Testimonials.tsx
  • src/components/ui/CodeWorkspace.tsx
  • src/components/ui/GraphListItem.tsx
  • src/db/index.ts
  • src/db/schema.ts
  • src/i18n/dictionaries/ar.json
  • src/i18n/dictionaries/en.json
  • src/i18n/dictionaries/es.json
  • src/i18n/dictionaries/fr.json
  • src/i18n/dictionaries/it.json
  • src/i18n/dictionaries/pt.json
  • src/lib/auth-actions.ts
  • src/lib/graphs.ts
  • src/lib/testimonials.ts
  • src/lib/validation.test.ts
  • src/lib/validation.ts
  • src/proxy.ts

📝 Walkthrough

Walkthrough

This PR integrates GitHub OAuth authentication via NextAuth backed by a Drizzle/LibSQL (Turso) database. It adds a full database schema, migration, and CRUD data-access modules for user-owned graphs and public testimonials. New pages let authenticated users list, view, and delete saved graphs, while the editor workspace gains a save button. A testimonials section is added to the home page. Six locale dictionaries receive new auth i18n strings.

Changes

Auth, Database, Graph Saving, and Testimonials

Layer / File(s) Summary
DB schema, migration, and configuration
src/db/schema.ts, src/db/index.ts, drizzle/0000_colossal_hex.sql, drizzle/meta/*, drizzle.config.ts, .env.example, .gitignore, package.json, pnpm-workspace.yaml
Drizzle SQLite schema defines Auth.js tables (users, accounts, sessions, verificationTokens) and app tables (graphs, testimonials) with cascade deletes. The initial SQL migration and meta snapshot are generated. Drizzle Kit config, LibSQL client initialization, environment variable examples, gitignore rules for local DB files, and new db:* scripts and dependencies are added.
NextAuth configuration and server actions
src/auth.ts, src/app/api/auth/[...nextauth]/route.ts, src/lib/auth-actions.ts, src/proxy.ts
NextAuth is configured with DrizzleAdapter wired to all four Auth.js tables, GitHub provider, and a session callback that exposes user.id. The API route handler exports GET/POST with nodejs runtime. Two server actions (signInGitHub, signOutAction) wrap the NextAuth primitives. CSP img-src is extended to allow avatars.githubusercontent.com.
Zod validation schemas and tests
src/lib/validation.ts, src/lib/validation.test.ts
Exports graphMetaSchema, graphSchema, sourceSchema, and testimonialSchema with size limits and refinements. Vitest tests cover rejection and acceptance paths for all four schemas.
Graph and testimonial data-access modules
src/lib/graphs.ts, src/lib/testimonials.ts
Server-side modules gate all operations via requireUserId()/auth(). graphs.ts exposes saveGraph, listGraphs, getGraph, and deleteGraph with ownership enforcement. testimonials.ts exposes listTestimonials (50-row join query) and postTestimonial (validates body, inserts, returns structured state).
Header auth UI and layout wiring
src/components/layout/Header.tsx, src/app/[lang]/layout.tsx, src/i18n/dictionaries/*.json
Header gains a user prop and renders "My graphs" link plus sign-out form (with avatar) or a GitHub sign-in form. RootLayout calls auth() and forwards the user to Header. Six locale dictionaries (en, es, fr, it, pt, ar) receive the new auth key block.
CodeWorkspace save button and saved-graph pages
src/components/ui/CodeWorkspace.tsx, src/app/[lang]/app/page.tsx, src/app/[lang]/graphs/page.tsx, src/app/[lang]/graphs/[id]/page.tsx, src/components/ui/GraphListItem.tsx
CodeWorkspace adds isAuthed, save labels, saving/saved state, and handleSave that calls saveGraph. The app page passes auth state and labels. A graphs list page renders GraphListItem components with delete transitions and route refresh. A saved-graph detail page enforces auth, loads graph JSON, and renders the Diagram component.
Testimonials UI and home page integration
src/components/sections/Testimonials.tsx, src/components/sections/TestimonialForm.tsx, src/app/[lang]/page.tsx
Testimonials (server component) fetches session and testimonial items concurrently and conditionally renders TestimonialForm or a sign-in prompt, then a grid of testimonial cards. TestimonialForm (client component) uses useActionState wired to postTestimonial, resets the form and calls router.refresh() on success. Testimonials is rendered on the home page.

Sequence Diagram(s)

sequenceDiagram
    participant Browser
    participant RootLayout
    participant NextAuth as NextAuth /api/auth
    participant GitHubOAuth as GitHub OAuth
    participant db as LibSQL (Turso)
    participant CodeWorkspace
    participant saveGraph as saveGraph()
    participant GraphsPage as /[lang]/graphs

    Browser->>RootLayout: page request
    RootLayout->>NextAuth: auth()
    NextAuth->>db: SELECT session WHERE sessionToken
    db-->>RootLayout: session | null
    RootLayout-->>Browser: Header with user/sign-in

    Browser->>NextAuth: POST /api/auth/signin/github
    NextAuth->>GitHubOAuth: OAuth redirect
    GitHubOAuth-->>NextAuth: callback with code
    NextAuth->>db: UPSERT user, account, session
    NextAuth-->>Browser: session cookie

    Browser->>CodeWorkspace: click Save
    CodeWorkspace->>saveGraph: saveGraph(title, language, graph, source)
    saveGraph->>db: INSERT INTO graphs
    db-->>CodeWorkspace: { id }

    Browser->>GraphsPage: GET /[lang]/graphs
    GraphsPage->>db: SELECT graphs WHERE userId ORDER BY createdAt DESC
    db-->>GraphsPage: graph rows
    GraphsPage-->>Browser: rendered graph list
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • DataDave-Dev/weftmap#84: Both PRs modify src/components/layout/Header.tsx and alter the Header component's props and conditional rendering logic at the same component level.
  • DataDave-Dev/weftmap#109: Both PRs modify pnpm-workspace.yaml to adjust which dependencies are allowed to run build scripts, touching the same configuration key.

Poem

🐇 A rabbit dug tunnels through auth and SQL,
Carved tables for users, graphs, and reviews too.
With GitHub it hops in, sessions take flight,
Saves diagrams by day and testimonials by night.
The warren grows richer — now logged in, we cheer! 🎉

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/auth-turso-persistence

Comment @coderabbitai help to get the list of available commands and usage tips.

@DataDave-Dev
DataDave-Dev merged commit 890bad8 into main Jun 18, 2026
0 of 2 checks passed
@DataDave-Dev
DataDave-Dev deleted the feat/auth-turso-persistence branch June 18, 2026 18:08
DataDave-Dev added a commit that referenced this pull request Jun 18, 2026
PR #111 added drizzle-kit (which pulls esbuild). esbuild's build script
was left undecided as a placeholder in pnpm-workspace.yaml, and the prior
change to onlyBuiltDependencies isn't the format this pnpm honors, so the
Vercel install failed with ERR_PNPM_IGNORED_BUILDS. Set esbuild: true and
keep the other builds disabled.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant