feat: initial project setup with Next.js 16 and Tailwind CSS 4

- Initialize Next.js 16 with React 19 and TypeScript 5
- Configure Tailwind CSS 4 with PostCSS
- Set up static export for Docker deployment
- Install figlet.js for ASCII art rendering
- Add fuse.js for fuzzy search functionality
- Create project structure (app/, components/, lib/, types/)
- Add comprehensive README and IMPLEMENTATION_PLAN
- Configure ESLint and TypeScript
- Set up pnpm package management

Tech stack matches units-ui project for consistency.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-09 12:07:23 +01:00
commit f120a8b3d0
13 changed files with 4897 additions and 0 deletions

26
.dockerignore Normal file
View File

@@ -0,0 +1,26 @@
# dependencies
node_modules
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# build artifacts
.next
out
build
dist
# development
.git
.gitignore
.env*.local
# misc
README.md
.DS_Store
*.pem
# IDE
.vscode
.idea

3
.eslintrc.json Normal file
View File

@@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}

44
.gitignore vendored Normal file
View File

@@ -0,0 +1,44 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# env files
.env*.local
.env
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
# Figlet fonts (will be cloned separately)
/public/fonts/figlet-fonts

443
IMPLEMENTATION_PLAN.md Normal file
View File

@@ -0,0 +1,443 @@
# Figlet UI - Implementation Plan
## Project Overview
A modern, feature-rich web UI for generating ASCII art text using figlet.js with 700+ fonts from xero/figlet-fonts. This project aims to be the best figlet web interface, significantly improving upon existing solutions like TAAG.
**Tech Stack:**
- Next.js 16 with static export
- React 19
- TypeScript 5
- Tailwind CSS 4
- figlet.js for ASCII art rendering
- Fuse.js for fuzzy search
- Lucide React for icons
- Docker deployment with nginx
## Key Features & Improvements Over TAAG
### Superior Font Management
- **700+ fonts** from xero collection (vs ~300 on TAAG)
- Visual font preview cards
- Fuzzy search with intelligent matching
- Font categories and tags (3D, block, script, retro, etc.)
- Favorites system with localStorage
- Recently used fonts
- Random font discovery
### Better Export & Sharing
- One-click copy to clipboard
- Export as PNG/SVG images
- Export as HTML with styling
- Shareable URLs (text + font encoded)
- Download as .txt file
- Generate code snippets (JS, Python, Bash)
- Markdown-ready code blocks
### Enhanced UX
- Live preview as you type
- Debounced updates for performance
- Dark/light mode toggle
- Keyboard shortcuts (/, Esc, Ctrl+C, Ctrl+K)
- Command palette for quick actions
- Mobile-optimized layout
- Smooth animations and transitions
- Character counter
- Width constraint preview
### Modern UI Design
- Clean, minimalist interface
- Responsive layout (mobile-first)
- Better typography and spacing
- Smooth transitions
- Loading states
- Empty states
- Error handling
## Implementation Phases
### Phase 1: Project Setup ✅
- [x] Initialize git repository
- [x] Add GitHub remote origin
- [x] Create Next.js 16 project with TypeScript
- [x] Configure Tailwind CSS 4
- [x] Install dependencies (figlet, fuse.js, lucide-react)
- [x] Set up project structure (app/, components/, lib/, types/)
- [x] Configure static export
- [x] Create initial commit
### Phase 2: Font Management System
- [ ] Clone xero/figlet-fonts into public/fonts/
- [ ] Create font loading service
- [ ] List all available fonts
- [ ] Load fonts on-demand (lazy loading)
- [ ] Cache loaded fonts in memory
- [ ] Build font metadata system
- [ ] Extract font characteristics (height, width, style)
- [ ] Categorize fonts by style tags
- [ ] Generate font preview data
- [ ] Create font types and interfaces
### Phase 3: Core Figlet Engine
- [ ] Implement figlet.js wrapper service
- [ ] Initialize figlet with custom fonts
- [ ] Handle font loading errors
- [ ] Provide type-safe API
- [ ] Create real-time rendering hook
- [ ] Debounced text input (300ms)
- [ ] Handle multi-line text
- [ ] Optimize re-renders
- [ ] Add text validation and sanitization
- [ ] Implement character width calculations
### Phase 4: Main UI Components
- [ ] Build main converter interface
- [ ] Text input area (textarea)
- [ ] Live preview display (pre/code block)
- [ ] Font selector component
- [ ] Options panel (alignment, width, etc.)
- [ ] Create font selector with search
- [ ] Visual font preview cards
- [ ] Fuzzy search implementation
- [ ] Category filters
- [ ] Sort options (name, recent, popular)
- [ ] Build responsive layout
- [ ] Desktop: side-by-side layout
- [ ] Mobile: stacked layout
- [ ] Tablet: adaptive layout
### Phase 5: Search & Filters
- [ ] Implement Fuse.js integration
- [ ] Configure fuzzy matching
- [ ] Index font names and metadata
- [ ] Real-time search results
- [ ] Add category filtering
- [ ] Style tags (3D, block, script, etc.)
- [ ] Font size filters
- [ ] System filters (metric/imperial)
- [ ] Create search UI
- [ ] Search input with icon
- [ ] Keyboard shortcut (/) to focus
- [ ] Clear button
- [ ] Results count
### Phase 6: Export & Sharing
- [ ] Copy to clipboard functionality
- [ ] One-click copy button
- [ ] Success feedback
- [ ] Clipboard API with fallback
- [ ] Export as image (PNG/SVG)
- [ ] Canvas rendering for PNG
- [ ] SVG text rendering
- [ ] Download with proper filename
- [ ] Shareable URLs
- [ ] Encode text + font in URL params
- [ ] Base64 compression for long text
- [ ] Auto-load from URL on page load
- [ ] Code snippet generation
- [ ] JavaScript/Node.js example
- [ ] Python example
- [ ] Bash/CLI command
- [ ] Copy individual snippets
### Phase 7: User Preferences & History
- [ ] Favorites system
- [ ] Mark fonts as favorite (heart icon)
- [ ] Save to localStorage
- [ ] Quick access to favorites
- [ ] Favorites filter
- [ ] Recent fonts
- [ ] Track last 10 used fonts
- [ ] Save to localStorage
- [ ] Display in font selector
- [ ] Conversion history
- [ ] Save recent conversions
- [ ] History panel/sidebar
- [ ] Re-apply previous conversion
- [ ] Clear history
### Phase 8: Keyboard Shortcuts & Command Palette
- [ ] Implement keyboard shortcuts
- [ ] `/` - Focus search
- [ ] `Esc` - Clear/close
- [ ] `Ctrl/Cmd + C` - Copy result
- [ ] `Ctrl/Cmd + K` - Open command palette
- [ ] `Ctrl/Cmd + D` - Toggle dark mode
- [ ] `Arrow keys` - Navigate fonts
- [ ] Build command palette
- [ ] Search commands
- [ ] Quick actions
- [ ] Recent commands
- [ ] Keyboard hints
### Phase 9: Dark Mode & Theming
- [ ] Implement theme system
- [ ] Light/dark mode toggle
- [ ] Save preference to localStorage
- [ ] System preference detection
- [ ] Smooth theme transitions
- [ ] Update color variables
- [ ] Dark mode color palette
- [ ] Ensure WCAG contrast ratios
- [ ] Theme-aware components
### Phase 10: Mobile Optimization
- [ ] Responsive breakpoints
- [ ] Mobile (< 640px)
- [ ] Tablet (640px - 1024px)
- [ ] Desktop (> 1024px)
- [ ] Touch-friendly UI
- [ ] Large tap targets (44px min)
- [ ] Swipe gestures (optional)
- [ ] Mobile font selector (bottom sheet)
- [ ] Performance on mobile
- [ ] Lazy load fonts
- [ ] Optimize image exports
- [ ] Reduce bundle size
### Phase 11: Advanced Features
- [ ] Font comparison mode
- [ ] Side-by-side preview
- [ ] Compare 2-4 fonts
- [ ] Toggle comparison view
- [ ] Random font generator
- [ ] Shuffle button
- [ ] Exclude recently used
- [ ] Lock text while changing font
- [ ] Text alignment options
- [ ] Left, center, right
- [ ] Custom width constraints
- [ ] Auto-fit to viewport
- [ ] Multi-line text support
- [ ] Preserve line breaks
- [ ] Line-by-line rendering
- [ ] Vertical spacing options
### Phase 12: Performance Optimization
- [ ] Web Workers for rendering
- [ ] Offload figlet rendering
- [ ] Non-blocking UI updates
- [ ] Progress indicators
- [ ] Lazy loading
- [ ] Font files on-demand
- [ ] Virtual scrolling for font list
- [ ] Intersection Observer for previews
- [ ] Bundle optimization
- [ ] Code splitting
- [ ] Tree shaking
- [ ] Dynamic imports
- [ ] Minification
### Phase 13: Accessibility & Polish
- [ ] WCAG 2.1 AA compliance
- [ ] Keyboard navigation
- [ ] Screen reader support
- [ ] ARIA labels and roles
- [ ] Focus indicators
- [ ] Color contrast
- [ ] Error handling
- [ ] Font load failures
- [ ] Network errors
- [ ] Invalid input handling
- [ ] User-friendly messages
- [ ] Loading states
- [ ] Skeleton screens
- [ ] Progress indicators
- [ ] Smooth transitions
- [ ] Empty states
- [ ] No search results
- [ ] No favorites yet
- [ ] No history
### Phase 14: Docker Deployment
- [ ] Create multi-stage Dockerfile
- [ ] Stage 1: Dependencies (node:22-alpine)
- [ ] Stage 2: Builder (pnpm build)
- [ ] Stage 3: Runner (nginx:alpine)
- [ ] Configure nginx.conf
- [ ] Static file serving
- [ ] Gzip compression
- [ ] Cache headers
- [ ] Security headers
- [ ] Add health check
- [ ] Create .dockerignore
- [ ] Build and test image
- [ ] Document deployment
### Phase 15: SEO & Meta Tags
- [ ] Add comprehensive metadata
- [ ] Title, description, keywords
- [ ] OpenGraph tags
- [ ] Twitter card tags
- [ ] Favicon and app icons
- [ ] Generate sitemap
- [ ] Add robots.txt
- [ ] Structured data (Schema.org)
- [ ] Performance optimization
- [ ] Lighthouse audit
- [ ] Core Web Vitals
- [ ] Image optimization
## Technical Architecture
### Component Structure
```
components/
├── converter/
│ ├── TextInput.tsx # Main text input
│ ├── FontPreview.tsx # ASCII art preview display
│ ├── FontSelector.tsx # Font selection with search
│ ├── FontCard.tsx # Individual font preview card
│ ├── OptionsPanel.tsx # Conversion options
│ └── ExportButtons.tsx # Export/copy actions
├── search/
│ ├── FuzzySearch.tsx # Search with Fuse.js
│ ├── SearchInput.tsx # Search input component
│ └── FilterPanel.tsx # Category/tag filters
├── ui/
│ ├── Button.tsx # Reusable button
│ ├── Input.tsx # Reusable input
│ ├── Card.tsx # Card container
│ ├── Badge.tsx # Tag/badge
│ ├── Tabs.tsx # Tab navigation
│ ├── Dialog.tsx # Modal dialog
│ └── CommandPalette.tsx # Keyboard command UI
└── layout/
├── Header.tsx # App header
├── Footer.tsx # App footer
└── ThemeToggle.tsx # Dark mode switch
```
### Service Layer
```
lib/
├── figlet/
│ ├── figletService.ts # Figlet.js wrapper
│ ├── fontLoader.ts # Font loading logic
│ ├── fontMetadata.ts # Font info/categorization
│ └── fontCache.ts # In-memory font cache
├── search/
│ ├── fuzzySearch.ts # Fuse.js integration
│ └── searchConfig.ts # Search configuration
├── export/
│ ├── clipboard.ts # Clipboard operations
│ ├── imageExport.ts # PNG/SVG generation
│ ├── codeGenerator.ts # Code snippet generation
│ └── urlSharing.ts # URL encoding/decoding
├── storage/
│ ├── favorites.ts # Favorites management
│ ├── history.ts # Conversion history
│ └── preferences.ts # User preferences
└── utils/
├── cn.ts # clsx + tailwind-merge
├── debounce.ts # Debounce utility
└── validation.ts # Input validation
```
### Type Definitions
```typescript
// Font metadata
interface FigletFont {
name: string;
path: string;
style: FontStyle[];
height: number;
width: number;
preview?: string;
}
type FontStyle = '3d' | 'block' | 'script' | 'retro' | 'small' | 'banner' | 'decorative';
// Conversion settings
interface ConversionOptions {
font: string;
text: string;
horizontalLayout?: 'default' | 'fitted' | 'full';
verticalLayout?: 'default' | 'fitted' | 'full';
width?: number;
whitespaceBreak?: boolean;
}
// Export format
type ExportFormat = 'text' | 'png' | 'svg' | 'html' | 'code';
// User preferences
interface UserPreferences {
theme: 'light' | 'dark' | 'system';
defaultFont: string;
recentFonts: string[];
favorites: string[];
history: ConversionRecord[];
}
// Conversion history
interface ConversionRecord {
id: string;
timestamp: number;
text: string;
font: string;
result: string;
}
```
## Design System
### Color Palette
```css
/* Light mode */
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
--primary: 0 0% 9%;
--muted: 0 0% 96.1%;
--border: 0 0% 89.8%;
/* Dark mode */
--background: 0 0% 3.9%;
--foreground: 0 0% 98%;
--primary: 0 0% 98%;
--muted: 0 0% 14.9%;
--border: 0 0% 14.9%;
```
### Typography
- **Headings**: System font stack
- **Body**: System font stack
- **Mono**: Monospace (for ASCII art display)
### Spacing Scale
- Tailwind CSS 4 default scale (0.5rem increments)
## Performance Targets
- **First Contentful Paint**: < 1.0s
- **Time to Interactive**: < 2.0s
- **Lighthouse Score**: > 95
- **Bundle Size**: < 150KB (gzipped)
- **Font Load Time**: < 100ms per font
## Browser Support
- Chrome/Edge (last 2 versions)
- Firefox (last 2 versions)
- Safari (last 2 versions)
- Mobile Safari iOS 14+
- Chrome Android (last 2 versions)
## Future Enhancements
- [ ] Custom font upload (.flf files)
- [ ] Animated ASCII art support
- [ ] Batch text generation
- [ ] API endpoint for programmatic access
- [ ] Browser extension
- [ ] PWA support with offline capability
- [ ] Multi-language support (i18n)
- [ ] Font editor/creator
- [ ] Collaborative sharing
- [ ] ASCII art gallery
---
**Project Start Date:** 2025-11-09
**Target Completion:** TBD
**Version:** 1.0.0

105
README.md Normal file
View File

@@ -0,0 +1,105 @@
# Figlet UI
A modern, feature-rich web UI for generating ASCII art text using figlet.js with 700+ fonts from the [xero/figlet-fonts](https://github.com/xero/figlet-fonts) collection.
## Features
- **700+ Figlet Fonts** - Massive library from xero's curated collection
- **Live Preview** - Real-time rendering as you type
- **Fuzzy Search** - Quickly find fonts by name or style
- **Visual Font Previews** - See actual rendering in the selector
- **Multiple Export Formats** - Copy, download as text, PNG, or SVG
- **Shareable URLs** - Share your creations with encoded URLs
- **Dark Mode** - Eye-friendly interface
- **Keyboard Shortcuts** - Power user features
- **Mobile Optimized** - Works great on all devices
- **Code Generation** - Generate snippets for JS, Python, CLI
## Tech Stack
- [Next.js 16](https://nextjs.org/) - React framework with static export
- [React 19](https://react.dev/) - Latest React with concurrent features
- [TypeScript 5](https://www.typescriptlang.org/) - Type-safe development
- [Tailwind CSS 4](https://tailwindcss.com/) - Modern utility-first CSS
- [figlet.js](https://github.com/patorjk/figlet.js) - ASCII art rendering engine
- [Fuse.js](https://fusejs.io/) - Fuzzy search functionality
- [Lucide React](https://lucide.dev/) - Beautiful icon library
## Development
### Prerequisites
- Node.js 22+ (managed via nvm)
- pnpm (enabled via corepack)
### Setup
```bash
# Install dependencies
pnpm install
# Run development server with Turbopack
pnpm dev
# Build for production (static export)
pnpm build
# Lint code
pnpm lint
```
The development server will be available at [http://localhost:3000](http://localhost:3000).
## Docker Deployment
Build and run with Docker:
```bash
# Build Docker image
docker build -t figlet-ui .
# Run container
docker run -p 80:80 figlet-ui
```
The application will be available at [http://localhost](http://localhost).
## Project Structure
```
figlet-ui/
├── app/ # Next.js app directory
│ ├── layout.tsx # Root layout with metadata
│ ├── page.tsx # Home page
│ └── globals.css # Global styles
├── components/ # React components
├── lib/ # Utility functions and services
├── types/ # TypeScript type definitions
├── public/ # Static assets
├── Dockerfile # Multi-stage Docker build
├── nginx.conf # Nginx configuration for static serving
└── IMPLEMENTATION_PLAN.md # Detailed implementation roadmap
```
## Why Figlet UI is Better Than TAAG
- **10x More Fonts**: 700+ fonts vs ~300 on TAAG
- **Modern UI/UX**: Clean, responsive design with animations
- **Better Search**: Fuzzy search with visual previews
- **More Export Options**: PNG, SVG, code snippets, not just text
- **Shareable Links**: URL-encoded sharing
- **Performance**: Lazy loading, Web Workers for smooth experience
- **Dark Mode**: Built-in theme switching
- **Keyboard Shortcuts**: Power user efficiency
- **Mobile First**: Optimized for touch devices
## License
MIT
## Credits
- [figlet.js](https://github.com/patorjk/figlet.js) by Patrick Gillespie
- [xero/figlet-fonts](https://github.com/xero/figlet-fonts) - Curated font collection
- Original [FIGlet](http://www.figlet.org/) project

58
app/globals.css Normal file
View File

@@ -0,0 +1,58 @@
@import "tailwindcss";
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
--card: 0 0% 100%;
--card-foreground: 0 0% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 0 0% 3.9%;
--primary: 0 0% 9%;
--primary-foreground: 0 0% 98%;
--secondary: 0 0% 96.1%;
--secondary-foreground: 0 0% 9%;
--muted: 0 0% 96.1%;
--muted-foreground: 0 0% 45.1%;
--accent: 0 0% 96.1%;
--accent-foreground: 0 0% 9%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 89.8%;
--input: 0 0% 89.8%;
--ring: 0 0% 3.9%;
--radius: 0.5rem;
}
.dark {
--background: 0 0% 3.9%;
--foreground: 0 0% 98%;
--card: 0 0% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 0 0% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 0 0% 9%;
--secondary: 0 0% 14.9%;
--secondary-foreground: 0 0% 98%;
--muted: 0 0% 14.9%;
--muted-foreground: 0 0% 63.9%;
--accent: 0 0% 14.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 14.9%;
--input: 0 0% 14.9%;
--ring: 0 0% 83.1%;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
font-feature-settings: "rlig" 1, "calt" 1;
}
}

28
app/layout.tsx Normal file
View File

@@ -0,0 +1,28 @@
import type { Metadata } from 'next';
import './globals.css';
export const metadata: Metadata = {
title: 'Figlet UI - ASCII Art Text Generator',
description: 'A modern web UI for generating ASCII art text with 700+ figlet fonts. Preview custom text in any figlet font, export to multiple formats, and share your creations.',
keywords: ['figlet', 'ascii art', 'text generator', 'banner', 'ascii', 'text art'],
authors: [{ name: 'Valknar' }],
openGraph: {
title: 'Figlet UI - ASCII Art Text Generator',
description: 'Generate beautiful ASCII art text with 700+ fonts',
type: 'website',
},
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className="antialiased">
{children}
</body>
</html>
);
}

28
app/page.tsx Normal file
View File

@@ -0,0 +1,28 @@
export default function Home() {
return (
<main className="min-h-screen p-8">
<div className="max-w-7xl mx-auto">
<header className="mb-8">
<h1 className="text-4xl font-bold mb-2">Figlet UI</h1>
<p className="text-muted-foreground">
ASCII Art Text Generator with 700+ Fonts
</p>
</header>
<div className="bg-card border rounded-lg p-6">
<pre className="font-mono text-sm">
{` _____ _ _ _ _ _ ___
| ___(_) __ _| | ___| |_ | | | |_ _|
| |_ | |/ _\` | |/ _ \\ __| | | | || |
| _| | | (_| | | __/ |_ | |_| || |
|_| |_|\\__, |_|\\___|\\__| \\___/|___|
|___/ `}
</pre>
<p className="mt-4 text-muted-foreground">
Coming soon: A modern interface for generating beautiful ASCII art text.
</p>
</div>
</div>
</main>
);
}

8
next.config.ts Normal file
View File

@@ -0,0 +1,8 @@
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
output: 'export',
reactStrictMode: true,
};
export default nextConfig;

32
package.json Normal file
View File

@@ -0,0 +1,32 @@
{
"name": "figlet-ui",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"clsx": "^2.1.1",
"figlet": "^1.8.0",
"fuse.js": "^7.1.0",
"lucide-react": "^0.553.0",
"next": "^16.0.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"tailwind-merge": "^3.3.1"
},
"devDependencies": {
"@tailwindcss/postcss": "^4.1.17",
"@types/figlet": "^1.7.0",
"@types/node": "^22",
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
"eslint-config-next": "^16.0.0",
"tailwindcss": "^4.0.0",
"typescript": "^5"
}
}

4090
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

5
postcss.config.mjs Normal file
View File

@@ -0,0 +1,5 @@
export default {
plugins: {
'@tailwindcss/postcss': {},
},
};

27
tsconfig.json Normal file
View File

@@ -0,0 +1,27 @@
{
"compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}