By Sahidur Pub Feb 20

Part 9: Building New Features — What It's Like to Be a Developer

A practical guide for developers on how to add new features to AllBengal while keeping code organized and safe.

Part 9: Building New Features — What It's Like to Be a Developer

The Goal: Make It Easy to Add Stuff

When I was building AllBengal, I thought: "Other developers might want to add features. How do I make that easy?"

The answer is: organize everything so it's obvious where new code goes, and use the same patterns everywhere.

Think of it like building with LEGO blocks:

  • Every block has the same connector style
  • You don't have to think about how to snap them together
  • Just follow the pattern and add your piece

The AllBengal Code Organization

backend/
├── app/
│   ├── core/                 ← Shared infrastructure
│   │   ├── database.py       ← How to talk to database
│   │   ├── security.py       ← Login & tokens
│   │   ├── config.py         ← Settings
│   │   └── permissions.py    ← Who can do what
│   │
│   └── features/             ← Features (auth, blog, media, etc.)
│       ├── auth/
│       │   ├── router.py     ← What HTTP endpoints exist
│       │   ├── schemas.py    ← Data validation
│       │   └── crud.py       ← Database queries
│       ├── blog/
│       │   ├── router.py
│       │   ├── schemas.py
│       │   └── crud.py
│       └── [other features]
│
└── main.py                   ← Start here

frontend/
├── src/
│   ├── lib/
│   │   ├── components/       ← Reusable UI pieces
│   │   ├── server/           ← Backend communication
│   │   └── utils/            ← Helper functions
│   │
│   └── routes/               ← Website pages
│       ├── +page.svelte      ← Home page
│       ├── blog/
│       │   ├── +page.server.ts    ← Load data from backend
│       │   └── [slug]/            ← Individual blog post
│       └── [other pages]
│
└── package.json              ← Dependencies

How to Add a New Feature

Step 1: Create the Backend Folder

If you want to add a "comments" feature:

backend/app/features/comments/
├── router.py       ← The HTTP endpoints
├── schemas.py      ← What data looks like
└── crud.py         ← Database queries

Step 2: Write the Data Models (schemas.py)

This defines what your data looks like:

// app/features/comments/schemas.py

from pydantic import BaseModel

class CommentCreate(BaseModel):
    post_id: int
    content: str

class Comment(BaseModel):
    id: int
    post_id: int
    author_id: int
    content: str
    created_at: str

This is like describing: "A comment has these fields with these types."

Step 3: Write Database Queries (crud.py)

CRUD = Create, Read, Update, Delete

// app/features/comments/crud.py

async def create_comment(post_id: int, author_id: int, content: str):
    query = """
        INSERT INTO comments (post_id, author_id, content)
        VALUES ($1, $2, $3)
        RETURNING id, post_id, author_id, content, created_at
    """
    return await db.execute(query, (post_id, author_id, content))

async def get_post_comments(post_id: int):
    query = """
        SELECT id, post_id, author_id, content, created_at
        FROM comments
        WHERE post_id = $1
        ORDER BY created_at DESC
    """
    return await db.fetch_all(query, (post_id,))

Step 4: Write the API Endpoints (router.py)

These are the HTTP endpoints your frontend will call:

// app/features/comments/router.py

from fastapi import APIRouter, Depends, HTTPException
from . import crud, schemas

router = APIRouter(prefix="/comments", tags=["Comments"])

@router.post("/")
async def create_comment(
    comment: schemas.CommentCreate,
    token_data: dict = Depends(get_token_data)
):
    author_id = token_data["user_id"]
    post = await crud.get_post_by_id(comment.post_id)
    if not post or post["status"] != "published":
        raise HTTPException(status_code=404, detail="Post not found")
    
    new_comment = await crud.create_comment(
        post_id=comment.post_id,
        author_id=author_id,
        content=comment.content
    )
    return new_comment

@router.get("/{post_id}")
async def get_comments(post_id: int):
    return await crud.get_post_comments(post_id)

Step 5: Register the Router

Add it to backend/main.py:

from app.features.comments.router import router as comments_router

app.include_router(comments_router, prefix=settings.API_PREFIX)

Now your endpoints are available at /api/comments/

Step 6: Create the Frontend Page

Make it easy for users to use your feature with beautiful, interactive UI.

Key Patterns to Follow

1. Always Validate Input

Good:
class CommentCreate(BaseModel):
    content: str  # Validates: must be string, must not be empty
Bad:
def create_comment(data):  # What is data? Could be anything!

2. Always Check Permissions

Good:
is_author = comment["author_id"] == token_data["user_id"]
if not is_author:
    raise HTTPException(status_code=403, detail="Not authorized")
Bad:
delete_comment(comment_id)  # No permission check!

The LEGO Block Principle

Every feature should follow the same three-file pattern:

  • schemas.py: Define data shapes with Pydantic
  • crud.py: Write database queries
  • router.py: Write HTTP endpoints that use crud and validate with schemas

This consistency means once you've added one feature, adding the next one is obvious. You just follow the same template.

Testing Your Feature

Before publishing, test:

  1. ✅ Can logged-in users create?
  2. ✅ Can non-logged-in users see "Permission Denied"?
  3. ✅ Are inputs validated?
  4. ✅ Do invalid inputs show friendly errors?
  5. ✅ Does the frontend work?

The Bottom Line

Adding features to AllBengal is easy because:

  • ✅ Every feature has the same structure
  • ✅ You know where code goes
  • ✅ Tests are straightforward
  • ✅ Other developers understand your code
  • ✅ Like LEGO blocks: snap it in and it works

Want to build a feature? Drop a comment with your idea!

Analytics

Unique visitors

0

Visits

0

Reactions

0

💬 Comments (0)

No comments yet.

💌 Share Your Opinion With Us

📖 Read More Articles

Explore more articles and discover interesting stories from our blog.

View All Articles →