Code Style
Coding standards and conventions for Duckling.
Python (Backend)
General Guidelines
- Follow PEP 8 guidelines
- Use type hints
- Maximum line length: 100 characters
- Use docstrings for functions and classes
Function Documentation
def convert_document(file_path: str, settings: dict) -> ConversionResult:
"""
Convert a document using Docling.
Args:
file_path: Path to the document file
settings: Conversion settings dictionary
Returns:
ConversionResult object with converted content
Raises:
ValueError: If file format is not supported
IOError: If file cannot be read
"""
pass
Class Documentation
class ConverterService:
"""
Service for document conversion operations.
This service manages the conversion pipeline, job queue,
and interaction with the Docling library.
Attributes:
_job_queue: Queue for pending conversion jobs
_max_concurrent_jobs: Maximum parallel conversions
"""
pass
Imports
Order imports as:
- Standard library
- Third-party packages
- Local modules
import os
import json
from typing import Optional, Dict, List
from flask import Flask, request
from sqlalchemy import Column, String
from models.database import Conversion
from services.converter import ConverterService
Formatting
Use Black for automatic formatting:
TypeScript/React (Frontend)
General Guidelines
- Use functional components with hooks
- Use TypeScript for type safety
- Follow ESLint configuration
- Use meaningful component and variable names
Component Structure
interface ButtonProps {
label: string;
onClick: () => void;
disabled?: boolean;
variant?: 'primary' | 'secondary';
}
export function Button({
label,
onClick,
disabled = false,
variant = 'primary'
}: ButtonProps) {
return (
<button
onClick={onClick}
disabled={disabled}
className={`btn btn-${variant}`}
>
{label}
</button>
);
}
Hooks
export function useConversion() {
const [status, setStatus] = useState<ConversionStatus>('idle');
const [result, setResult] = useState<ConversionResult | null>(null);
const startConversion = useCallback(async (file: File) => {
setStatus('uploading');
// ...
}, []);
return { status, result, startConversion };
}
File Organization
components/
├── Button/
│ ├── Button.tsx
│ ├── Button.test.tsx
│ └── index.ts
├── DropZone/
│ ├── DropZone.tsx
│ ├── DropZone.test.tsx
│ └── index.ts
Imports
// React and hooks first
import { useState, useCallback, useEffect } from 'react';
// Third-party libraries
import { motion } from 'framer-motion';
import axios from 'axios';
// Local components
import { Button } from '@/components/Button';
import { useConversion } from '@/hooks/useConversion';
// Types
import type { ConversionResult } from '@/types';
Formatting
Use Prettier for automatic formatting:
Commit Messages
Follow Conventional Commits:
Types
| Type | Description |
|---|---|
feat | New feature |
fix | Bug fix |
docs | Documentation changes |
style | Code style changes (formatting) |
refactor | Code refactoring |
test | Adding/updating tests |
chore | Maintenance tasks |
Examples
feat(upload): add drag-and-drop file upload
Implemented drag-and-drop functionality using react-dropzone.
Supports multiple file selection in batch mode.
Closes #123
fix(converter): handle large PDF files correctly
Fixed memory issue when processing PDFs > 50MB by streaming
the file instead of loading entirely into memory.
docs(readme): update installation instructions
Added Docker setup instructions and troubleshooting section.
CSS/Tailwind
Class Organization
Order Tailwind classes consistently:
- Layout (flex, grid, position)
- Spacing (margin, padding)
- Sizing (width, height)
- Typography (font, text)
- Visual (background, border, shadow)
- Interactive (hover, focus)
<div className="flex items-center gap-4 p-4 w-full text-sm bg-gray-800 rounded-lg hover:bg-gray-700">
{/* content */}
</div>
Custom Classes
Use @apply sparingly, prefer composition:
/* Prefer this */
.btn-primary {
@apply px-4 py-2 bg-teal-500 text-white rounded-lg hover:bg-teal-600;
}
/* Over inline classes everywhere */
API Design
Endpoint Naming
- Use nouns, not verbs
- Use plural forms
- Use kebab-case for multi-word resources
GET /api/conversions
POST /api/conversions
GET /api/conversions/{id}
DELETE /api/conversions/{id}
GET /api/conversions/{id}/status