Web Development con Claude Sonnet 3.5

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.