Middle
Where do you draw the line between front-end and back-end development?
sobes.tech AI
Answer from AI
The boundary is at the API level. The backend is responsible for:
- Business logic
- Data management (database, cache)
- Authorization and authentication (if not separated into a different service)
- Providing data and functions via API (REST, GraphQL, etc.)
The frontend is responsible for:
- User interface (HTML, CSS)
- User interaction (JavaScript/Ruby with Hotwire/etc.)
- Consuming data and calling backend functions via API
- Presenting data received from the backend
In the classic approach, the backend generates HTML pages, and the frontend only adds interactivity. In SPA (Single Page Application), the boundary is more distinct, as interaction occurs exclusively through the API.
Example:
# app/controllers/api/users_controller.rb
# Backend: Responsible for fetching the user from the database and formatting data for the frontend
class Api::UsersController < ApplicationController
def show
user = User.find(params[:id])
render json: user.as_json(only: [:id, :name, :email])
end
end
// app/javascript/packs/user_profile.js
// Frontend: Responsible for requesting data from the backend and displaying it
document.addEventListener('DOMContentLoaded', () => {
fetch(`/api/users/${userId}`) // userId obtained on the frontend
.then(response => response.json())
.then(data => {
document.getElementById('user-name').innerText = data.name;
document.getElementById('user-email').innerText = data.email;
});
});
In hybrid approaches like Hotwire, some rendering logic can be shifted to the backend, but interaction is still built on data or HTML fragment transfer via specific protocols (e.g., Turbo Streams).
# app/controllers/posts_controller.rb
# Backend: Renders HTML for Turbo Stream
class PostsController < ApplicationController
def create
@post = Post.new(post_params)
if @post.save
render turbo_stream: turbo_stream.append(:posts, partial: 'posts/post', locals: { post: @post })
else
# Error handling
end
end
private
def post_params
params.require(:post).permit(:body)
end
end
<!-- _post.html.erb -->
<!-- HTML fragment sent to the frontend via Turbo Stream -->
<div>
<%= post.body %>
</div>
The main principle: the backend provides data and services, and the frontend consumes and visualizes them for the user.