What You'll Build
- Frontend: React component with form handling
- Backend: RESTful API endpoints
- Database: Schema migrations and queries
- Tests: Unit, integration, and E2E tests
- Documentation: API docs and README updates
Put everything you’ve learned together by building a real feature with Claude Code. This guide walks through a complete development workflow, from receiving requirements to deploying tested code.
We’ll build a user profile feature that includes:
What You'll Build
Start Claude Code and create a Product Requirements Document:
> Create a PRD for a user profile feature. Users should be able to:> - View and edit their profile (name, bio, location)> - Upload an avatar image> - Make their profile public or private> - See when their profile was last updated
Claude will generate a comprehensive PRD. Review and refine:
> Add requirements for:> - Avatar image size limits (max 5MB)> - Bio character limit (500 chars)> - Profile URL format (/users/{username})
Use extended thinking to create a technical plan:
> Based on this PRD, think hard about the implementation approach.> Consider database schema, API design, security, and testing strategy.> We're using React, Node.js/Express, and PostgreSQL.
Transform the plan into actionable tasks:
> Convert your plan into a detailed todo list with subtasks.> Organize by: Database, Backend API, Frontend, Tests, Documentation
Claude generates something like:
## User Profile Feature Tasks
### Database- [ ] Create migration for users table updates - [ ] Add bio, location, avatar_url columns - [ ] Add is_public boolean with default true - [ ] Add updated_at timestamp- [ ] Create migration for avatar_metadata table - [ ] Store file size, mime type, upload date
### Backend API- [ ] Create profile endpoints - [ ] GET /api/users/:username/profile - [ ] PUT /api/users/profile (authenticated) - [ ] POST /api/users/avatar (file upload) - [ ] DELETE /api/users/avatar- [ ] Implement middleware - [ ] Authentication check - [ ] File upload validation - [ ] Profile visibility check
### Frontend- [ ] Create ProfilePage component - [ ] Display mode for public profiles - [ ] Edit mode for own profile- [ ] Create ProfileForm component - [ ] Form validation - [ ] Avatar upload with preview- [ ] Add routing- [ ] Add to navigation
### Tests- [ ] Unit tests for API endpoints- [ ] Integration tests for profile workflows- [ ] E2E tests for profile interactions- [ ] Test file upload edge cases
### Documentation- [ ] API documentation- [ ] Update README- [ ] Add example usage
Start with the database schema:
> Create the database migration for the user profile fields.> Use our standard migration format with up/down methods.
Claude creates migrations/20250315_add_user_profile_fields.js
:
exports.up = async (knex) => { await knex.schema.alterTable('users', (table) => { table.text('bio').nullable(); table.string('location', 100).nullable(); table.string('avatar_url', 255).nullable(); table.boolean('is_public').defaultTo(true).notNullable(); table.timestamp('profile_updated_at').defaultTo(knex.fn.now()); });
await knex.schema.createTable('avatar_metadata', (table) => { table.increments('id').primary(); table.integer('user_id').unsigned().notNullable() .references('id').inTable('users').onDelete('CASCADE'); table.integer('file_size').unsigned().notNullable(); table.string('mime_type', 50).notNullable(); table.timestamp('uploaded_at').defaultTo(knex.fn.now()); table.index('user_id'); });};
exports.down = async (knex) => { await knex.schema.dropTableIfExists('avatar_metadata');
await knex.schema.alterTable('users', (table) => { table.dropColumn('bio'); table.dropColumn('location'); table.dropColumn('avatar_url'); table.dropColumn('is_public'); table.dropColumn('profile_updated_at'); });};
> Run the migration and verify the schema changes
Claude executes:
npm run migrate:latestnpm run db:schema
> Update the User model to include the new profile fields.> Add validation rules and any computed properties.
Implement the profile API:
> Implement the GET /api/users/:username/profile endpoint.> It should:> - Return 404 if user doesn't exist> - Return 403 if profile is private and requester isn't the owner> - Include avatar metadata if available
Claude's Approach
Claude will:
> Implement avatar upload with:> - Multer for file handling> - Image validation (type and size)> - Resize to standard dimensions> - Store in local uploads directory> - Save metadata to database
> Write comprehensive tests for the profile API endpoints.> Include tests for:> - Successful operations> - Authentication failures> - Validation errors> - File upload edge cases
If you have Figma MCP configured:
> Get the user profile design from Figma and analyze the component structure
> Create the ProfilePage component based on the design.> Include:> - Conditional rendering for view/edit modes> - Form validation with react-hook-form> - Avatar upload with drag-and-drop> - Loading and error states
Claude creates a well-structured component:
import React, { useState, useEffect } from 'react';import { useParams } from 'react-router-dom';import { useForm } from 'react-hook-form';import { useAuth } from '../hooks/useAuth';import AvatarUpload from './AvatarUpload';import ProfileDisplay from './ProfileDisplay';import ProfileForm from './ProfileForm';
const ProfilePage: React.FC = () => { const { username } = useParams<{ username: string }>(); const { user: currentUser } = useAuth(); const [profile, setProfile] = useState(null); const [isEditing, setIsEditing] = useState(false); const [loading, setLoading] = useState(true);
// ... implementation};
> Style the components to match the Figma design.> Use our existing design system tokens.
> Add the profile route to our router and test the full flow:> - Navigate to profile> - Edit own profile> - Upload avatar> - View another user's profile
Using Playwright MCP:
> Write E2E tests for the profile feature:> - User can view their own profile> - User can edit and save changes> - Avatar upload works correctly> - Privacy settings are enforced
> Analyze the profile page performance:> - Check database query efficiency> - Verify image optimization> - Test loading times> Run lighthouse if available
> Update our API documentation with the new profile endpoints.> Include request/response examples and error codes.
> Review all changes and create a pull request:> - Generate a comprehensive PR description> - Link to the original requirements> - Include testing instructions> - Add screenshots of the UI
Claude will:
git status
to see all changesAfter PR approval:
> Create a deployment plan for the profile feature.> Include:> - Database migration steps> - Environment variable updates> - Feature flag configuration> - Rollback procedure
Throughout the workflow, Claude automatically:
Keeping Claude Focused
/clear
between major phasesWhen things go wrong:
# Claude made an error> Undo the last change
# Tests are failing> Debug why the profile update test is failing
# Need to start over> Revert all changes since the last commit
Here’s a condensed real-world session:
# Start with requirements> Let's build a user profile feature. Think about what we need.
# Claude analyzes and plans...
> Great plan. Create the database migration first.
# Claude creates migration file...
> Run the migration and verify it worked.
# Claude runs migration...
> Now implement the GET profile endpoint with tests.
# Claude implements endpoint and tests...
> The tests are failing. Debug and fix.
# Claude investigates and fixes...
> Perfect. Now build the React component.
# Claude creates component...
> Add E2E tests for the complete flow.
# Claude writes Playwright tests...
> All tests passing! Create a PR with a good description.
# Claude creates comprehensive PR...
Feature Completion Checklist
✅ All requirements from PRD implemented
✅ Database migrations run successfully
✅ API endpoints tested and documented
✅ Frontend matches design specifications
✅ Unit test coverage > 80%
✅ E2E tests cover happy path + edge cases
✅ Documentation updated
✅ PR reviewed and approved
✅ Deployed successfully
Congratulations! You’ve built a complete feature with Claude Code. Continue learning with:
Remember: Claude Code is your pair programmer. The more context and clarity you provide, the better it can help you build robust, well-tested features efficiently.