This document provides a comprehensive overview of DevPockit's architecture, design decisions, and implementation patterns.
- System Overview
- Project Structure
- Component Architecture
- Tool Implementation Pattern
- State Management
- Routing
- Build & Deployment
- Design Decisions
DevPockit is a client-side web application built with Next.js 15 that provides 30+ developer tools. All processing happens in the browser, ensuring privacy and optimal performance.
- Client-Side Only: No backend server required, all tools run in the browser
- Static Export: Can be deployed as static files (GitHub Pages compatible)
- Type-Safe: Full TypeScript implementation with strict mode
- Component-Based: React components with clear separation of concerns
- Modular: Tools are self-contained modules that can be easily added/removed
- Framework: Next.js 15 (App Router)
- Language: TypeScript (strict mode)
- UI Library: React 19
- Styling: Tailwind CSS
- UI Components: Shadcn/ui (Radix UI primitives)
- Code Editor: Monaco Editor
- Package Manager: pnpm
- Testing: Jest + React Testing Library
devpockit/
├── src/
│ ├── app/ # Next.js App Router
│ │ ├── layout.tsx # Root layout with providers
│ │ ├── page.tsx # Home page
│ │ ├── globals.css # Global styles
│ │ └── tools/ # Tool routes
│ │ └── [category]/
│ │ └── [toolId]/
│ │ └── page.tsx
│ ├── components/
│ │ ├── ui/ # Shadcn/ui components
│ │ ├── tools/ # Tool-specific components
│ │ ├── layout/ # Layout components
│ │ │ ├── AppLayout.tsx
│ │ │ ├── AppSidebar.tsx
│ │ │ └── ...
│ │ └── pages/ # Page components
│ ├── libs/ # Core logic and utilities
│ │ ├── tools-data.ts # Tool definitions
│ │ ├── tool-components.ts # Dynamic component loader
│ │ └── [tool-name].ts # Tool-specific logic
│ ├── config/ # Tool configurations
│ │ └── [tool-name]-config.ts
│ ├── hooks/ # Custom React hooks
│ │ ├── useMonacoEditor.ts
│ │ └── useCodeEditorTheme.ts
│ ├── types/ # TypeScript type definitions
│ │ └── tools.ts
│ └── providers/ # React context providers
│ └── ToolStateProvider.tsx
├── public/ # Static assets
├── .github/ # GitHub templates and workflows
├── docs/ # Documentation
└── scripts/ # Build and utility scripts
Next.js App Router directory. Contains:
- Layout: Root layout with theme provider and tool state provider
- Pages: Route pages, including dynamic tool pages
- Global Styles: Tailwind CSS and custom styles
React components organized by purpose:
ui/: Reusable UI components from Shadcn/uitools/: Tool-specific React components (one per tool)layout/: Layout components (sidebar, header, etc.)pages/: Page-level components
Core business logic:
tools-data.ts: Central registry of all tools and categoriestool-components.ts: Dynamic component loader for static export compatibility[tool-name].ts: Pure functions implementing tool logic (no React dependencies)
Tool configuration files:
- Tool-specific options, examples, and settings
- Separated from logic for easier maintenance
Custom React hooks:
- Editor hooks (Monaco Editor integration)
- Theme hooks
- Reusable state management hooks
TypeScript type definitions:
- Shared interfaces and types
- Tool type definitions
React context providers:
- Tool state management
- Theme management (via next-themes)
AppLayout (Root)
├── AppSidebar (Navigation)
├── Header (Top bar with search)
└── ToolPage
└── DynamicToolRenderer
└── [Tool Component]
├── Input Section
├── Settings/Options
└── Output Section
- Purpose: Root layout wrapper
- Responsibilities:
- Provides theme context
- Provides tool state context
- Renders sidebar and main content
- Handles responsive layout
- Purpose: Navigation sidebar
- Responsibilities:
- Displays tool categories
- Tool search functionality
- Mobile-responsive navigation
- Active tool highlighting
- Purpose: Dynamically loads tool components
- Responsibilities:
- Maps tool ID to component name
- Lazy loads tool components
- Handles loading states
- Error boundaries for tools
- Purpose: Individual tool implementations
- Structure:
export function ToolName() { // State management // Event handlers // Tool logic (via libs/) // UI rendering }
- Logic: Pure functions in
src/libs/ - Configuration: Data in
src/config/ - UI: React components in
src/components/tools/ - State: React hooks and context
- Shared UI components in
src/components/ui/ - Common patterns extracted to hooks
- Configuration-driven tool options
Each tool follows a consistent pattern with four main parts:
Pure functions that implement the tool's core functionality:
// src/libs/json-formatter.ts
export function formatJson(input: string, minify: boolean): string {
// Pure function, no React dependencies
// Handles all business logic
// Returns formatted result
}Principles:
- Pure functions (no side effects)
- No React dependencies
- Easy to test
- Reusable across contexts
Configuration data for the tool:
// src/config/json-formatter-config.ts
export const JSON_FORMAT_OPTIONS = {
// Options, examples, defaults
};
export const JSON_EXAMPLES = {
// Example inputs
};Contains:
- Default options
- Example inputs
- Validation rules
- UI configuration
React component that provides the UI:
// src/components/tools/JsonFormatter.tsx
export function JsonFormatter() {
const [input, setInput] = useState('');
const [output, setOutput] = useState('');
const [options, setOptions] = useState(DEFAULT_OPTIONS);
const handleFormat = () => {
const result = formatJson(input, options.minify);
setOutput(result);
};
return (
<div>
{/* Input section */}
{/* Options section */}
{/* Output section */}
</div>
);
}Responsibilities:
- User interface
- State management
- Event handling
- Calls logic functions from
libs/
Register the tool in the central registry:
{
id: 'json-formatter',
name: 'JSON Formatter',
description: 'Format and beautify JSON data',
category: 'formatters',
path: '/tools/formatters/json-formatter',
component: 'JsonFormatter',
// ... other metadata
}Standard tool component follows this structure:
export function ToolName() {
// 1. State declarations
const [input, setInput] = useState('');
const [output, setOutput] = useState('');
const [options, setOptions] = useState(DEFAULT_OPTIONS);
// 2. Event handlers
const handleProcess = () => {
const result = processTool(input, options);
setOutput(result);
};
// 3. UI rendering
return (
<div className="tool-container">
<ToolHeader />
<InputSection />
<OptionsSection />
<OutputSection />
</div>
);
}For static export compatibility, tools are loaded dynamically:
// src/libs/tool-components.ts
export const getToolComponent = async (componentName: string) => {
const componentMap = {
'JsonFormatter': () => import('@/components/tools/JsonFormatter'),
// ... other tools
};
return componentMap[componentName]();
};This allows:
- Code splitting per tool
- Smaller initial bundle
- Static export compatibility
- Lazy loading
Global tool state management via React Context:
// src/providers/ToolStateProvider.tsx
export function ToolStateProvider({ children }) {
const [toolStates, setToolStates] = useState({});
const saveToolState = (toolId: string, state: any) => {
// Save tool state
};
const getToolState = (toolId: string) => {
// Retrieve tool state
};
return (
<ToolStateContext.Provider value={{ ... }}>
{children}
</ToolStateContext.Provider>
);
}Features:
- Persists tool state across navigation
- Per-tool state isolation
- LocalStorage integration (optional)
Most tools use local React state:
- Input values
- Output results
- UI state (expanded/collapsed)
- Options/settings
Managed by next-themes:
- Dark/light mode
- System preference detection
- Persistent theme selection
/ # Home page
/tools # Tools listing
/tools/[category] # Category page
/tools/[category]/[toolId] # Individual tool page
Next.js App Router dynamic routes:
[category]: Tool category (e.g., "formatters", "encoders")[toolId]: Specific tool ID (e.g., "json-formatter")
// src/app/tools/[category]/[toolId]/page.tsx
export default async function ToolPage({ params }) {
const { category, toolId } = await params;
const tool = getToolById(toolId);
return <AppLayout><ToolPageContent tool={tool} /></AppLayout>;
}- Type Checking: TypeScript compilation
- Linting: ESLint validation
- Testing: Jest test suite
- Build: Next.js production build
- Export: Static file generation (if needed)
For static hosting (GitHub Pages, etc.):
// next.config.js
module.exports = {
output: 'export',
trailingSlash: true,
};Considerations:
- All routes must be statically generable
- Dynamic imports for code splitting
- No server-side features
.next/ # Next.js build output
out/ # Static export (if enabled)
The application can be deployed as:
- Static Site: Export to
out/directory - Node.js App: Run
next startwith.next/directory - Serverless: Vercel, Netlify, etc.
- Privacy: No data sent to servers
- Performance: Instant processing
- Cost: No server infrastructure needed
- Reliability: Works offline (with service workers)
- Modern: Latest Next.js features
- TypeScript: Excellent TypeScript support
- Static Export: Can generate static sites
- Code Splitting: Automatic route-based splitting
- Performance: Optimized out of the box
- Accessible: Built on Radix UI
- Customizable: Copy components, not install
- Type-Safe: Full TypeScript support
- Modern: Uses latest React patterns
- Testability: Pure functions are easy to test
- Reusability: Logic can be used outside React
- Maintainability: Clear separation of concerns
- Performance: Logic can be optimized independently
- Code Splitting: Smaller initial bundle
- Static Export: Required for static site generation
- Performance: Load tools on demand
- Scalability: Easy to add new tools
- Route-based splitting (automatic)
- Component-based splitting (dynamic imports)
- Tool-level splitting (each tool is separate chunk)
- Lazy Loading: Tools loaded on demand
- Memoization: React.memo for expensive components
- Virtual Scrolling: For long lists (if needed)
- Image Optimization: Next.js Image component
- Tree shaking enabled
- Minimal dependencies
- Shared code extracted
- Tool code split per tool
- Input Validation: All inputs validated
- XSS Prevention: React's built-in escaping
- No Eval: No use of eval() or similar
- Content Security Policy: Can be configured
- No Tracking: No analytics or tracking
- No Data Collection: All processing local
- No External Requests: Tools don't call APIs (except IP checker)
- Service Workers: Offline support
- IndexedDB: Local data persistence
- Web Workers: Heavy computation off main thread
- Progressive Web App: PWA capabilities
- Current architecture supports 100+ tools
- Dynamic loading ensures performance
- Modular design allows easy extension
For implementation details, see CONTRIBUTING.md. For development setup, see CONTRIBUTING.md.