Introduction: From Configuration to Building Features

Welcome back! In our previous lesson, we configured OpenCode to understand our e-commerce project's rules using AGENTS.md and opencode.json. Now, it is time to put those rules into action. In this lesson, we will build a complete Product Reviews feature. Building a new feature in an existing project requires discipline. We will use a structured workflow loop: PlanImplementVerifyEdge CasesCleanup.

By following this loop, you ensure that your new code perfectly matches the existing application. We will create a database model, build API endpoints with canonical error handling, and secure them with validation and authentication. Let's start planning our feature!

Planning the Feature with OpenCode

Feature Planning is the process of defining exactly what your new code needs to do before you actually write it. This step matters because jumping straight into coding often leads to mistakes, missed requirements, and messy integration. When working with an AI assistant like OpenCode, a clear plan gives the AI the context it needs to generate accurate, helpful code that fits your project.

For our product reviews feature, we need users to be able to rate a product from 1 to 5, leave a text comment, and manage their own reviews. We can prompt OpenCode to help us outline this plan. We might ask it: Based on our existing product and user models, outline the necessary files and database fields to create a product reviews feature.

This output shows that OpenCode understands our architecture. It correctly identified that we need a new database model, validation middleware to check user input, and a new routes file for our API endpoints. Having this roadmap makes the implementation phase much smoother.

Creating the Review Database Model

A Database Model is a class in your code that defines the structure of a table in your database. This matters because it ensures that all data saved by your application follows strict rules and types. Let's start by defining our Review model in src/models/review.py and setting up its basic columns.

In this first block, we import the necessary tools from sqlalchemy. We define our table name as "reviews" and create our columns. Notice that we use ForeignKey for user_id and product_id. This links our review directly to the existing users and products tables, ensuring that a review cannot exist without a valid user and a valid product. We also include both created_at and updated_at timestamps. The onupdate parameter on tells to automatically refresh this value whenever a row is modified. Next, we need to add relationships and constraints to this model. A is a database-level rule that restricts what values can be saved.

Building API Endpoints with Canonical Error Handling

Canonical Error Handling is a standardized pattern for catching exceptions and returning consistent error messages across your entire application. This matters because it ensures that whoever is using your API always receives predictable responses, making debugging much easier. If you recall from our last lesson, we defined this exact pattern in our AGENTS.md file. Let's implement the route to create a new review in src/api/routes/reviews.py.

We create a Flask Blueprint for our review routes. In the create_review function, we wrap our logic inside a try block. We extract the JSON data sent by the user, create a new Review object, and save it to the database using db.session.commit(). On success, we return the data wrapped in a {"data": ...} dictionary with a status code. Now, we must complete our canonical error-handling pattern by catching potential failures without exposing internal exception details to the client.

Implementing Validation and Authentication Middleware

Middleware refers to reusable functions that intercept a request before it reaches your main route logic. This matters because it allows you to separate security and data validation from your actual business logic, keeping your route files clean and easy to read. Let's create a custom validation decorator in src/api/middleware/validation.py.

This validate_review function acts as a guard. Before the main route runs, it checks if the user provided JSON data. For POST requests, required fields such as rating, comment, and product_id must be enforced explicitly so missing data returns a clean 400 validation error instead of failing later at the database layer. For requests, partial updates are often allowed, so it still makes sense to validate fields only when they are present. We also validate types: must be an integer between and , and must be a string no longer than characters, matching the constraint on our database column. If the data is valid, it calls the original function using . To use this middleware, along with authentication, we apply them as decorators to our routes back in .

Verifying Integration and Handling Edge Cases

Edge Cases are situations outside of normal user behavior that can cause your application to behave unexpectedly or crash. Identifying and handling these scenarios matters because real users rarely use applications perfectly. Your code must be defensive. During our workflow loop, after implementing the main logic, we must verify integration and account for these tricky situations. One major edge case in a reviews system is preventing a user from reviewing the same product twice. Let's look at how we handle this edge case inside our create_review route.

Before we create a review, we run two important checks. First, we query the database to ensure that the product_id provided actually exists. If a user tries to review a deleted or fake product, we return a 404 error. Second, we query the Review table to see if a record already exists with the same user_id and product_id. If it does, we block the creation and return a friendly 400 error. To verify everything works, we can use an OpenCode terminal to send a test request.

Summary and Practice Preparation

Excellent work! In this lesson, we transitioned from configuration to building a real feature. We followed a professional workflow loop: planning the requirements, implementing the database model, and writing the API routes. We applied the canonical error-handling rules we established in AGENTS.md during our previous lesson to ensure that our responses were consistent. Furthermore, we protected our application by implementing validation middleware, enforcing authentication, and handling edge cases like duplicate reviews.

Now, it is your turn to practice. In the upcoming exercises, you will write the models, middleware, and API routes for this exact Product Reviews feature. You will use the CodeSignal IDE (which has all the necessary libraries like Flask and SQLAlchemy pre-installed) to implement and test your code. Get ready to build!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal