Skip to content

IslamIhab/smart-polling

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

smart-polling

This monorepo implements a smart polling application with conditional questions, anonymous participation, and scheduling. It uses Next.js + Tailwind on the frontend and Convex for the backend and auth.

Note: Running the app locally involves multiple services and configuring auth. For easier testing, please use the deployed version.

Features

  • TypeScript – End-to-end types
  • Next.js – App Router with React 19
  • TailwindCSS + shadcn/ui – Fast, accessible UI
  • Convex – Real-time data + auth via @convex-dev/auth
  • Turborepo – Monorepo orchestration
  • Biome – Linting/formatting

Architecture decisions

  • Monorepo layout: apps/web (Next.js UI), packages/backend (Convex functions, schema, auth). Shared types come from Convex codegen and are consumed in the app via the workspace dependency @smart-polling/backend.
  • Auth: @convex-dev/auth with Password and Anonymous providers. See packages/backend/convex/auth.ts. New password sign-ins can upgrade an existing anonymous user by patching the same record.
  • Data model: Defined in packages/backend/convex/schema.ts.
    • poll holds metadata (visibility, anonymous allowed, start/end times, creator)
    • pollQuestion holds per-question config with optional reliesOn dependency
    • pollResponse stores user answers
  • Conditional logic model: pollQuestion.reliesOn references another question by id and stores a simple condition string ("equals:value" or "contains:value"). This keeps the DB schema minimal and makes evaluation deterministic on the client.
  • Conditional logic evaluation: Performed client-side in apps/web/src/app/polls/[id]/page.tsx by isQuestionVisible. It checks dependency chains, resolves the operator, and supports both single/multi-choice and text questions.
  • Scheduling: Start/end timestamps are enforced in mutations (see submitResponse) and echoed to the client for display and disabling inputs.

Run locally (Bun + Convex)

  1. Install deps
bun install
  1. Configure Convex (local)
# Creates/links a Convex project and runs until the dev server is reachable
bun dev:setup

Follow the prompts to create a new Convex project and connect it to your application.

  1. Generate auth keys (required by @convex-dev/auth)

The backend includes a helper that prints a JWT_PRIVATE_KEY and JWKS JSON to stdout. Run it and copy the output into your Convex env.

# Prints two lines: JWT_PRIVATE_KEY=... and JWKS=...
bun generate-keys

Set these in your Convex dev environment

  1. Copy the .env.local from packages/backend to apps/web/.env following the example in apps/web/.env.example

  2. Then run the app

bun dev

Now visit http://localhost:3000.

How conditional logic is handled

  • Authoring (apps/web/src/app/polls/create/page.tsx):
    • Each question can optionally depend on a prior question via reliesOn, selecting either:
      • equals:<option> (for choice questions)
      • contains:<text> (for text questions)
    • The UI constrains valid dependencies to earlier questions and chooses a sensible default operator based on the source question type.
  • Persistence (packages/backend/convex/polls.ts):
    • On creation, the UI maps an author-time questionIndex into the stored reliesOn.questionId by inserting questions in order and resolving ids.
  • Evaluation (apps/web/src/app/polls/[id]/page.tsx):
    • isQuestionVisible checks dependency chains recursively, parses the condition string, and returns visibility. Choice answers support equals; text answers support case-insensitive contains.

Scripts

  • bun dev: Start all apps (Turborepo)
  • bun build: Build all apps
  • bun dev:web: Start the web app only
  • bun dev:server: Start the Convex backend only
  • bun dev:setup: Configure Convex and run until ready
  • bun check-types: Type-check all apps
  • bun check: Biome lint/format
  • bun generate-keys: Generates the keys for the auth to work

What I’d improve with more time

  • Server-side validation for conditional visibility: mirror client logic server-side to validate dependencies on write and on response submission.
  • Results and analytics: aggregate views, per-question breakdowns, and filters by answer.
  • Access control: per-poll roles (owner, collaborators), link-based private access tokens.
  • Rate limiting and abuse prevention: IP/device-based heuristics for anonymous responses.
  • Stronger condition language: AND/OR groups, numeric ops, regex, and multi-dependency graphs with guardrails.
  • Optimistic UI and offline: optimistic submits with reconcile on reconnect.
  • E2E tests: Playwright for flows (create, depend, participate, close).

About

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors