{{ post.title }}
Comments ({{ comments | length }})
{% if comments %}No comments yet.
{% endif %} {% if current_user.is_authenticated %} {% endif %}npx skills add https://github.com/aj-geddes/useful-ai-prompts --skill server-side-rendering
Server-Side Rendering Overview
Build server-side rendered applications using modern template engines, view layers, and data-driven HTML generation with caching, streaming, and performance optimization across Python, Node.js, and Ruby frameworks.
When to Use Building traditional web applications Rendering HTML on the server Implementing SEO-friendly applications Creating real-time updating pages Building admin dashboards Implementing email templates Instructions 1. Flask with Jinja2 Templates
from flask import Flask, render_template, request, jsonify from datetime import datetime
app = Flask(name)
@app.template_filter('currency') def format_currency(value): return f"${value:.2f}"
@app.template_filter('date_format') def format_date(date_obj): return date_obj.strftime('%Y-%m-%d %H:%M:%S')
@app.context_processor def inject_globals(): """Inject global variables into templates""" return { 'app_name': 'My App', 'current_year': datetime.now().year, 'support_email': 'support@example.com' }
@app.route('/') def index(): """Home page""" featured_posts = Post.query.filter_by(featured=True).limit(5).all() return render_template('index.html', featured_posts=featured_posts)
@app.route('/dashboard') @login_required def dashboard(): """User dashboard""" user_stats = { 'total_posts': current_user.posts.count(), 'total_views': sum(p.view_count for p in current_user.posts), 'total_followers': current_user.followers.count() }
recent_activity = current_user.get_activity(limit=10)
return render_template(
'dashboard.html',
stats=user_stats,
activity=recent_activity
)
@app.route('/posts/
# Increment view count
post.view_count += 1
db.session.commit()
# Get related posts
related = Post.query.filter(
Post.category_id == post.category_id,
Post.id != post.id
).limit(5).all()
return render_template(
'post.html',
post=post,
related_posts=related,
comments=post.comments.order_by(Comment.created_at.desc()).all()
)
@app.route('/search') def search(): """Search posts""" query = request.args.get('q', '') page = request.args.get('page', 1, type=int)
if not query:
return render_template('search.html', posts=[], query='')
posts = Post.query.filter(
Post.title.ilike(f'%{query}%') |
Post.content.ilike(f'%{query}%')
).paginate(page=page, per_page=20)
return render_template(
'search.html',
posts=posts.items,
total=posts.total,
query=query,
page=page
)
@app.route('/admin/posts/create', methods=['GET', 'POST']) @login_required @admin_required def create_post(): """Create new post""" if request.method == 'POST': title = request.form['title'] content = request.form['content'] category_id = request.form['category_id']
post = Post(
title=title,
slug=generate_slug(title),
content=content,
category_id=category_id,
author_id=current_user.id
)
db.session.add(post)
db.session.commit()
return redirect(url_for('view_post', slug=post.slug))
categories = Category.query.all()
return render_template('admin/create_post.html', categories=categories)
{% extends "base.html" %}
{% block title %}Dashboard - {{ app_name }}{% endblock %}
{% block content %}
{{ stats.total_posts }}
{{ stats.total_views | default(0) }}
{{ stats.total_followers }}
No recent activity.
{% endif %}{% endblock %}
{% extends "base.html" %}
{% block title %}{{ post.title }} - {{ app_name }}{% endblock %}
{% block content %}
No comments yet.
{% endif %} {% if current_user.is_authenticated %} {% endif %}{% endblock %}
const app = express();
// Set template engine app.set('view engine', 'ejs'); app.set('views', path.join(__dirname, 'views'));
// Middleware app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use(express.static(path.join(__dirname, 'public')));
// Local variables middleware app.use((req, res, next) => { res.locals.currentUser = req.user || null; res.locals.appName = 'My App'; res.locals.currentYear = new Date().getFullYear(); next(); });
// Routes app.get('/', (req, res) => { const posts = [ { id: 1, title: 'Post 1', excerpt: 'First post', slug: 'post-1' }, { id: 2, title: 'Post 2', excerpt: 'Second post', slug: 'post-2' } ];
res.render('index', { posts });
});
app.get('/posts/:slug', async (req, res) => { const { slug } = req.params; const post = await Post.findOne({ where: { slug } });
if (!post) {
return res.status(404).render('404');
}
const comments = await post.getComments();
const relatedPosts = await Post.findAll({
where: { categoryId: post.categoryId },
limit: 5
});
res.render('post', {
post,
comments,
relatedPosts
});
});
app.get('/dashboard', requireAuth, (req, res) => { const stats = { totalPosts: req.user.posts.length, totalViews: req.user.posts.reduce((sum, p) => sum + p.views, 0) };
res.render('dashboard', { stats });
});
app.listen(3000);
<%= comment.content %>
from flask_caching import Cache
cache = Cache(app, config={'CACHE_TYPE': 'redis'})
@app.route('/posts/
@app.route('/api/posts') @cache.cached(timeout=300) # Cache for 5 minutes def get_posts(): """Cached API endpoint""" posts = Post.query.filter_by(published=True).all() return jsonify([p.to_dict() for p in posts])
@app.route('/admin/posts/
# Clear cache
cache.delete_memoized(view_post, post.slug)
cache.delete_memoized(get_posts)
return redirect(url_for('view_post', slug=post.slug))
from django.shortcuts import render from django.views.generic import DetailView, ListView from django.db.models import Q from .models import Post, Comment
class PostListView(ListView): model = Post template_name = 'blog/post_list.html' context_object_name = 'posts' paginate_by = 10
def get_queryset(self):
return Post.objects.filter(published=True).order_by('-created_at')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['featured_posts'] = Post.objects.filter(featured=True)[:5]
return context
class PostDetailView(DetailView): model = Post template_name = 'blog/post_detail.html' context_object_name = 'post' slug_field = 'slug'
def get_queryset(self):
return Post.objects.filter(published=True)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['comments'] = self.object.comments.all()
context['related_posts'] = Post.objects.filter(
category=self.object.category
).exclude(id=self.object.id)[:5]
return context
{% extends "base.html" %}
{% block title %}Blog - {{ app_name }}{% endblock %}
{% block content %}
{{ post.excerpt }}
Read More{{ post.content|truncatewords:50 }}
No posts yet.
{% endfor %}{% endblock %}
Best Practices
✅ DO
Use template inheritance for DRY code
Implement caching for frequently rendered pages
Use template filters for formatting
Separate concerns between views and templates
Validate and sanitize all user input
Use context processors for global variables
Implement proper pagination
Use conditional rendering appropriately
Cache expensive queries
Optimize template rendering
❌ DON'T
Put business logic in templates
Use unbounded loops in templates
Execute database queries in templates
Trust user input without sanitization
Over-nest template inheritance
Use very long template files
Render sensitive data in templates
Ignore template caching opportunities
Use global variables excessively
Mix multiple concerns in one template
Complete Example
@app.route('/hello/
{{ comment.content }}