Polymorphic Feed Item Rendering
Why it matters
A feed schema that only supports a single activity type (post) cannot evolve to include likes, comments, follows, or shares without a full schema migration. When type support is added ad-hoc through if/else chains in the renderer, each new type adds a branch, tests, and cognitive overhead — the component becomes a maintenance liability under ISO 25010:2011. More concretely, the absence of a type discriminator on the Activity model means you cannot query or filter by activity type, which blocks every notification and analytics feature that depends on distinguishing activity kinds.
Severity rationale
Medium because the maintainability impact is indirect — code still works for the single type — but adding any second activity type without this structure triggers a disruptive schema migration.
Remediation
Add a type discriminator field to your activity or post schema, then replace branching renderer logic with a component factory in components/feed/ActivityRenderer.tsx.
// Prisma schema
model Activity {
id String @id @default(cuid())
type String // 'post' | 'like' | 'comment' | 'follow'
userId String
targetId String?
content String?
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id])
}
// components/feed/ActivityRenderer.tsx
const renderers: Record<string, React.FC<{ activity: Activity }>> = {
post: PostActivity,
like: LikeActivity,
comment: CommentActivity,
follow: FollowActivity
}
export function ActivityRenderer({ activity }: { activity: Activity }) {
const Component = renderers[activity.type]
return Component ? <Component activity={activity} /> : null
}
This pattern lets you add new activity types by registering a new entry in renderers without touching the router or switch logic.
Detection
-
ID:
polymorphic-feed-items -
Severity:
medium -
What to look for: Enumerate all relevant files and Examine feed components and the Post/Activity schema. Check for support of multiple activity types: posts, comments, likes, shares, follows, reactions, etc. Look for either: (a) a type discriminator field (e.g.,
activity_type,kind), (b) a component factory pattern that routes render logic, or (c) a schema with different tables per activity type. Verify the component avoids excessiveifstatements for each type. -
Pass criteria: At least 1 implementation must be present. Multiple activity types are supported by the schema (evidenced by a
typefield, separate tables, or extensible design). Components use a factory or discriminator pattern to render different activity types cleanly. -
Fail criteria: Only one activity type (posts) is supported, or the rendering component is a giant
if/elseblock with hardcoded logic for each type. -
Skip (N/A) when: Feed only shows posts (single activity type).
-
Detail on fail:
"Post table has no type field; feed only supports post activities"or"FeedItem component has 20+ if/else branches for different activity types" -
Remediation: Use a polymorphic schema and factory component:
// Prisma schema model Activity { id String @id type String // 'post', 'like', 'comment', 'follow' userId String targetId String? // Post ID if type is 'like'/'comment' content String? createdAt DateTime user User @relation(fields: [userId], references: [id]) } // Component factory function ActivityRenderer({ activity }) { switch (activity.type) { case 'post': return <PostActivity activity={activity} /> case 'like': return <LikeActivity activity={activity} /> case 'comment': return <CommentActivity activity={activity} /> default: return null } }
External references
- iso-25010:2011 · maintainability — Modularity
Taxons
History
- 2026-04-18·v1.0.0·Initial import from community-social-engagement·automated