Example output, no signup required

Here's what we generate from a job description.

Below is one real run. We pasted the job description on the left into Evaluator and kept what came back, unedited: 8 questions across all 6 dimensions, sized to the 45 minute limit we set, and about 17 if you set no limit. That includes the AI Collaboration section, which grades how well candidates read, fix, and work with AI-written code. We show 4 of the 8, one from each of four sections, including that one. The job description is one we wrote for this page.

Generate one for my role, freeOr scroll and skim first, no rush.

Generation

~100s

Questions

Fits your time limit

Dimensions

6 scored rubrics

Integrity

Per-Q AI score

  • Frontier-grade AI under the hood
  • Self-serve, no sales call
  • 10 free cycles, no credit card required
  • Cancel any time
Example output

Generated output (4 of 8 questions shown)

Q1, 10 ptsReadingmultiple choice

Explain the Zustand selector behavior

A teammate wrote the following Zustand store and component. What will happen to the component's render behavior when `filters` changes but `selectedRowIds` does not?

import { create } from 'zustand'

interface DashboardState {
  filters: Record<string, string>
  selectedRowIds: Set<string>
  reportTitle: string
  setFilters: (filters: Record<string, string>) => void
}

const useDashboardStore = create<DashboardState>((set) => ({
  filters: {},
  selectedRowIds: new Set(),
  reportTitle: 'Q1 Report',
  setFilters: (filters) => set({ filters }),
}))

function SelectedRowCounter() {
  const state = useDashboardStore()
  return <div>Selected: {state.selectedRowIds.size}</div>
}
  • A) The component will not re-render because it only reads `selectedRowIds`, which has not changed.
  • B) The component will re-render on every store update because it subscribes to the entire store state object.
  • C) The component will throw a runtime error because `Set` is not a valid Zustand state type.
  • D) The component will re-render only if `reportTitle` also changes, because Zustand batches unrelated updates.
Q2, 25 ptsWritingcode editor

Implement a paginated data fetching hook

Implement the `usePaginatedReports` hook below. The hook must use TanStack Query to fetch paginated report data from the provided `fetchReports` function. It must expose the current page, a way to go to the next page, a way to go to the previous page, the fetched data, a loading state, and an error state. The hook should prefetch the next page in the background so navigation feels instant. Page numbers are 1-indexed and must not go below 1. The `fetchReports` function signature and the expected return shape are shown in the starter code.

Candidate editor

import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useState, useEffect } from 'react';

export interface Report {
  id: string;
  name: string;
  createdAt: string;
  value: number;
}

export interface PaginatedResponse<T> {
  data: T[];
  totalPages: number;
  currentPage: number;
}

async function fetchReports(page: number): Promise<PaginatedResponse<Report>> {
  const response = await fetch(`/api/reports?page=${page}&pageSize=50`);
  if (!response.ok) throw new Error('Failed to fetch reports');
  return response.json();
}

export interface UsePaginatedReportsResult {
  data: PaginatedResponse<Report> | undefined;
  isLoading: boolean;
  isError: boolean;
  currentPage: number;
  goToNextPage: () => void;
  goToPreviousPage: () => void;
}

export function usePaginatedReports(): UsePaginatedReportsResult {
  // TODO: implement the hook here
}
Q3, 15 ptsCommunicationshort answer

Write a PR description

Below is a before-and-after code change from a real dashboard feature. Review both versions, then write a concise pull request description as you would for your team. Your description should cover: what changed, why the change was made, and any trade-offs or follow-up work worth noting. Aim for the level of detail you would expect from a senior engineer on your own team.

// BEFORE: fetching report data directly inside the component
import { useEffect, useState } from 'react';

type Report = {
  id: string;
  label: string;
  value: number;
};

export function ReportTable({ orgId }: { orgId: string }) {
  const [data, setData] = useState<Report[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    setLoading(true);
    fetch(`/api/orgs/${orgId}/reports`)
      .then((res) => res.json())
      .then((json) => {
        setData(json);
        setLoading(false);
      })
      .catch(() => {
        setError('Failed to load reports');
        setLoading(false);
      });
  }, [orgId]);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>{error}</p>;
  return <table>{/* render rows */}</table>;
}

// AFTER: fetching via TanStack Query
import { useQuery } from '@tanstack/react-query';

type Report = {
  id: string;
  label: string;
  value: number;
};

async function fetchReports(orgId: string): Promise<Report[]> {
  const res = await fetch(`/api/orgs/${orgId}/reports`);
  if (!res.ok) throw new Error('Failed to load reports');
  return res.json();
}

export function ReportTable({ orgId }: { orgId: string }) {
  const { data, isLoading, isError } = useQuery({
    queryKey: ['reports', orgId],
    queryFn: () => fetchReports(orgId),
  });

  if (isLoading) return <p>Loading...</p>;
  if (isError) return <p>Failed to load reports.</p>;
  return <table>{/* render rows */}</table>;
}
Q4, 15 ptsAI collaborationshort answer

Write an AI prompt for a paginated report table

You need to implement a paginated, sortable report table for a B2B SaaS dashboard. The table displays up to 50,000 rows of financial transaction data fetched from a REST API. Pagination is server-side, with page size fixed at 100 rows. Sorting is also server-side: clicking a column header sends a new request with sort field and direction as query parameters. The component must use TanStack Query for data fetching and caching, Zustand for storing the current page and sort state, and TypeScript with strict mode enabled. Loading and error states must be handled explicitly, and the previous page's data should remain visible while the next page loads. Write the exact prompt you would give an AI coding assistant to implement this feature. Do not write the implementation itself. We are scoring the quality of your prompt, not any resulting code.

Candidate response

(text field)

+ 4 more across code reading, debugging, tradeoffs and AI collaboration, all scored automatically with per-question feedback and an integrity report per submission.

Graded output

And here is what it does with the answers.

Generating questions is the easy half. This is the half you are buying: every answer scored against a rubric, the reasoning written out, and, outside the AI Collaboration section where AI use is expected and detection is switched off by design, a per-question read on whether a person wrote it.

ReadingExplain the Zustand selector behavior
0 / 10

Candidate answer

A) The component will not re-render because it only reads `selectedRowIds`, which has not changed.

Grader feedback

The correct answer is B. When useDashboardStore is called with no selector argument, the component subscribes to the entire store state object. Any state change, including a change to filters, will cause a re-render because the reference to the returned state object changes on every update. The candidate selected A, which describes what would happen if a selector like (s) => s.selectedRowIds were used. This is a foundational Zustand behavior that is worth reviewing.

AI likelihood

10%

Single sentence answer selecting a multiple choice option, clearly human.

WritingImplement a paginated data fetching hook
18 / 25

Candidate answer

import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useState, useEffect } from 'react';

export interface Report {
  id: string;
  name: string;
  createdAt: string;
  value: number;
}

export interface PaginatedResponse<T> {
  data: T[];
  totalPages: number;
  currentPage: number;
}

async function fetchReports(page: number): Promise<PaginatedResponse<Report>> {
  const response = await fetch(`/api/reports?page=${page}&pageSize=50`);
  if (!response.ok) throw new Error('Failed to fetch reports');
  return response.json();
}

export interface UsePaginatedReportsResult {
  data: PaginatedResponse<Report> | undefined;
  isLoading: boolean;
  isError: boolean;
  currentPage: number;
  goToNextPage: () => void;
  goToPreviousPage: () => void;
}

export function usePaginatedReports(): UsePaginatedReportsResult {
  const [currentPage, setCurrentPage] = useState(1);

  const { data, isLoading, isError } = useQuery({
    queryKey: ['reports', currentPage],
    queryFn: () => fetchReports(currentPage),
  });

  const goToNextPage = () => {
    setCurrentPage(currentPage + 1);
  };

  const goToPreviousPage = () => {
    setCurrentPage(currentPage - 1);
  };

  return {
    data,
    isLoading,
    isError,
    currentPage,
    goToNextPage,
    goToPreviousPage,
  };
}

Grader feedback

The hook is structurally correct: useState initialised to 1, useQuery with a key that includes currentPage, and goToPreviousPage and goToNextPage functions. The return type annotation is present and accurate. However, two requirements from the spec are missing. First, there is no prefetch of the next page: the description explicitly asks for a useEffect that calls queryClient.prefetchQuery for currentPage + 1, which is what makes navigation feel instant. Second, goToPreviousPage does not clamp at 1, meaning a user on page 1 could set currentPage to 0 and fire a request for page 0. The goToNextPage and goToPreviousPage functions would also benefit from using the functional updater form, setCurrentPage((prev) => prev + 1), to avoid acting on a stale closure. Overall, the core pattern is solid and the TypeScript is clean, but the two missing requirements are meaningful gaps.

AI likelihood

30%

Clean, correct code with no comments or padding. Reasonable for someone who knows TanStack Query well, though the absence of any roughness is a mild signal.

CommunicationWrite a PR description
11 / 15

Candidate answer

## Summary

This pull request refactors the `ReportTable` component to leverage
TanStack Query for data fetching, replacing the previous manual
implementation based on `useEffect` and local component state.

## Motivation

The existing implementation manages three separate pieces of state
(`data`, `loading`, and `error`) within the component itself. This
approach, while functional, introduces several challenges:

- **Lack of caching**: Every mount triggers a fresh network request.
- **Race conditions**: Rapid changes to `orgId` may result in stale
  responses being applied out of order.
- **Boilerplate**: The imperative pattern requires substantial repetition
  across components.

## Changes

- Introduced a dedicated `fetchReports` function for improved separation
  of concerns.
- Replaced the `useEffect` and `useState` logic with a single `useQuery`
  invocation.
- Adopted a structured query key (`['reports', orgId]`) to enable granular
  cache invalidation.
- Enhanced error handling by leveraging the built-in `isError` state.

## Reviewer Considerations

Reviewers should pay particular attention to the query key structure, as
this determines caching granularity. It is also worth noting that error
messaging is now handled generically.

## Follow-up Work

Future iterations could explore prefetching, optimistic updates, and a
shared query client configuration to further enhance the developer
experience.

Grader feedback

The PR description covers all three required areas: what changed, why, and follow-up work. The motivation section correctly identifies caching, race conditions, and boilerplate as the problems being solved. The changes list accurately describes the structural difference. The follow-up mentions prefetching and a shared query client configuration, which aligns with the model answer's suggestion about a QueryClient provider and moving fetchReports to a shared module. The main gap is that the staleTime and retry configuration considerations are not mentioned, and the description does not call out that the queryKey ties cache entries to orgId specifically. The formatting is very polished with markdown headers and bold bullets, which may be appropriate for some teams but is heavier than a typical PR body in many organisations. The substance is good, but some of the phrasing is generic.

AI likelihood

72%

Uses markdown headers, bold bullet points, and formal section names like 'Reviewer Considerations' and 'Follow-up Work'. Phrasing such as 'further enhance the developer experience' is a common LLM hedge. The level of structural polish is unusual for a timed answer.

AI collaborationWrite an AI prompt for a paginated report table
4 / 15

Candidate answer

Write me a React component for a paginated report table.

It should use TanStack Query to fetch the data and Zustand for the state. It
needs to be in TypeScript. Make sure it handles pagination and sorting, and
add loading and error states. Use best practices and make it production
ready.

Grader feedback

The prompt is too generic to be useful. It names TanStack Query and Zustand but omits versions, which matters because the keepPreviousData API changed between TanStack Query v4 and v5. It does not specify the query parameter contract (sort_field, sort_direction), the Zustand store shape, or any TypeScript interface expectations. The requirement to keep the previous page visible while loading is stated in the problem but absent from the prompt, so the AI would have no reason to use placeholderData or keepPreviousData. There is no mention of strict mode, no success criteria, and no edge cases called out. A prompt this sparse would produce generic boilerplate that the candidate would then need to heavily revise, which defeats the purpose of the collaboration.

Collaboration rubric

Prompt quality18
Critical reviewnot scored
Autonomynot scored

The prompt names TanStack Query and Zustand but gives no versions, no TypeScript strict mode callout, no query parameter contract, no Zustand store shape, no interface definitions, no mention of keepPreviousData or placeholderData for the stale-data requirement, and no edge cases. It is essentially a high-level feature description with a 'make it production ready' instruction, which is the canonical example of a weak prompt. An AI given this prompt would have to guess almost every important implementation detail.

Ready to try?

Paste your job description and we will generate a full assessment against it. It takes about 100 seconds, so start it and leave the tab open.

Paste a real job description and see your own assessment in about 100 seconds.

No signup, no credit card required. Free tier after sign-up is 10 full cycles per month, with scoring, a shareable candidate link, and an integrity report included.

At least 40 characters (40 to go)0/8,000
Runs your JD in about 100 seconds.

Like what you see? Save it to your account.

Sign up free to save your generated assessment, get a shareable candidate link, automated scoring, and the per-question AI-likelihood report. 10 cycles per month, no credit card.

Generate one for your role

Paste any engineering job description, get a tailored assessment in about 100 seconds, sized to the time limit you set. 10 free cycles per month, no credit card required.

What if it's not a fit?

The free tier is 10 cycles per month, no card required. If you try it and it's not useful, no one chases you. The account just sits there. Paid plans cancel any time from settings.

What happens to my job descriptions?

They stay in your account. We use a third-party AI API to generate questions, which doesn't train on API inputs. See our privacy policy for the specifics.

How is AI detection even possible?

It's a per-question likelihood score based on tells in the response (vocabulary, pacing, formatting, consistency with earlier answers). Not perfect (no detector is), but useful as a ranked signal for reviewers.

Can I cancel any time?

Yes. Paid plans cancel from your account settings and downgrade at the end of the current billing period. No sales calls, no retention flow.

Comparing tools?

We've written honest side-by-sides with the major players.