Skip to content

Latest commit

 

History

41 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CSV Insights

CI codecov Version License

Upload a CSV, get instant charts. Sign in with GitHub or Google, drop in a file (or pick one of three sample datasets), and the dashboard builds a bar chart, a trend line, and summary stats automatically - no manual column mapping.

Live demo: quickcsv.vercel.app

Stack

Getting started

npm install
cp .env.example .env.local
npm run dev

Open http://localhost:3000. The landing page and /login work immediately; /dashboard requires a signed-in session (see below).

OAuth setup

  1. Generate a session secret and put it in .env.local:

    node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"

    AUTH_SECRET=...

  2. GitHub: create an OAuth App at github.com/settings/developers with callback URL http://localhost:3000/api/auth/callback/github. Put the client ID/secret in AUTH_GITHUB_ID / AUTH_GITHUB_SECRET. GitHub only supports one callback URL per OAuth App - if you also deploy this, you'll want a second app for production (see Deployment).

  3. Google: create an OAuth client at console.cloud.google.com/apis/credentials with callback URL http://localhost:3000/api/auth/callback/google. Put the client ID/secret in AUTH_GOOGLE_ID / AUTH_GOOGLE_SECRET. Google OAuth clients support multiple redirect URIs, so the same client works for both local dev and production - just add both URLs.

See .env.example for the full list of variables, including NEXT_PUBLIC_APP_URL (optional locally, used to build canonical Open Graph URLs in production).

Testing

Three layers, each covering what it's actually good at:

Layer Tool What it covers
Unit Vitest Pure logic: CSV type inference, parsing, column-magnitude ranking, category/time-series bucketing (lib/csv/*), string formatting (lib/format.ts)
Component Vitest + React Testing Library CsvUploader file-validation behavior (type/size/empty-file rejection, the happy path)
End-to-end Playwright Real browser flows against a production build: landing page, theme toggle, the /dashboard/login auth redirect, CSP-clean page load, carousel navigation, and the full GitHub OAuth redirect chain

Vitest + React Testing Library over Jest because it's faster and has native ESM/Turbopack compatibility with no extra config; Playwright over Cypress because it's the current Microsoft-backed standard for multi-browser E2E and integrates cleanly with Next.js's own webServer pattern.

npm test              # unit + component tests (Vitest)
npm run test:watch    # same, in watch mode
npm run test:e2e      # Playwright E2E - builds and starts a production
                       # server automatically, then runs against it

The GitHub OAuth E2E test needs real credentials in .env.local (see OAuth setup) and is skipped automatically if they're not present, so a fresh clone can still run the rest of the suite with zero config.

Both suites run automatically on every push and pull request via GitHub Actions - see the badge at the top of this file.

Security

A full security review - what was checked, what was found, and what was fixed (a middleware-only auth bypass, missing security headers, and patched CVEs in transitive dependencies) - is documented in SECURITY.md.

Deployment

Vercel (used for the live demo)

  1. Import the repo at vercel.com/new - Next.js is auto-detected, no config needed.
  2. Add environment variables (Production scope only - see SECURITY.md for why Preview is deliberately excluded for OAuth credentials): AUTH_SECRET, AUTH_GITHUB_ID, AUTH_GITHUB_SECRET, AUTH_GOOGLE_ID, AUTH_GOOGLE_SECRET.
  3. Deploy once to get your assigned *.vercel.app URL, then add NEXT_PUBLIC_APP_URL set to that URL and redeploy.
  4. Update your GitHub OAuth App and Google OAuth Client callback URLs to point at the deployed domain (see OAuth setup).

Docker (self-hosted)

docker build -t csv-insights .
docker run -p 3000:3000 --env-file .env.local -e PORT=3000 csv-insights

The Dockerfile is a three-stage build (depsbuilderrunner) using Next.js's output: "standalone" mode - only the files each route actually needs are traced and copied in, node_modules isn't shipped, and the container runs as a non-root user. standalone output is gated behind a DOCKER_BUILD env var set by the Dockerfile itself, so it has no effect on the Vercel build, which already has its own optimized pipeline.

Same OAuth callback rules apply as any other deployment: point your OAuth apps' callback URLs at wherever the container is actually reachable, and set NEXT_PUBLIC_APP_URL accordingly.

Project structure

app/
  page.tsx            # public landing page
  login/              # OAuth sign-in
  dashboard/           # protected - upload/sample picker, charts, preview table
  api/auth/[...nextauth]/  # Auth.js route handler
components/
  landing/            # landing page sections
  dashboard/           # uploader, sample picker, preview table, shell
  charts/             # recharts wrappers (bar, line, stat tile, tooltip)
  ui/                 # shadcn/ui primitives
  auth/               # OAuth sign-in buttons
lib/
  auth.ts             # Auth.js config
  csv/                # parsing + column-type inference + auto-insights (+ *.test.ts)
  sample-datasets.ts  # metadata for the 3 bundled sample CSVs
  actions/            # server actions (sign in/out)
types/
  csv.ts              # shared CSV/insights types
e2e/                  # Playwright end-to-end specs
proxy.ts              # route protection (Next 16's renamed middleware)
public/sample-data/   # the 3 sample CSVs
Dockerfile            # multi-stage build for self-hosting
SECURITY.md           # security review notes

How the auto-charts work

lib/csv/insights.ts picks columns without any user input:

  • The numeric column with the largest total magnitude becomes the primary metric (so "revenue" wins over "quantity").
  • The categorical column with the best top-8 coverage becomes the breakdown axis - this avoids picking either an overly blunt 2-value split or a high-cardinality column that dumps most rows into "Other".
  • If a date column exists, it's plotted as a time series, bucketed by month once there are more than 60 distinct dates.

This logic is covered by unit tests in lib/csv/insights.test.ts - see Testing.

License

MIT - see LICENSE.

About

Full-stack CSV data visualization dashboard with OAuth authentication, built with Next.js 15 and TypeScript.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages