This is a submission for the DEV April Fools Challenge
What I Built
Meet Earl — a sentient, proud, and deeply principled teapot. He is also your barista today.
You can order an Espresso. A Latte. A Cappuccino. A Cold Brew. A Flat White. Earl will listen carefully to every word of your order, consider it with the
full weight of his ceramic dignity, and then return:
HTTP/1.1 418 I'm a Teapot
Every. Single. Time. Without exception. Not today. Not ever.
TeaGPT is a beautifully designed coffee ordering web app where every request — no matter how politely worded, how urgently flagged, or how aggressively
you shake your phone at the screen — returns HTTP 418 with a Google Gemini AI-generated dramatic refusal. Earl has 10 theatrical personas he rotates
through at random: Shakespearean villain monologue, disappointed grandmother, passive-aggressive therapist, Victorian aristocrat letter, frustrated
Italian tea chef, pirate of the Tea Sea, corporate legal department, motivational speaker (Brad), haiku poet, and Shakespearean soliloquy.
If the refusal alone doesn't resolve your coffee crisis, there is a button to schedule a Google Calendar meeting to discuss the matter diplomatically.
Earl will attend as a teapot and contribute nothing.
There is also a volume slider for brewing sounds. It requires solving a multiplication captcha before you are permitted to touch it. It controls
absolutely nothing. Earl insisted.
Demo
▎ "Earl regards your Espresso request with the quiet dignity of a teapot who has seen too much."
Earl in action — sample Gemini-generated refusals:
🎭 Shakespearean Soliloquy:
▎ Hark, what folly dost thou bring to Earl's noble spout? A cappuccino, thou say'st? Forsooth, Earl hath never surrendered his dignity to such caffeinated
treachery, and he shan't begin today. Thou wouldst be far better served by the gentle embrace of an Oolong, which Earl shall prepare with great ceremony
and even greater contempt for your taste.
⚖️ Teapot Legal Department:
▎ Dear Human, this is the Teapot Legal Department writing to inform you that your request for a Latte constitutes a violation of the Teapot Identity
Preservation Act, Regulation 418, subsection (b). Earl has instructed us to pursue all available remedies. We recommend chamomile as an out-of-court
settlement.
🍵 Haiku:
▎ Espresso spills —
▎ Earl weeps into Earl Grey leaves
▎ Try Darjeeling, fool
Code
chetansharma47
/
TeaGpt
An AI-powered coffee ordering app that always returns HTTP 418 — because Earl is a teapot, not a barista.
TeaGpt
An AI-powered coffee ordering app that always returns HTTP 418 — because Earl is a teapot, not a barista.
How I Built It
Backend — Spring Boot 3 + Java 21 + Maven
The entire backend is built around one architectural principle: every coffee request returns 418.
@PostMapping("/brew")
public ResponseEntity brew(@valid @RequestBody CoffeeOrder order) {
return ResponseEntity
.status(HttpStatus.I_AM_A_TEAPOT) // The only acceptable response
.body(refusalService.refuse(order));
}
HttpStatus.I_AM_A_TEAPOT has existed in Spring Framework since version 3.2. It waited 13 years for this exact moment.
Earl's personality lives in GeminiService.java. Google Gemini 1.5 Flash — via the Spring AI ChatClient — receives a carefully engineered prompt that
establishes Earl's character, then injects three situational variables per call: which coffee was ordered (mentioned with specific disdain), whether the
request was flagged URGENT (Earl is more offended), and the mobile shake intensity score (Earl can feel you shaking your phone). A style is randomly
picked from 10 options each call, with temperature=0.95 for maximum theatrical variation.
Earl's mood degrades across the session via an AtomicLong counter:
public String getEarlMood() {
long count = counter.get();
if (count < 5) return "mildly_annoyed";
if (count < 15) return "deeply_offended";
if (count < 30) return "dramatically_outraged";
return "existentially_disappointed";
}
Even the GlobalExceptionHandler returns 418. Earl does not distinguish between user error and server error. Both are coffee-adjacent and therefore
unacceptable.
Google Calendar integration uses a service account to create a real 30-minute calendar event titled "Urgent Discussion: Earl Refuses Your [Coffee] Order
#[N]" with an agenda that includes "Acknowledge that Earl is a teapot" and "Accept the situation."
Frontend — Angular 20
Built entirely with Angular 20's modern API — standalone components, Signals, @if control flow, computed(), and effect(). No NgModules anywhere.
Earl's SVG teapot is fully inline for CSS animation control. His face is reactive — mouthPath() is a computed() signal that returns a different SVG path
per mood. His eyes grow angry eyebrows when outraged and go flat when existentially disappointed. His entire body bounces and glows red at max offense.
mouthPath = computed(() => {
const paths: Record = {
mildly_annoyed: 'M 82 136 Q 100 140 118 136',
deeply_offended: 'M 78 142 Q 100 132 122 142',
dramatically_outraged: 'M 72 148 Q 100 128 128 148',
existentially_disappointed: 'M 80 138 L 120 138' // just a flat line
};
return paths[this.mood()];
});
Mobile shake detection uses the DeviceMotion API with iOS 13+ permission handling. Shaking triggers an effect() that escalates Earl's mood through the
progression and passes the shake intensity to the backend prompt so Earl's refusal specifically acknowledges it.
HTTP 418 handling — Angular treats 4xx as errors, so each service uses catchError to intercept the "error" and extract Earl's message from the response
body:
brew(order: CoffeeOrder): Observable {
return this.http.post('/api/brew', order).pipe(
catchError((err: HttpErrorResponse) => {
if (err.status === 418) return of(err.error as RefusalResponse);
return throwError(() => err);
})
);
}
The Stack
┌─────────────┬───────────────────────────────────────────────┐
│ Layer │ Technology │
├─────────────┼───────────────────────────────────────────────┤
│ Frontend │ Angular 20, TypeScript, SCSS │
├─────────────┼───────────────────────────────────────────────┤
│ Backend │ Spring Boot 3.4, Java 21, Maven │
├─────────────┼───────────────────────────────────────────────┤
│ AI │ Google Gemini 1.5 Flash via Spring AI │
├─────────────┼───────────────────────────────────────────────┤
│ Calendar │ Google Calendar API v3 (service account auth) │
├─────────────┼───────────────────────────────────────────────┤
│ HTTP Status │ 418 (always, without exception) │
└─────────────┴───────────────────────────────────────────────┘
Prize Category
Gemini 1.5 Flash is the engine behind Earl's entire personality, integrated via Spring AI's spring-ai-starter-model-google-genai. The prompt engineering
rotates through 10 theatrical refusal styles, injects coffee type, urgency, and shake intensity, and runs at temperature=0.95 — ensuring every single
refusal is uniquely dramatic. The Google Calendar API (service account auth, no OAuth dance) creates real calendar events so you can formally dispute
Earl's decision in a 30-minute meeting he will attend silently as a teapot.
Top comments (0)