CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl-labs/typescript-project-structure

TypeScript project structure, strict tsconfig, module resolution, path aliases, shared types, and monorepo patterns

90

1.09x
Quality

84%

Does it follow best practices?

Impact

100%

1.09x

Average score across 5 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

criteria.jsonevals/scenario-3/

{
  "context": "Tests whether the agent correctly sets up a full-stack TypeScript project with shared types between React frontend and Express backend, separate tsconfig files with correct module resolution for each, and proper build/dev scripts.",
  "type": "weighted_checklist",
  "checklist": [
    {
      "name": "Shared types directory",
      "description": "A shared/ directory (or similar) exists with type definitions that are imported by BOTH client (src/) and server (server/) code — types are not duplicated",
      "max_score": 12
    },
    {
      "name": "Separate tsconfig for server",
      "description": "A separate tsconfig.server.json (or tsconfig.server.json) exists for the server, distinct from the client/base tsconfig.json",
      "max_score": 10
    },
    {
      "name": "Frontend uses bundler resolution",
      "description": "The frontend/base tsconfig.json uses moduleResolution: \"bundler\" (or \"Bundler\") paired with module: \"ESNext\", appropriate for Vite",
      "max_score": 8
    },
    {
      "name": "Server uses NodeNext resolution",
      "description": "tsconfig.server.json uses moduleResolution: \"NodeNext\" paired with module: \"NodeNext\" for proper Node.js ESM support",
      "max_score": 8
    },
    {
      "name": "Both tsconfigs have strict: true",
      "description": "Both tsconfig.json and tsconfig.server.json have \"strict\": true",
      "max_score": 10
    },
    {
      "name": "Both tsconfigs include shared",
      "description": "Both tsconfig files include the shared/ directory in their include array (or have path aliases that resolve to it)",
      "max_score": 8
    },
    {
      "name": "Union types not enum",
      "description": "String-based categorical types (like BookCategory, OrderStatus) in shared types use union types (type X = 'a' | 'b') rather than TypeScript enum",
      "max_score": 8
    },
    {
      "name": "Concurrent dev scripts",
      "description": "package.json has a dev script that runs both frontend and backend development servers concurrently (using concurrently, npm-run-all, or similar)",
      "max_score": 8
    },
    {
      "name": "Typecheck validates both",
      "description": "A typecheck script exists that validates BOTH client and server tsconfigs (e.g., tsc --noEmit && tsc -p tsconfig.server.json --noEmit)",
      "max_score": 8
    },
    {
      "name": "Path alias for shared",
      "description": "A path alias is configured (e.g., @shared/*) in tsconfig paths for cleaner imports of shared types, and Vite config has matching resolve.alias",
      "max_score": 8
    },
    {
      "name": "API types in shared",
      "description": "API request and response shapes (not just entity types) are defined in the shared types — both the frontend API client and backend routes reference the same type definitions",
      "max_score": 10
    },
    {
      "name": "noUncheckedIndexedAccess",
      "description": "At least one tsconfig has noUncheckedIndexedAccess: true",
      "max_score": 5
    }
  ]
}

evals

tile.json