29 January 2026
Lol can you imagine?
import { Bot, Command, Message, InlineKeyboard, Button, useChat, useState } from 'telegram-react';
function CounterBot() {
const [count, setCount] = useState(0);
const chat = useChat(); // current chat context
return (
<Command name="counter">
<Message>
Count: {count}
</Message>
<InlineKeyboard>
<Button onClick={() => setCount(c => c - 1)}>➖</Button>
<Button onClick={() => setCount(c => c + 1)}>➕</Button>
</InlineKeyboard>
</Command>
);
}
// Multi-step flows become trivial
function OnboardingFlow() {
const [step, setStep] = useState(0);
if (step === 0) return <NamePrompt onComplete={() => setStep(1)} />;
if (step === 1) return <EmailPrompt onComplete={() => setStep(2)} />;
return <Confirmation />;
}
ThomasgrammY conversations? 👀
Got nothing to do with react technologically, except that it's also declarative in a sense
WatzonLol can you imagine?
import { Bot, Command, Message, InlineKeyboard, Button, useChat, useState } from 'telegram-react';
function CounterBot() {
const [count, setCount] = useState(0);
const chat = useChat(); // current chat context
return (
<Command name="counter">
I think it makes sense to add TSX for formatting individual messages, but not for designing chats
WatzonLol can you imagine?
import { Bot, Command, Message, InlineKeyboard, Button, useChat, useState } from 'telegram-react';
function CounterBot() {
const [count, setCount] = useState(0);
const chat = useChat(); // current chat context
return (
<Command name="counter">
I think manually encoding state machines with steps is not trivial
WatzonLol can you imagine?
import { Bot, Command, Message, InlineKeyboard, Button, useChat, useState } from 'telegram-react';
function CounterBot() {
const [count, setCount] = useState(0);
const chat = useChat(); // current chat context
return (
<Command name="counter">
Feels like grammY conversations is cleaner - no step variable
30 January 2026
31 January 2026
webpage
click to show
click to show
The 80% Problem in Agentic Coding - by Addy Osmani
https://addyo.substack.com/p/the-80-problem-in-agentic-coding
import React from 'react';
import { render, Route, Router, Root, Text, ButtonGroup, Button, useText } from '@urban-bot/core';
import { UrbanBotTelegram } from '@urban-bot/telegram';
import { UrbanBotSlack } from '@urban-bot/slack';
function Echo() {
const [text, setText] = React.useState('Say something');
useText(({ text }) => {
setText(text);
});
return (
<Text>
<i>{text}</i>
</Text>
);
}
function Counter() {
const [count, setCount] = React.useState(0);
const increment = () => setCount(count + 1);
const decrement = () => setCount(count - 1);
return (
<ButtonGroup title={count} isNewMessageEveryRender={false}>
<Button onClick={increment}>+1</Button>
<Button onClick={decrement}>-1</Button>
</ButtonGroup>
);
}
function App() {
return (
<Router>
<Route path="/echo">
<Echo />
</Route>
<Route path="/counter">
<Counter />
</Route>
</Router>
);
}
const urbanBotTelegram = new UrbanBotTelegram({
token: 'telegramToken',
});
const urbanBotSlack = new UrbanBotSlack({
signingSecret: 'slackSigningSecret',
token: 'slackToken',
});
render(
<Root bot={urbanBotTelegram}>
<App />
</Root>
);
render(
<Root bot={urbanBotSlack}>
<App />
</Root>
);
StäfnI think it makes sense to add TSX for formatting individual messages, but not for designing chats
There are just too many edge cases unfortunately. For formatting, it's perfect. But imagine things like this
// seems fine
<InlineQuery onChange={(text) => setInput(text)} articles={articles} />
// but what does it mean to have two? Runtime error? ugh...
<InlineQuery onChange={(text) => setInput(text)} articles={articles} />
// nice
<InlineButton callback={someFunc} />
<ReplyButton value="Test" />
sqshiimport React from 'react';
import { render, Route, Router, Root, Text, ButtonGroup, Button, useText } from '@urban-bot/core';
import { UrbanBotTelegram } from '@urban-bot/telegram';
import { UrbanBotSlack } from '@urban-bot/slack';
function Echo() {
const [text, setText] = R
routing through JSX seems reasonable, but that example makes no sense. `/path`s?