Owner: Engineering Team | Last Updated: 2026-01-30 | Status: Current
The WWAI web app uses a component architecture built on React with NextUI v2 and TipTap for rich text editing. Components are organized under components/ with shared TypeScript interfaces in types/index.ts. For the full web app overview, see Web App Overview.
Used for readability and purpose dropdown items:
export interface HumanizerSelectOptions {
id: number
value?: string // API value string (e.g., "University", "General Writing")
icon: string // Emoji icon (e.g., "🎓 ")
name: string // Translated display name
premium?: boolean // Whether option requires paid plan
}
All 9 external detector scores:
export interface StatusProps {
is_scored: string | boolean | null
total: string | boolean | null
gptZero: string | boolean | null
copyLeaks: string | boolean | null
zeroGPT: string | boolean | null
crossPlag: string | boolean | null
sapling: string | boolean | null
writer: string | boolean | null
contScale: string | boolean | null
originality: string | boolean | null
turnitin: string | boolean | null
}
Scores are 0-1 decimals. Display: (score * 100).toFixed(0)%. Values of false or null mean the detector did not return a result.
export interface Version {
id: string
input_text: string
output_text: string
like: null | boolean // User rating: null=unrated, true=liked, false=disliked
action: string
created_at: string
updated_at: string
word_count: number
created_at_day: string
history: number // Parent document ID
user_id: number
draft_list: DraftListItem[]
}
export interface DraftListItem {
id: number
output_text: string
created_at: string
version: number // Parent version ID
}
export interface DocumentListItem {
id: number
title: string
user: number
version_count: number
version_list: Version[]
created_at: string
updated_at: string
}
export interface PurposeCategory {
id: number
name: string
icon: string
value: string // API value (e.g., "General Writing")
}
export interface ReadabilityCategory {
id: number
icon: string
name: string
}
export interface UserProfileData {
first_name: string
last_name: string
avatar: File | null | string
}
export interface UserPasswordData {
old_password: string
new_password: string
confirm_password: string
}
From hooks/useWordsUsage.tsx — tracks credit/word usage for the current user:
const {
remainingWords, // number — remaining word credits
remainingReferWords, // number — remaining referral bonus words
totalWords, // number | "Unlimited" — monthly word limit
totalWordsPerRequest, // number — per-request word cap
totalReferWords, // number — total referral bonus words
percent, // number — usage percentage (0-100)
percentRefer, // number — referral usage percentage
referralPercent, // number — referral progress percentage
referralMaxWords, // number — referral tier cap (10K/20K/50K)
expiryDate, // string — formatted referral expiry date
nextBillingDate, // string — next billing date
totalWordUsedCurrentPeriod, // number — words used this period
nextRenewalDate, // string — formatted renewal date
unpauseDate, // string — subscription unpause date
} = useWordsUsage()
Plan-aware logic: When plan === 'unlimited', totalWords returns the string "Unlimited" and percent is always 100.
From hooks/useDocumentActions.ts — CRUD operations for documents (search, pin/unpin, delete, rename, pagination).
From hooks/use-countdown.ts — countdown timer utility hook.
From hooks/use-on-click-outside.ts — detects clicks outside a ref element.
| Library | Version | Usage |
|---|---|---|
| NextUI v2 | @nextui-org/react |
Accordion, Switch, Modal, Tooltip, Tabs |
| TipTap | 3.10.7 | Rich text editor (HumanizerTextEditor, TiptapEditor) |
| Lucide React | — | Icons (Brain, Shield, Check, Lock, Trash, etc.) |
| Framer Motion | — | Animations (button states, result reveal) |
| Headless UI | @headlessui/react |
Tab, TabGroup, TabList (strength selector) |
| React Tooltip | — | Hover tooltips on buttons and labels |
| React Toastify | — | Toast notifications (errors, success) |
components/
├── partials/
│ ├── humanizer/ # Core humanizer feature
│ │ ├── Humanizer.tsx # Main container (951 lines)
│ │ ├── HumanizeButton.tsx
│ │ ├── DetectorButton.tsx
│ │ ├── DetectorResult.tsx
│ │ ├── DetectorScorecard.tsx
│ │ ├── DetectorDynamicMessage.tsx
│ │ ├── HumanizerContext.tsx
│ │ ├── HumanizerSelect.tsx
│ │ ├── HumanizerLayout.tsx
│ │ ├── HumanizerBanner.tsx
│ │ ├── HumanizerPreloader.tsx
│ │ ├── HumanizerFeedbackModal.tsx
│ │ ├── HumanizerHelpModal.tsx
│ │ ├── HumanizerHistoryModal.tsx
│ │ ├── TiptapEditor.tsx
│ │ ├── TiptapToolbar.tsx
│ │ ├── drafts/
│ │ │ ├── DesktopDrafts.tsx
│ │ │ └── MobileDrafts.tsx
│ │ └── humanizer-history/
│ │ ├── HumanizerHistory.tsx
│ │ ├── HumanizerHistoryCard.tsx
│ │ └── HumanizerHistoryFooter.tsx
│ ├── detector/ # Standalone detector
│ │ └── DetectorCircleChart.tsx
│ ├── HumanizerTextEditor.tsx
│ ├── RequestLimit.tsx # Plan/credit limit warnings
│ └── UpgradeModal.tsx # Upgrade plan modal
├── ui/ # Shared UI primitives
└── layout/ # Layout components
| Date | Author | Change |
|---|---|---|
| 2026-01-30 | Admin | Initial creation |
| 2026-01-30 | Docs team | Rewritten with real code: all TypeScript interfaces from types/index.ts, useWordsUsage hook, component directory structure, UI library inventory |
Prev: Web App - State Management (Redux) | Next: Web App - API Integration | Up: WalterWrites