A simple neighborhood messaging app built in Python. This project runs a plain TCP backend, a browser-facing HTTP gateway, and a Supabase PostgreSQL persistence layer.
server.py— a plain TCP server that accepts text-based commands from clients.routes.py— parses TCP commands such asPOST,LIST,LISTJSON,GET,EXIT, andSHUTDOWN.bridge.py— an HTTP gateway that translates browser requests into TCP server commands.database.py— a Supabase PostgreSQL storage layer usingpsycopg2connection pooling.index.html— a static web UI that runs in the browser and interacts with the bridge.dump.sql— Supabase PostgreSQL schema migration for thepoststable.
- The TCP server stores and retrieves posts using
database.py. database.pyconnects to Supabase PostgreSQL throughDATABASE_URLorSUPABASE_DATABASE_URL.- The bridge serves the web UI at
http://localhost:8000/and keeps the/messagesAPI for browser POST and GET requests. - The browser UI does not need direct access to the TCP port.
- Create a Supabase project.
- Open the Supabase SQL editor and run
dump.sql. - Copy the PostgreSQL connection URI from Supabase Project Settings > Database > Connection string.
- Set
DATABASE_URLorSUPABASE_DATABASE_URLto that connection string. - Use the pooled connection string on port
6543for serverless deployments such as Render, Railway, or Fly.io.
The Supabase PostgreSQL posts table contains:
id— unique integer primary keyusername— sender nametype— category of the message, such asinfooralertmessage— the content texttimestamp— UNIX timestamp stored as a double-precision float
database.py exposes the same public methods used by server.py:
add_post(username, type_, message)→ returns a dict with the inserted postlist_posts(type_filter=None, limit=10)→ returns a list of dicts ordered oldest to newestget_post(id_)→ returns a dict orNone
- Open a terminal in the project folder.
- Install Python dependencies:
python -m pip install -r .\requirements.txt- Copy
.env.exampleto.envand add your Supabase PostgreSQL connection string:
copy .env.example .env- Start the TCP server:
python .\server.py- In a second terminal, start the HTTP bridge:
python .\bridge.py- Open your browser and go to:
http://localhost:8000/
- Use the form to post a new message, then click
Refreshto load the latest posts.
You can override the defaults with environment variables:
DATABASE_URLorSUPABASE_DATABASE_URL— Supabase PostgreSQL connection URISUPABASE_SCHEMA— PostgreSQL schema for thepoststable, defaultpublicSUPABASE_POSTS_TABLE— table name, defaultpostsDATABASE_SSL_MODE— PostgreSQL SSL mode, defaultrequireDATABASE_POOL_MIN— minimum PostgreSQL connection pool size, default1DATABASE_POOL_MAX— maximum PostgreSQL connection pool size, default10SERVER_IP— TCP server bind address, default0.0.0.0SERVER_PORTorPORT— TCP server port, default7000HTTP_PORT— bridge HTTP port, default8000HTTP_BIND— bridge bind address, default0.0.0.0TCP_SERVER_IP— backend TCP server host for the bridge, default127.0.0.1TCP_SERVER_PORTorTCP_PORT— backend TCP server port for the bridge, default7000ADMIN_TOKEN— optional token for theSHUTDOWNcommand
Example:
$env:DATABASE_URL = 'postgresql://postgres:[YOUR-PASSWORD]@db.[YOUR-PROJECT-REF].supabase.co:5432/postgres'
python .\server.pyRun this from the project root after setting DATABASE_URL or SUPABASE_DATABASE_URL:
python -c "from database import Database; db=Database(); post=db.add_post('tester','info','Test Supabase post'); print(post); print(db.list_posts()); print(db.get_post(post['id'])); db.close()"Start server.py, then use a socket client to connect to 127.0.0.1:7000.
With bridge.py running, open http://localhost:8000/ and confirm:
- the page loads
- you can submit a post
- the message list refreshes
A container image can bundle both services in one deployable unit.
Build the image from the project root:
docker build -t neighborhood-helpboard .Run the container locally exposing the bridge and TCP ports:
docker run --rm -p 8000:8000 -p 7000:7000 -e DATABASE_URL='postgresql://postgres:[YOUR-PASSWORD]@db.[YOUR-PROJECT-REF].supabase.co:5432/postgres' neighborhood-helpboardIf you want to override ports inside the container:
docker run --rm -p 9000:9000 -p 7001:7001 -e HTTP_PORT=9000 -e SERVER_PORT=7001 neighborhood-helpboardThis project is not a static-only website. It requires a running Python backend and cannot be published as a complete app on Netlify by itself.
Recommended free hosts for this project:
- Render.com
- Railway.app
- Fly.io
Render is the simplest choice for beginners because it can deploy your existing Dockerfile directly.
-
Push your repository to GitHub.
-
Create a free Render account.
-
Create a new
Web Serviceand connect your GitHub repository. -
Choose
Dockeras the environment so Render uses yourDockerfile. -
Set environment variables if needed:
DATABASE_URLHTTP_PORT=8000TCP_SERVER_IP=127.0.0.1TCP_SERVER_PORT=7000SERVER_PORT=7000
-
Deploy and open the generated URL.
Netlify can host only the static index.html file, but this app also needs bridge.py and server.py to run. For a complete working deployment, use Render, Railway, or Fly.io instead.
.envis ignored by Git. Use environment variables in production.- Supabase PostgreSQL connections require SSL, so
DATABASE_SSL_MODE=requireis used by default. - The backend creates the
poststable and indexes automatically on startup, butdump.sqlshould still be run once during project setup. - The TCP command protocol is unchanged, so the bridge keeps compatibility with the original design.
- Add authentication and request validation.
- Add better error handling for TCP/HTTP failures.
- Add pagination or filtering support on the UI.
- Convert
client.pyinto a shared client module for both TCP and HTTP access. - Add message deleting with an admin token.