Create a new React + TypeScript project using Vite, install TailwindCSS and set up a basic folder structure for src/components, src/pages, src/hooks, src/services, and src/styles. Configure Tailwind (with JIT), add postcss.config.js, and add linting (ESLint + Prettier) with recommended rules. Output the exact commands to run and a minimal tailwind.config.cjs extension showing custom colors tokens: primary, accent, bg, muted. Also include a README with run/test/build commands
I'll help you set up a complete React + TypeScript project with Vite, TailwindCSS, and all the tooling you requested. Here are the exact commands and configurations:
# Create Vite project with React + TypeScript
npm create vite@latest my-react-app -- --template react-ts
cd my-react-app
# Install TailwindCSS and dependencies
npm install -D tailwindcss postcss autoprefixer
npm install -D @tailwindcss/forms @tailwindcss/typography
# Install ESLint and Prettier
npm install -D eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser
npm install -D prettier eslint-config-prettier eslint-plugin-prettier
npm install -D eslint-plugin-react eslint-plugin-react-hooks
# Initialize Tailwind
npx tailwindcss init -p
# Create the folder structure
mkdir -p src/components src/pages src/hooks src/services src/styles
tailwind.config.cjs
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {
colors: {
primary: {
50: '#eff6ff',
100: '#dbeafe',
200: '#bfdbfe',
300: '#93c5fd',
400: '#60a5fa',
500: '#3b82f6',
600: '#2563eb',
700: '#1d4ed8',
800: '#1e40af',
900: '#1e3a8a',
},
accent: {
50: '#fdf4ff',
100: '#fae8ff',
200: '#f5d0fe',
300: '#f0abfc',
400: '#e879f9',
500: '#d946ef',
600: '#c026d3',
700: '#a21caf',
800: '#86198f',
900: '#701a75',
},
bg: {
50: '#f8fafc',
100: '#f1f5f9',
200: '#e2e8f0',
300: '#cbd5e1',
400: '#94a3b8',
500: '#64748b',
600: '#475569',
700: '#334155',
800: '#1e293b',
900: '#0f172a',
},
muted: {
50: '#f9fafb',
100: '#f3f4f6',
200: '#e5e7eb',
300: '#d1d5db',
400: '#9ca3af',
500: '#6b7280',
600: '#4b5563',
700: '#374151',
800: '#1f2937',
900: '#111827',
}
}
},
},
plugins: [
require('@tailwindcss/forms'),
require('@tailwindcss/typography'),
],
}
postcss.config.js
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
eslint.config.js
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from '@typescript-eslint/eslint-plugin'
import tsparser from '@typescript-eslint/parser'
import prettier from 'eslint-plugin-prettier'
export default [
{
ignores: ['dist'],
},
{
files: ['**/*.{ts,tsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
parser: tsparser,
parserOptions: {
ecmaVersion: 'latest',
ecmaFeatures: { jsx: true },
sourceType: 'module',
},
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
'@typescript-eslint': tseslint,
prettier: prettier,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
'@typescript-eslint/no-unused-vars': ['error'],
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'warn',
'prettier/prettier': 'error',
},
},
]
.prettierrc
{
"semi": false,
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 80,
"tabWidth": 2,
"useTabs": false
}
src/styles/globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
html {
font-family: system-ui, sans-serif;
}
}
@layer components {
.btn-primary {
@apply bg-primary-600 hover:bg-primary-700 text-white font-medium py-2 px-4 rounded-lg transition-colors;
}
.btn-secondary {
@apply bg-accent-600 hover:bg-accent-700 text-white font-medium py-2 px-4 rounded-lg transition-colors;
}
}
src/main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import './styles/globals.css'
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)
src/App.tsx
import React from 'react'
function App() {
return (
<div className="min-h-screen bg-bg-50">
<div className="container mx-auto px-4 py-8">
<h1 className="text-4xl font-bold text-primary-600 mb-4">
Welcome to Your React App
</h1>
<p className="text-muted-600 mb-6">
Built with Vite, TypeScript, and TailwindCSS
</p>
<div className="space-x-4">
<button className="btn-primary">Primary Button</button>
<button className="btn-secondary">Secondary Button</button>
</div>
</div>
</div>
)
}
export default App
Add these scripts to your package.json
:
{
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"lint:fix": "eslint . --ext ts,tsx --fix",
"format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,css,md}\"",
"preview": "vite preview",
"test": "echo \"No tests specified\" && exit 0"
}
}
# React + TypeScript + Vite Project
A modern React application built with TypeScript, Vite, and TailwindCSS.
## Features
- ⚡️ Vite for fast development and building
- 🔷 TypeScript for type safety
- 🎨 TailwindCSS with custom color tokens
- 📁 Organized folder structure
- 🔍 ESLint + Prettier for code quality
- 🎯 Custom Tailwind components
## Getting Started
### Prerequisites
- Node.js (version 16 or higher)
- npm or yarn
### Installation
1. Clone the repository
2. Install dependencies:
```bash
npm install
Start the development server:
npm run dev
The app will be available at http://localhost:5173
Build for production:
npm run build
Run tests:
npm run test
Check for linting errors:
npm run lint
Fix linting errors:
npm run lint:fix
Format code:
npm run format
Preview the production build locally:
npm run preview
src/
├── components/ # Reusable UI components
├── pages/ # Page components
├── hooks/ # Custom React hooks
├── services/ # API calls and external services
├── styles/ # Global styles and Tailwind config
├── App.tsx # Main app component
└── main.tsx # Entry point
The project includes custom Tailwind color tokens:
primary
- Main brand color (blue variants)accent
- Secondary brand color (purple variants)bg
- Background colors (slate variants)muted
- Muted text colors (gray variants)Use them like: bg-primary-600
, text-accent-500
, etc.
npm run dev
- Start development servernpm run build
- Build for productionnpm run preview
- Preview production buildnpm run lint
- Check for linting errorsnpm run lint:fix
- Fix linting errorsnpm run format
- Format code with Prettiernpm run test
- Run tests
## Final Setup Commands
Run these commands in order:
```bash
# 1. Create and setup project
npm create vite@latest my-react-app -- --template react-ts
cd my-react-app
# 2. Install all dependencies
npm install -D tailwindcss postcss autoprefixer @tailwindcss/forms @tailwindcss/typography
npm install -D eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser
npm install -D prettier eslint-config-prettier eslint-plugin-prettier
npm install -D eslint-plugin-react eslint-plugin-react-hooks
# 3. Initialize Tailwind
npx tailwindcss init -p
# 4. Create folder structure
mkdir -p src/components src/pages src/hooks src/services src/styles
# 5. Replace the generated config files with the ones above
# 6. Update src/main.tsx and src/App.tsx with the code above
# 7. Create src/styles/globals.css with the Tailwind imports
# 8. Start development
npm run dev
Your project will be ready with a complete development environment including hot reloading, TypeScript support, TailwindCSS with JIT compilation, and proper linting/formatting setup!
Generate a minimal design system for this app: 5-color palette (primary, accent, success, warning, neutral), font stack (Inter fallback), type scale (xs, sm, base, lg, xl, 2xl), and spacing scale. Produce a Tailwind config extension JSON to add --radius, --card-padding and the tokens. Add suggested CSS variables and a small theme file.
I'll create a minimal design system with semantic color tokens, typography, and spacing scales. Here's the complete configuration:
Color Palette:
#3B82F6
) - Main brand actions#8B5CF6
) - Secondary highlights#10B981
) - Positive states#F59E0B
) - Caution states#6B7280
) - Text and backgroundstailwind.config.cjs
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {
colors: {
primary: {
50: '#eff6ff',
100: '#dbeafe',
200: '#bfdbfe',
300: '#93c5fd',
400: '#60a5fa',
500: '#3b82f6',
600: '#2563eb',
700: '#1d4ed8',
800: '#1e40af',
900: '#1e3a8a',
},
accent: {
50: '#f5f3ff',
100: '#ede9fe',
200: '#ddd6fe',
300: '#c4b5fd',
400: '#a78bfa',
500: '#8b5cf6',
600: '#7c3aed',
700: '#6d28d9',
800: '#5b21b6',
900: '#4c1d95',
},
success: {
50: '#ecfdf5',
100: '#d1fae5',
200: '#a7f3d0',
300: '#6ee7b7',
400: '#34d399',
500: '#10b981',
600: '#059669',
700: '#047857',
800: '#065f46',
900: '#064e3b',
},
warning: {
50: '#fffbeb',
100: '#fef3c7',
200: '#fde68a',
300: '#fcd34d',
400: '#fbbf24',
500: '#f59e0b',
600: '#d97706',
700: '#b45309',
800: '#92400e',
900: '#78350f',
},
neutral: {
50: '#f9fafb',
100: '#f3f4f6',
200: '#e5e7eb',
300: '#d1d5db',
400: '#9ca3af',
500: '#6b7280',
600: '#4b5563',
700: '#374151',
800: '#1f2937',
900: '#111827',
}
},
fontFamily: {
sans: ['Inter', 'system-ui', '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'sans-serif'],
},
fontSize: {
xs: ['0.75rem', { lineHeight: '1rem' }],
sm: ['0.875rem', { lineHeight: '1.25rem' }],
base: ['1rem', { lineHeight: '1.5rem' }],
lg: ['1.125rem', { lineHeight: '1.75rem' }],
xl: ['1.25rem', { lineHeight: '1.75rem' }],
'2xl': ['1.5rem', { lineHeight: '2rem' }],
},
spacing: {
'0.5': '0.125rem',
'1': '0.25rem',
'1.5': '0.375rem',
'2': '0.5rem',
'2.5': '0.625rem',
'3': '0.75rem',
'3.5': '0.875rem',
'4': '1rem',
'5': '1.25rem',
'6': '1.5rem',
'7': '1.75rem',
'8': '2rem',
'10': '2.5rem',
'12': '3rem',
'16': '4rem',
'20': '5rem',
'24': '6rem',
},
borderRadius: {
'sm': 'var(--radius-sm)',
'DEFAULT': 'var(--radius)',
'md': 'var(--radius-md)',
'lg': 'var(--radius-lg)',
'xl': 'var(--radius-xl)',
}
},
},
plugins: [],
}
src/styles/design-tokens.css
:root {
/* Border Radius */
--radius-sm: 0.25rem;
--radius: 0.5rem;
--radius-md: 0.75rem;
--radius-lg: 1rem;
--radius-xl: 1.5rem;
/* Card Padding */
--card-padding: 1.5rem;
--card-padding-sm: 1rem;
--card-padding-lg: 2rem;
/* Shadows */
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
--shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
/* Typography */
--font-weight-normal: 400;
--font-weight-medium: 500;
--font-weight-semibold: 600;
--font-weight-bold: 700;
/* Transitions */
--transition-fast: 150ms ease-in-out;
--transition-normal: 250ms ease-in-out;
--transition-slow: 350ms ease-in-out;
}
src/styles/theme.css
@import './design-tokens.css';
/* Component Base Styles */
.card {
@apply bg-white rounded-lg shadow-sm border border-neutral-200;
padding: var(--card-padding);
}
.card-sm {
padding: var(--card-padding-sm);
}
.card-lg {
padding: var(--card-padding-lg);
}
/* Button Variants */
.btn {
@apply inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors;
@apply focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2;
@apply disabled:pointer-events-none disabled:opacity-50;
padding: 0.5rem 1rem;
transition: var(--transition-fast);
}
.btn-primary {
@apply bg-primary-600 text-white hover:bg-primary-700 focus-visible:ring-primary-500;
}
.btn-accent {
@apply bg-accent-600 text-white hover:bg-accent-700 focus-visible:ring-accent-500;
}
.btn-success {
@apply bg-success-600 text-white hover:bg-success-700 focus-visible:ring-success-500;
}
.btn-warning {
@apply bg-warning-600 text-white hover:bg-warning-700 focus-visible:ring-warning-500;
}
.btn-outline {
@apply border border-neutral-300 bg-white text-neutral-700 hover:bg-neutral-50 focus-visible:ring-neutral-500;
}
.btn-ghost {
@apply text-neutral-700 hover:bg-neutral-100 focus-visible:ring-neutral-500;
}
/* Input Styles */
.input {
@apply flex w-full rounded-md border border-neutral-300 bg-white px-3 py-2 text-sm;
@apply placeholder:text-neutral-400 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent;
@apply disabled:cursor-not-allowed disabled:opacity-50;
}
/* Status Indicators */
.status-success {
@apply bg-success-50 text-success-700 border-success-200;
}
.status-warning {
@apply bg-warning-50 text-warning-700 border-warning-200;
}
.status-error {
@apply bg-red-50 text-red-700 border-red-200;
}
/* Typography Utilities */
.text-heading {
@apply font-semibold text-neutral-900;
}
.text-body {
@apply text-neutral-700;
}
.text-muted {
@apply text-neutral-500;
}
.text-caption {
@apply text-sm text-neutral-400;
}
Component Example:
// Example Card Component
export function ExampleCard() {
return (
<div className="card">
<h3 className="text-lg text-heading mb-2">Card Title</h3>
<p className="text-body mb-4">Card content goes here.</p>
<div className="flex gap-2">
<button className="btn btn-primary">Primary</button>
<button className="btn btn-outline">Secondary</button>
</div>
</div>
)
}
Update src/styles/globals.css:
@tailwind base;
@tailwind components;
@tailwind utilities;
@import './theme.css';
@layer base {
html {
font-family: Inter, system-ui, sans-serif;
}
body {
@apply bg-neutral-50 text-neutral-900;
}
}
This design system provides a complete foundation with semantic color tokens, consistent spacing, typography scales, and reusable component classes. The CSS variables make it easy to maintain consistent styling across your application while the Tailwind integration keeps everything type-safe and performant.
Build a React AppShell component using Tailwind that includes: top nav with logo (left), nav links: Home, Upload, History, Docs, and a user avatar (right). On small screens show a hamburger that toggles a slide-over menu. Provide accessible markup (nav landmark, aria attributes). Return JSX + minimal Tailwind classes and comments where to inject routes (react-router or wouter).
Build a React AppShell component using Tailwind that includes: top nav with logo (left), nav links: Home, Upload, History, Docs, and a user avatar (right). On small screens show a hamburger that toggles a slide-over menu. Provide accessible markup (nav landmark, aria attributes). Return JSX + minimal Tailwind classes and comments where to inject routes (react-router or wouter).
Build a FileUpload React component with drag-and-drop and fallback file input. It should accept .pdf,.docx,.txt and show: filename, size, page count (if PDF), and parsed text preview (first 300 chars). Show validation errors (size limit 10MB, unsupported type). After upload show a “Parse & Simplify” primary button. Include skeleton loader while parsing. Expose prop onSubmit(formData) that calls backend POST /api/parse with multipart/form-data. Provide suggested Tailwind classes and aria attributes.
Create a DocumentResults page that consumes the /api/simplify response (sample below). Show: (A) top summary card (short bullet points), (B) side-by-side expander with original text (left) and simplified text (right) with a toggle to switch to single-column on mobile, (C) tag bar showing detected tags: Obligation, Risk, Deadline, Payment. Each clause should be an accordion row with “Show original”, “Explain clause” and “Mark as important” actions. Return JSX and sample Tailwind layout.
Implement a DocChat component: chat bubbles for user questions and AI answers. When AI answers, show a small “Sources” section below each answer with clause IDs and a “Jump to clause” link that scrolls the clause into view in the DocumentResults page and briefly highlights it. Include a compact input box that supports pressing Enter to send and shows streaming / typing indicator while waiting for the answer.
Build a FilterBar and ClauseHighlighter UI. FilterBar should allow toggling tags (Obligation, Risk, Deadline) and risk severity (High, Medium, Low). ClauseHighlighter should color-code clauses with thin left borders and small badges. Add a legend and tooltip explaining each tag.
Create a Dashboard/History page listing uploaded documents. Each row shows: document name, upload date, summarized bullets, and actions: View, Export Simplified PDF, Delete. Add search and sort by date, and pagination (or infinite scroll for >10 items). Provide UI skeleton for empty state “No documents yet – Upload your first contract”.
Add an ExportMenu component to DocumentResults with options: “Download Simplified PDF”, “Download Original PDF”, “Copy shareable link (7 days)”. Show toast confirmations for success. The share link should be disabled if the user is not logged in (show tooltip “Sign in to create share link”).
Audit the UI for mobile-first responsiveness. Provide responsive utility classes for breakpoints: sm:640px, md:768px, lg:1024px. For DocumentResults, switch from 2-column to single column under md. For nav, use bottom fixed bar on mobile if screen height < 700px. Return suggested CSS/Tailwind layout changes.
Add loading skeletons for: file parsing, summary card, clause list, and chat streaming. Implement global error banner component that shows friendly messages and a “Retry” button for failed API calls. Provide ARIA live region for error announcements.
Review UI components and add accessibility features: keyboard focus states, appropriate aria-* attributes for accordions, role=dialog for modals, labels for inputs. Add i18n scaffolding (e.g., react-i18next) and put all user-visible strings in a translation JSON (English). List which strings need translation (hero copy, CTA, error messages, tag labels).
Add micro-interactions using Framer Motion for these: hover on clause rows (slight lift), expand/collapse accordion with smooth height animation, toast slide-in/out, and fade for skeleton-to-content. Keep animations subtle and short (≤250ms). Provide sample Framer Motion usage for one component.
Scaffold tests: one unit test for FileUpload (shows error on big file), one integration test for upload → parse → results (mock API), and one Cypress E2E test for a demo flow: upload sample contract → view summary → ask question → get answer. Produce a demo checklist to run before presenting.