Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DevJournal Backend

A fully automated developer journal backend — write posts in your Telegram channel and they instantly appear on your website. Built with Express, TypeScript, and Supabase.


How it works

You post in Telegram → Bot Webhook → Express API → Supabase → React Frontend
  • Post a message with #hashtags → saved automatically as a post with tags
  • Edit a message → post content and tags update instantly
  • Delete a message → post is removed from the database

Stack

Layer Tech
Runtime Node.js 18+
Framework Express 4
Language TypeScript 5
Database Supabase (PostgreSQL)
Deployment Render

Project Structure

backend/
├── sql/
│   └── schema.sql                  ← Run in Supabase SQL Editor first
├── src/
│   ├── index.ts                    ← Express app, CORS, server setup
│   ├── supabaseClient.ts           ← Supabase singleton
│   ├── types/
│   │   └── index.ts                ← Shared TypeScript interfaces
│   ├── routes/
│   │   ├── posts.ts                ← CRUD API for posts
│   │   └── webhook.ts              ← Telegram webhook handler
│   ├── scripts/
│   │   └── setWebhook.ts           ← One-time script to register bot webhook
│   └── middleware/
│       └── errorHandler.ts         ← Global error + 404 handler
├── .env.example
├── package.json
└── tsconfig.json

Setup

1. Create a Supabase project

Go to supabase.com and create a new project.

2. Run the SQL schema

Supabase Dashboard → SQL Editor → paste sql/schema.sql → Run.

This creates the Post, Tag, and PostTag tables with indexes and RLS policies.

3. Get your Supabase credentials

Supabase Dashboard → Settings → API:

  • Project URLSUPABASE_URL
  • service_role secret key → SUPABASE_SERVICE_ROLE_KEY

⚠️ Never expose the service-role key on the frontend — it bypasses Row Level Security.

4. Create a Telegram bot

  1. Open Telegram → search @BotFather → send /newbot
  2. Follow the prompts and copy the bot token
  3. Add the bot as an Admin to your channel

5. Get your Telegram channel ID

Forward any message from your channel to @username_to_id_bot — it replies with your channel's numeric ID (e.g. -1001234567890).

6. Configure environment

cp .env.example .env

Fill in all values:

# Supabase
SUPABASE_URL=https://your-project-id.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key

# Server
PORT=3000
NODE_ENV=development
ALLOWED_ORIGINS=http://localhost:5173,http://localhost:3000

# Telegram
TELEGRAM_BOT_TOKEN=123456789:ABCdefGhIJKlmNoPQRstuVWXyz
TELEGRAM_CHANNEL_ID=-1001234567890
TELEGRAM_WEBHOOK_URL=https://your-deployed-app.onrender.com

7. Install and run

npm install
npm run dev        # development with hot reload
npm run build      # compile TypeScript
npm start          # run compiled output

8. Register the Telegram webhook

⚠️ Your server must be deployed with a public HTTPS URL before this step. For local testing use ngrok: ngrok http 3000

npm run webhook:set

You should see:

✅  Webhook registered: https://your-app.onrender.com/webhook/telegram
📋  Webhook info:
   URL            : https://your-app.onrender.com/webhook/telegram
   Pending updates: 0

Telegram Usage

Just post in your channel — the bot handles everything automatically.

What you do in Telegram What happens
Post "Learned about RLS today #Supabase #Backend" New post saved, tags extracted
Edit the message Post content and tags updated
Delete the message Post removed from database

Hashtags become filterable tags on your frontend. The # symbols are stripped from the post body automatically.


API Reference

GET /posts?max=9

Returns the latest N posts (default 9, max 50), newest first.

Response 200 OK

[
  {
    "createdAt": "2025-06-01T00:00:00Z",
    "post": "Learned about RLS today",
    "date_string": "June 1, 2025",
    "date": "2025-06-01",
    "post_link": "https://t.me/YourChannel/42",
    "PostTag": [
      { "postId": 1, "tagId": 4, "Tag": { "id": 4, "tag": "Supabase" } }
    ]
  }
]

GET /posts/:id

Returns a single post by ID.

POST /posts

Creates a new post manually.

{
  "post": "Markdown content here",
  "post_link": "https://t.me/...",
  "date_string": "June 10, 2025",
  "date": "2025-06-10",
  "tags": ["TypeScript", "React"]
}

PUT /posts/:id

Updates a post. All fields optional. tags array replaces existing tags.

DELETE /posts/:id

Deletes a post and its tag links (cascade).

GET /posts/tags/all

Returns all tags alphabetically.

POST /webhook/telegram

Telegram webhook endpoint — called automatically by Telegram, not manually.

GET /health

Health check → { "status": "ok", "timestamp": "..." }


Testing

Test the webhook manually (no Telegram needed)

curl -X POST http://localhost:3000/webhook/telegram \
  -H "Content-Type: application/json" \
  -d '{
    "update_id": 123456,
    "channel_post": {
      "message_id": 42,
      "chat": {
        "id": -1001234567890,
        "type": "channel",
        "title": "My Dev Journal",
        "username": "TerminalThoughts1"
      },
      "date": 1717000000,
      "text": "Test post from curl #Backend #TypeScript"
    }
  }'

Then verify it was saved:

curl http://localhost:3000/posts?max=9

Reset all data

Run in Supabase SQL Editor:

TRUNCATE TABLE "PostTag", "Post", "Tag" RESTART IDENTITY CASCADE;

Connecting the React Frontend

In JounalIntegration.tsx, set BASE_URL to your server address:

export const BASE_URL = "http://localhost:3000";                      // dev
// export const BASE_URL = "https://your-app.onrender.com";          // prod

Deployment (Render)

  1. Push to GitHub
  2. Render Dashboard → New Web Service → connect your repo
  3. Set build command: npm install && npm run build
  4. Set start command: npm start
  5. Add all environment variables from .env.example
  6. Deploy, then run npm run webhook:set to register the Telegram webhook

⚠️ Render's free tier spins down after 15 minutes of inactivity. Upgrade to a paid plan or switch to Railway/Fly.io for production use.


Future Features

  • Pagination (GET /posts?page=1&limit=9)
  • Full text search (GET /posts?search=supabase)
  • Media support (photos/videos from Telegram)
  • Post views counter
  • Pin a post
  • RSS feed (GET /feed.xml)
  • Scheduled posts

About

Express + TypeScript REST API for a developer journal that auto-syncs with a Telegram channel. Post, edit, or delete in Telegram — changes reflect instantly on your site. Powered by Supabase.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages