Docs
KEd Studio
Applications
KEd Studio
Overview
IntroductionArchitectureDevelopment setup
KEd JSON contractKEd language assistDesktop integration planCloud books auth planBook editor data integration
Platform integration
HomeBrowse applications

© 2026 Wekify LLC · Kifuliiru Lab

Homellms.txtkifuliiru.com

GuidesBook editor data integration

Book editor data integration

Web editor data integration reference.

Overview

This document describes the workflow for opening generated data (numbers, sentences, conjugation rules, etc.) directly in the Book Editor for preview, editing, and PDF export.

The Problem

Previously, data generation would create PDFs directly without preview, leading to:

  • Uncontrolled PDF output with unknown formatting
  • No way to preview content before generating PDFs
  • No editing capability after generation
  • Mismatch between what was generated and final PDF

The Solution

Generate → Preview in Editor → Edit → Export PDF

Instead of generating PDFs blindly, users can:

  1. Generate data on data pages (numbers, sentences, etc.)
  2. Click "Open in Editor" to load data into the book editor
  3. Preview and see exactly how it will look
  4. Edit content, formatting, and structure if needed
  5. Export to PDF when satisfied with the preview

Architecture

Data Flow

∑Formula
Data Generation Page → Session Storage → Book Editor → PDF Export
```text

1. **Data Generation**: User generates data (e.g., numbers 0-1000)
2. **Store Data**: Data is stored in `sessionStorage` before navigation
3. **Load in Editor**: Editor checks for incoming data on mount
4. **Convert Format**: Table data is converted to editor pages format
5. **Preview/Edit**: User can see and edit the content
6. **Export**: Export to PDF when ready

### Technical Implementation

#### 1. Data Storage Format

```typescript
interface EditorData {
 type: 'numbers' | 'sentences' | 'conjugation' | 'verbs'
 data: any[] // Table data array
 columns: Array<{
 key: string
 label: string
 width?: number
 }>
 metadata?: {
 title?: string
 range?: [number, number]
 languagePair?: string
 [key: string]: any
 }
}
```text

#### 2. Session Storage Key

```typescript
const STORAGE_KEY = 'editorData'
```text

#### 3. Data Conversion Strategy

**Table Data → Editor Pages**

- **Cover Page**: Created from metadata (title, subtitle, author)
- **Content Pages**: Table data formatted as:
 - Headers/table structure preserved
 - Data rows formatted as readable content
 - Proper pagination (content distributed across pages)
 - Styling matches editor settings

## Implementation Guide

### Step 1: Add "Open in Editor" Button to Data Pages

#### Example: Numbers Page

```typescript
// src/app/data-generation/numbers/page.tsx
import { useRouter } from 'next/navigation'
import { BookOpen } from 'lucide-react'

const router = useRouter()

// Add button in export options section
<ThemeButton
 onClick={() => {
 // Store data for editor
 const editorData = {
 type: 'numbers',
 data: dataTable,
 columns: exportColumns,
 metadata: {
 title: `Kifuliiru Numbers ${numberRange[0]}-${numberRange[1]}`,
 range: numberRange,
 languagePair: 'Kifuliiru-English'
 }
 }
 sessionStorage.setItem('editorData', JSON.stringify(editorData))
 router.push('/book-editor')
 }}
 variant="primary"
 size="md"
 icon={<BookOpen size={16} />}
>
 Open in Editor
</ThemeButton>
```text

#### Example: Sentences Page

```typescript
// src/app/sentences/page.tsx
<ThemeButton
 onClick={() => {
 const editorData = {
 type: 'sentences',
 data: filtered, // or entries
 columns: [
 { key: 'kifuliiru', label: 'Kifuliiru' },
 { key: 'english', label: 'English' },
 { key: 'category', label: 'Category' }
 ],
 metadata: {
 title: 'Kifuliiru Sentences',
 category: selectedCategory || 'All'
 }
 }
 sessionStorage.setItem('editorData', JSON.stringify(editorData))
 router.push('/book-editor')
 }}
>
 <BookOpen size={16} />
 Open in Editor
</ThemeButton>
```text

#### Example: Conjugation Page

```typescript
// src/app/data-generation/conjugation/page.tsx
<ThemeButton
 onClick={() => {
 const editorData = {
 type: 'conjugation',
 data: dataTable,
 columns: exportColumns,
 metadata: {
 title: 'Kifuliiru Verb Conjugation',
 tense: selectedTense,
 persons: selectedPersons
 }
 }
 sessionStorage.setItem('editorData', JSON.stringify(editorData))
 router.push('/book-editor')
 }}
>
 <BookOpen size={16} />
 Open in Editor
</ThemeButton>
```text

### Step 2: Add Data Loading Logic to Book Editor

```typescript
// src/app/book-editor/page.tsx
import { useSearchParams } from 'next/navigation'

export default function BookEditorPage() {
 const searchParams = useSearchParams()
 
 // Check for incoming data on mount
 useEffect(() => {
 const editorDataStr = sessionStorage.getItem('editorData')
 
 if (editorDataStr) {
 try {
 const editorData = JSON.parse(editorDataStr)
 
 // Convert table data to editor pages
 const { pages, settings } = convertDataToEditorPages(editorData)
 
 // Load into editor
 setPages(pages)
 if (settings) {
 setBookSettings(settings)
 }
 
 // Clean up
 sessionStorage.removeItem('editorData')
 
 // Show notification
 showNotification(' Data loaded into editor!')
 } catch (error) {
 console.error('Error loading editor data:', error)
 showNotification('Error loading data', 'error')
 }
 }
 }, [])
 
 // ... rest of component
}
```text

### Step 3: Create Data Converter Utility

```typescript
// src/lib/utils/editor-data-converter.ts

interface EditorData {
 type: 'numbers' | 'sentences' | 'conjugation' | 'verbs'
 data: any[]
 columns: Array<{ key: string; label: string; width?: number }>
 metadata?: Record<string, any>
}

interface ConvertedEditorPages {
 pages: BookPage[]
 settings?: BookSettings
}

export function convertDataToEditorPages(editorData: EditorData): ConvertedEditorPages {
 const pages: BookPage[] = []
 
 // Create cover page from metadata
 const coverPage = createCoverPage(editorData.metadata)
 if (coverPage) {
 pages.push(coverPage)
 }
 
 // Convert table data to content pages
 const contentPages = convertTableDataToPages(editorData.data, editorData.columns)
 pages.push(...contentPages)
 
 // Set default book settings
 const settings: BookSettings = {
 pageSize: '6x9',
 fontFamily: 'Georgia, serif',
 fontSize: '12pt',
 lineHeight: '1.8',
 showHeader: true,
 showFooter: true,
 headerText: editorData.metadata?.title || 'Kifuliiru Data',
 pageNumberPosition: 'footer-right'
 }
 
 return { pages, settings }
}

function createCoverPage(metadata?: Record<string, any>): BookPage | null {
 if (!metadata?.title) return null
 
 return {
 id: 'cover',
 type: 'cover',
 number: 0,
 content: {
 title: metadata.title,
 subtitle: metadata.subtitle || metadata.languagePair || '',
 author: metadata.author || 'Kifuliiru Lab'
 }
 }
}

function convertTableDataToPages(
 data: any[],
 columns: Array<{ key: string; label: string }>
): BookPage[] {
 const pages: BookPage[] = []
 
 // Create table header row
 const headerRow = `<table style="width: 100%; border-collapse: collapse; margin-bottom: 20px;">
 <thead>
 <tr>
 ${columns.map(col => `<th style="border: 1px solid #ddd; padding: 8px; text-align: left; background: #f3f4f6;">${col.label}</th>`).join('')}
 </tr>
 </thead>
 <tbody>
`
 
 // Distribute data across pages
 const itemsPerPage = 25 // Adjust based on content
 let currentPageContent = headerRow
 let pageNumber = 1
 
 for (let i = 0; i < data.length; i++) {
 const row = data[i]
 const rowHtml = `
 <tr>
 ${columns.map(col => `<td style="border: 1px solid #ddd; padding: 8px;">${row[col.key] || ''}</td>`).join('')}
 </tr>
`
 
 currentPageContent += rowHtml
 
 // Create new page when reaching limit or last item
 if ((i + 1) % itemsPerPage === 0 || i === data.length - 1) {
 currentPageContent += `
 </tbody>
 </table>`
 
 pages.push({
 id: `page-${pageNumber}`,
 type: 'content',
 number: pageNumber,
 content: currentPageContent
 })
 
 pageNumber++
 currentPageContent = headerRow
 }
 }
 
 return pages
}

// Format-specific converters
export function formatNumbersData(data: any[], columns: any[]): string {
 // Custom formatting for numbers
 let content = '<h1>Kifuliiru Numbers</h1>\n\n'
 
 data.forEach(item => {
 content += `<p><strong>${item.value}</strong> - ${item.kifuliiru} (${item.english})</p>\n`
 })
 
 return content
}

export function formatSentencesData(data: any[], columns: any[]): string {
 // Custom formatting for sentences
 let content = '<h1>Kifuliiru Sentences</h1>\n\n'
 
 data.forEach(item => {
 content += `<div style="margin-bottom: 20px;">
 <p><strong>Kifuliiru:</strong> ${item.kifuliiru || ''}</p>
 <p><strong>English:</strong> ${item.english || ''}</p>
 ${item.category ? `<p><em>Category: ${item.category}</em></p>` : ''}
 </div>\n`
 })
 
 return content
}
```text

## Usage Guide

### For Users

1. **Generate Data**
 - Navigate to a data generation page (Numbers, Sentences, Conjugation)
 - Configure generation settings
 - Click "Generate" to create data

2. **Open in Editor**
 - Click the "Open in Editor" button
 - Editor opens automatically with data loaded
 - Cover page is created from metadata
 - Content pages show formatted data

3. **Preview and Edit**
 - Review content in the editor
 - Edit text, formatting, or structure as needed
 - Adjust book settings (fonts, page size, etc.)
 - Add/remove pages if needed

4. **Export PDF**
 - Click "Export" → "PDF"
 - PDF is generated from the editor content
 - Download when ready

### For Developers

#### Adding Support to New Data Types

1. **Add Button to Data Page**
 ```typescript
 <ThemeButton onClick={openInEditor}>
 <BookOpen /> Open in Editor
 </ThemeButton>
 ```text

2. **Store Data Format**
 ```typescript
 const editorData = {
 type: 'yourDataType',
 data: yourDataTable,
 columns: yourColumns,
 metadata: { title: 'Your Title' }
 }
 sessionStorage.setItem('editorData', JSON.stringify(editorData))
 ```text

3. **Add Converter Function** (if needed)
 - Add custom formatting in `editor-data-converter.ts`
 - Handle type-specific formatting

## Benefits

### For Users
- **Preview Before Export**: See exactly how content will look
- **Edit Capability**: Make changes before PDF generation
- **Better Control**: Adjust formatting, fonts, page size
- **Iterative Workflow**: Generate → Preview → Edit → Export

### For Developers
- **Single Source of Truth**: Editor becomes the preview system
- **Flexible**: Easy to add new data types
- **Reusable**: Same editor for all data types
- **Maintainable**: Centralized conversion logic

## Limitations & Considerations

### Current Limitations
1. **Large Datasets**: Very large tables may create many pages
 - **Solution**: Paginate or use table view in editor
2. **Complex Formatting**: Some table structures may not convert perfectly
 - **Solution**: Allow editing after loading
3. **Data Loss**: Data format may lose some structure
 - **Solution**: Preserve original data in metadata

### Future Improvements
1. **Table Editor View**: Option to view as table in editor
2. **Bulk Edit**: Edit multiple rows at once
3. **Data Filtering**: Filter data before loading into editor
4. **Template Support**: Save editor layouts as templates
5. **Auto-Pagination**: Smart page breaking for tables
6. **Export Formats**: Export to Word, EPUB, etc.

## Troubleshooting

### Data Not Loading
- Check browser console for errors
- Verify `sessionStorage` is enabled
- Check data format matches expected structure

### Formatting Issues
- Editor may display differently than PDF
- Use editor preview as guide, not exact match
- Adjust settings in editor sidebar

### Performance Issues
- Large datasets may load slowly
- Consider pagination or chunking
- Limit initial data size if needed

## Technical Details

### Session Storage
- **Key**: `editorData`
- **Format**: JSON string
- **Lifetime**: Per browser session
- **Cleanup**: Removed after loading

### Data Conversion
- **Cover Page**: Created if metadata.title exists
- **Content Pages**: Created from table data
- **Pagination**: Automatic based on content size
- **Styling**: Basic HTML/CSS preserved

### Error Handling
- Invalid data format → Error notification
- Missing columns → Default formatting
- Empty data → Empty editor state

## Examples

### Example 1: Numbers 0-100
```typescript
{
 type: 'numbers',
 data: [
 { value: 0, kifuliiru: 'zero', english: 'zero' },
 { value: 1, kifuliiru: 'umu', english: 'one' },
 // ... more numbers
 ],
 columns: [
 { key: 'value', label: 'Value' },
 { key: 'kifuliiru', label: 'Kifuliiru' },
 { key: 'english', label: 'English' }
 ],
 metadata: {
 title: 'Kifuliiru Numbers 0-100',
 range: [0, 100]
 }
}
```text

### Example 2: Sentences
```typescript
{
 type: 'sentences',
 data: [
 {
 kifuliiru: 'Muha omuhi?',
 english: 'How are you?',
 category: 'greetings'
 },
 // ... more sentences
 ],
 columns: [
 { key: 'kifuliiru', label: 'Kifuliiru' },
 { key: 'english', label: 'English' },
 { key: 'category', label: 'Category' }
 ],
 metadata: {
 title: 'Kifuliiru Sentences',
 category: 'All Categories'
 }
}
```text

## Conclusion

This workflow transforms the data generation process from:
- **Before**: Generate → PDF (no preview, no control)
- **After**: Generate → Preview in Editor → Edit → Export PDF

The editor becomes the central hub for content preview and editing, giving users full control over their final output.
PreviousCloud books auth planNextPlatform integration

On this page

  • Overview
  • The Problem
  • The Solution
  • Architecture
  • Data Flow