Web Development con Claude Sonnet 3.5

Sviluppo web con Claude AI
L'IA nel processo di sviluppo web moderno
Mauto 5 min

Dopo aver esplorato l’ottimizzazione del codice, vediamo come Claude può aiutarci nello sviluppo web. Dalla creazione di componenti frontend al debugging di API, Claude eccelle nell’analisi e generazione di codice web.

Sviluppo Frontend Responsivo

Dev: Devo creare un componente card responsive per un blog. Requisiti:
- Immagine in evidenza
- Titolo
- Estratto
- Data e autore
- Layout a griglia su desktop, colonna su mobile

Claude: Creiamo un componente usando CSS Grid e flexbox per la responsività. Ecco una prima versione:
<article class="blog-card">
  <img src="{{post.image}}" alt="{{post.title}}" class="card-image">
  <div class="card-content">
    <h2 class="card-title">{{post.title}}</h2>
    <div class="card-meta">
      <time>{{post.date}}</time>
      <span class="author">{{post.author}}</span>
    </div>
    <p class="card-excerpt">{{post.excerpt}}</p>
  </div>
</article>

<style>
.blog-card {
  display: grid;
  gap: 1rem;
  background: #fff;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

/* Mobile first */
.card-image {
  width: 100%;
  height: 200px;
  object-fit: cover;
}

/* Desktop layout */
@media (min-width: 768px) {
  .blog-card {
    grid-template-columns: 1fr 2fr;
  }
  
  .card-image {
    height: 100%;
  }
}
</style>
Dev: Aggiungerei un hover effect e animazioni smooth

Claude: Ecco la versione con effetti hover e transizioni:
<style>
.blog-card {
  display: grid;
  gap: 1rem;
  background: #fff;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.blog-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 8px 24px rgba(0,0,0,0.15);
}

.card-image {
  width: 100%;
  height: 200px;
  object-fit: cover;
  transition: transform 0.5s ease;
}

.blog-card:hover .card-image {
  transform: scale(1.05);
}

.card-title {
  position: relative;
  padding-bottom: 0.5rem;
}

.card-title::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  width: 0;
  height: 2px;
  background: currentColor;
  transition: width 0.3s ease;
}

.blog-card:hover .card-title::after {
  width: 100%;
}
</style>
Dev: Come lo renderei accessibile?

Claude: Ecco la versione con miglioramenti per l'accessibilità:
<article class="blog-card" tabindex="0">
  <img 
    src="{{post.image}}" 
    alt="{{post.imageDescription}}" 
    class="card-image"
    loading="lazy"
  >
  <div class="card-content">
    <h2 class="card-title">
      <a href="{{post.url}}" 
         class="card-link"
         aria-label="Leggi l'articolo: {{post.title}}"
      >
        {{post.title}}
      </a>
    </h2>
    <div class="card-meta" aria-label="Dettagli articolo">
      <time datetime="{{post.date.iso}}">{{post.date.formatted}}</time>
      <span class="author">di {{post.author}}</span>
    </div>
    <p class="card-excerpt">{{post.excerpt}}</p>
  </div>
</article>

<style>
.blog-card {
  /* ... stili precedenti ... */
}

/* Focus styles */
.blog-card:focus-within {
  outline: 3px solid #4A90E2;
  outline-offset: 2px;
}

.card-link {
  color: inherit;
  text-decoration: none;
  outline: none;
}

.card-link:focus {
  text-decoration: underline;
  text-underline-offset: 4px;
}

/* Reduce motion if requested */
@media (prefers-reduced-motion: reduce) {
  .blog-card,
  .card-image,
  .card-title::after {
    transition: none;
  }
}
</style>

Backend: API RESTful

Dev: Devo creare un'API per gestire gli ordini di un e-commerce. Mi aiuti a definire la struttura?

Claude: Iniziamo con le principali endpoints RESTful per la gestione ordini:
// types.ts
interface OrderItem {
  productId: string;
  quantity: number;
  price: number;
}

interface Order {
  id: string;
  userId: string;
  items: OrderItem[];
  status: 'pending' | 'confirmed' | 'shipped' | 'delivered';
  shippingAddress: Address;
  paymentInfo: PaymentInfo;
  createdAt: Date;
  updatedAt: Date;
}

// orders.controller.ts
@Controller('orders')
export class OrdersController {
  @Post()
  @UseGuards(AuthGuard)
  async createOrder(@Body() order: CreateOrderDto) {
    return this.orderService.create(order);
  }
  
  @Get('user/:userId')
  @UseGuards(AuthGuard)
  async getUserOrders(
    @Param('userId') userId: string,
    @Query() filters: OrderFilters
  ) {
    return this.orderService.findByUser(userId, filters);
  }
  
  @Patch(':orderId/status')
  @UseGuards(AuthGuard, RolesGuard)
  @Roles('admin')
  async updateOrderStatus(
    @Param('orderId') orderId: string,
    @Body('status') status: OrderStatus
  ) {
    return this.orderService.updateStatus(orderId, status);
  }
}
Dev: Come gestisco le notifiche quando cambia lo stato dell'ordine?

Claude: Implementiamo un sistema di eventi con notifiche multiple:
// events/order-status.event.ts
export class OrderStatusChangedEvent {
  constructor(
    public readonly orderId: string,
    public readonly oldStatus: OrderStatus,
    public readonly newStatus: OrderStatus,
    public readonly userId: string
  ) {}
}

// notifications/order.listener.ts
@Injectable()
export class OrderNotificationListener {
  @OnEvent('order.status.changed')
  async handleStatusChange(event: OrderStatusChangedEvent) {
    const notifications = await Promise.all([
      this.emailService.sendStatusUpdate(event),
      this.pushService.sendNotification(event),
      event.newStatus === 'shipped' && 
        this.smsService.sendTrackingInfo(event)
    ]);
    
    await this.logNotifications(event, notifications);
  }
}

// orders.service.ts
@Injectable()
export class OrdersService {
  async updateStatus(orderId: string, newStatus: OrderStatus) {
    const order = await this.findById(orderId);
    
    const event = new OrderStatusChangedEvent(
      orderId,
      order.status,
      newStatus,
      order.userId
    );
    
    await this.orderRepository.update(orderId, { status: newStatus });
    await this.eventEmitter.emit('order.status.changed', event);
    
    return this.findById(orderId);
  }
}

Testing e Debugging

Quando scriviamo i test, Claude può aiutarci a identificare i casi edge:

Dev: Devo testare il sistema di ordini, quali casi devo considerare?

Claude: Ecco una suite di test completa:
describe('OrdersService', () => {
  describe('createOrder', () => {
    it('crea ordine con prodotti validi', async () => {
      // Test base
    });
    
    it('gestisce prodotti non disponibili', async () => {
      // Verifica errori stock
    });
    
    it('calcola correttamente totali e sconti', async () => {
      // Verifica calcoli
    });
    
    it('valida indirizzo spedizione', async () => {
      // Test validazione
    });
  });
  
  describe('updateStatus', () => {
    it('notifica utente del cambio stato', async () => {
      // Verifica notifiche
    });
    
    it('impedisce transizioni stato invalide', async () => {
      // Es: da pending a delivered
    });
    
    it('gestisce errori notifiche con retry', async () => {
      // Test resilienza
    });
  });
});

Continuous Integration

Claude può suggerire workflow di CI ottimizzati:

Dev: Come configuro la CI per questo progetto?

Claude: Ecco una configurazione GitHub Actions completa:
name: E-commerce API CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    
    services:
      postgres:
        image: postgres:14
        env:
          POSTGRES_USER: test
          POSTGRES_PASSWORD: test
          POSTGRES_DB: test_db
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
                    
    steps:
    - uses: actions/checkout@v3
    
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
        cache: 'npm'
        
    - name: Install dependencies
      run: npm ci
      
    - name: Lint
      run: npm run lint
      
    - name: Type check
      run: npm run type-check
      
    - name: Unit tests
      run: npm test
      
    - name: E2E tests
      run: npm run test:e2e
      env:
        DATABASE_URL: postgresql://test:test@localhost:5432/test_db

Conclusione

Lo sviluppo web con Claude richiede una comunicazione chiara dei requisiti e un processo iterativo di raffinamento. Nel prossimo articolo esploreremo l’utilizzo di Claude per il machine learning.

content_copy Copiato