Samuel Edusa MD

< Back to list of posts

Building a Paste App: From Web to Phone

As a developer, I often find myself needing to quickly transfer snippets of text from my computer to my phone. Whether it's a code snippet, a URL, or just a quick note, the process of copying and pasting between devices can be cumbersome. That's why I decided to build a simple yet effective paste app that allows me to send information directly from a website to my phone. In this blog post, I'll walk you through my thought process and the key components of this project.

The Concept

The core idea was to create a web application with a clean, user-friendly interface that would allow me to:

  1. Input a title and message
  2. Send this information to my phone with a single click
  3. View the sent information on my phone in a readable format

To achieve this, I decided to leverage the Telegram messaging platform, which offers a robust API for sending messages to specific chats or channels.

flow A sketch of the application flow

Technical Stack

For this project, I chose the following technologies:

  • React: For building a responsive and interactive user interface
  • styled-components: For creating modular and reusable CSS-in-JS styles
  • Telegram Bot API: For sending messages from the web app to my phone

Key Components

1. User Interface

The UI consists of a sticky note-like component with two main input fields:

  • A title input (NoteInput)
  • A message textarea (NoteTextarea)

I used styled-components to create a visually appealing and responsive design that works well on both desktop and mobile devices.

ui User interface for the paste app

2. State Management

I utilized React's useState hook to manage the state of the title and message inputs:

const [title, setTitle] = useState(''); const [message, setMessage] = useState('');

3. Date and Time Display

To add context to each paste, I implemented a real-time date and time display using the useEffect hook:

useEffect(() => { const updateDateTime = () => { const now = new Date(); setCurrentDateTime(now.toLocaleString()); }; updateDateTime(); const timer = setInterval(updateDateTime, 1000); return () => clearInterval(timer); }, []);

4. Sending Messages to Telegram

The core functionality is implemented in the sendToTelegram function. This function:

  1. Cleans and escapes the input text to prevent XSS attacks
  2. Formats the message with HTML tags for better readability
  3. Sends a POST request to the Telegram Bot API.
    NOTE: Avoid exposing sensitive credentials (token and chat_id) in client-side code. Instead of making direct API calls to Telegram from the frontend, implement a secure middleware layer - either a proxy server or backend API - to handle authentication and protect your secrets. In this implementation, I used Netlify Functions as a serverless solution to securely manage API calls.

sendToTelegram (front end code)

const sendToTelegram = () => { // Clean and escape the title and message const cleanedTitle = cleanText(title); const cleanedMessage = cleanText(message); const escapedTitle = escapeHtml(cleanedTitle); const escapedMessage = escapeHtml(cleanedMessage); fetch('/.netlify/functions/send-telegram', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ title: escapedTitle, message: escapedMessage, dateTime: currentDateTime, }), }) .then((response) => { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.json(); }) .then((data) => { if (data.success) { setTitle(''); setMessage(''); alert('Message sent successfully!'); } else { throw new Error(data.error || 'Unknown error occurred'); } }) .catch((error) => { console.error('Error sending message:', error); alert(`Error sending message: ${error.message}`); }); };

send-telegram (serverless function)

const axios = require('axios'); exports.handler = async function(event, context) { if (event.httpMethod !== 'POST') { return { statusCode: 405, body: 'Method Not Allowed' }; } const { title, message, dateTime } = JSON.parse(event.body); const telegram_bot_token = process.env.TELEGRAM_BOT_TOKEN; const telegram_chat_id = process.env.TELEGRAM_CHAT_ID; if (!telegram_bot_token || !telegram_chat_id) { return { statusCode: 500, body: JSON.stringify({ error: 'Missing Telegram configuration' }) }; } const telegram_message = `<b>${title}</b>\n\n<pre><code>${message}</code></pre>\n\n<i>${dateTime}</i>`; try { const response = await axios.post(`https://api.telegram.org/bot${telegram_bot_token}/sendMessage`, { chat_id: telegram_chat_id, text: telegram_message, parse_mode: 'HTML' }); if (response.data.ok) { return { statusCode: 200, body: JSON.stringify({ success: true }) }; } else { throw new Error(response.data.description || 'Unknown error occurred'); } } catch (error) { console.error('Error sending message:', error); return { statusCode: 500, body: JSON.stringify({ error: `Error sending message: ${error.message}` }) }; } };

Screenshot of message being sent to Telegram chat

proof Note sent to private Telegram chat with message body formatted to allow easier copying of code snippets

5. Security Considerations

To enhance security, I implemented two important functions:

  • cleanText: Removes non-printable characters (except newlines and spaces) and trims the input
  • escapeHtml: Escapes special HTML characters to prevent XSS attacks

Conclusion

Building this paste app has significantly streamlined my workflow, allowing me to quickly transfer information from my computer to my phone. The combination of React for the frontend and the Telegram Bot API for message delivery provides a seamless and efficient solution.

Future improvements could include:

  • Adding authentication to make the app more secure
  • Implementing a history feature to view past pastes
  • Adding support for file uploads