A Next.js application for collecting sentiment-annotated user feedback via an embeddable widget and an administrative dashboard.
- Quick overview
- Features
- Auth flow and schema
- Widget design and API specifications
- Embedding the widget
- Local development
- Project structure
- How to get an API key
- Security notes
- Contributing
- Deployment
- Built with Next.js (App Router), Prisma, and a small auth layer (Better Auth / OAuth).
- Collect feedback via the embeddable widget (
public/widget.js) — server validates API keys and performs sentiment analysis usingvader-sentiment. - Admin dashboard and project management lives under
app/(dashboard).
- Widget: quick embed for external sites (preview in
public/widget-test.html). - Feedback API: stores content, rating (1–5), type (BUG/FEATURE/OTHER), sentiment and score.
- Authentication: email/password + Google OAuth integration.
- Postgres (Prisma) for persistence and included migrations.
- Auth implementation:
lib/auth.ts(usesbetter-authwith the Prisma adapter). - Database schema:
prisma/schema.prisma— runpnpm prisma migrate devto apply changes andpnpm prisma generateto generate the client. - Important env vars:
DATABASE_URL— Postgres connection stringNEXTAUTH_URL— app url for OAuth callbacks (e.g.http://localhost:3000)NEXT_PUBLIC_URL— public base URL used to generate embed scriptsGOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET— for Google OAuthNEXTAUTH_SECRET— session / cookie secret (recommended)
- POST /api/feedback
- Headers:
X-API-Key: project API key (required)Content-Type: application/json
- Body (JSON):
content(string, required)rating(number, required, 1-5)feedbackType(string, optional:BUG|FEATURE|OTHER)email(string, optional)
- Success: 201 with
{ success: true, id } - Errors: 400 (validation), 401 (invalid/missing API key), 500 (server error)
Notes:
- The server runs a quick sentiment analysis (
vader-sentiment) and storessentimentandsentimentScorefor each submission. - CORS on
/api/feedbackis permissive (allows cross-origin embeds); make sure your API keys remain secret and rotate them if leaked.
Example cURL:
curl -X POST https://your-app.example.com/api/feedback \
-H "X-API-Key: <YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-d '{"content":"Love the new feature!","rating":5}'Create a project in the dashboard, copy the project's API key, then paste the embed script into your site where you want the widget:
<!-- simple embed (generated by dashboard) -->
<script
src="https:/fedback.akashd.online/widget.js"
data-project-key="YOUR_API_KEY"
></script>Or use the generateEmbedScript(apiKey, baseUrl) helper in lib/embed.ts to generate the snippet programmatically.
Prereqs: Node 18+, pnpm, Postgres.
- Install
pnpm install- Create a
.env(copy from.env.exampleif present) and set required variables:
DATABASE_URL="postgres://user:pass@localhost:5432/feedback"
NEXTAUTH_URL=http://localhost:3000
NEXT_PUBLIC_URL=http://localhost:3000
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-secret
NEXTAUTH_SECRET=some-random-secretNever commit secrets to the repo. Use a
.env.example(without secrets) for onboarding.
- Migrate & generate client
pnpm prisma migrate dev --name init
pnpm prisma generate- Run dev server
pnpm devapp/— Next.js routes & pages (App Router)components/— UI and widget componentspublic/— demo images, widget JS, test HTMLlib/— helpers:auth.ts,db.ts,embed.ts,utils.tsprisma/— schema & migrationsactions/— server/client helpers for auth, projects, feedback
- Sign in and go to Projects → Create project.
- Copy the API key from the project page or use the Copy API Key button.
- Paste the key into the
data-project-keyattribute in the embed script.
Contributions are welcome. Open issues or pull requests with focused changes.
