HomeTom - CS

Sunday, June 7, 2026

Add websocket support on Bluehost Ubuntu VPS for Django App to talk to OpenAI voice API

tee /etc/systemd/system/uvicorn.service > /dev/null << 'EOF'

Install Claude Code on ubuntu VPS of Bluehost

Trying to install claude code on bluehost vps with "curl -fsSL https://claude.ai/install.sh | bash" freezed the machine. the curl -fsSL https://claude.ai/install.sh | bash script hanging or freezing the machine during the final stages of a Linux installation is a documented issue.

The script frequently hangs at the Finalizing installation... step. This is because the downloaded Claude binary executes an internal loop to automatically scan, detect, and rewrite shell files (like .bashrc or .zshrc) to insert itself into your system PATH. In restricted virtual private server (VPS) environments like Bluehost—where terminal TTY inputs, file locks, or strict security permissions block background configuration rewrites—this loop gets permanently stuck and consumes available server resources.


You can easily bypass the broken native script by using the traditional, highly reliable Node Package Manager (npm) installation path.

 

How to Install Claude Code Safely via npm

Because Bluehost VPS servers typically run standard Linux environments, installing via npm avoids the buggy shell-rewriting binary wrapper entirely. [1]

1. Install Node.js and npm (if not already present on your VPS): 

 sudo apt update && sudo apt install -y nodejs npm

2. Configure npm to install globally without root permissions (highly recommended to avoid EACCES security lockouts):

mkdir -p ~/.npm-global
npm config set prefix '~/.npm-global'
 

3. Manually add the new path to your profile file (manually doing what the frozen script failed to do):

echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
  

4. Install Claude Code via npm:

npm install -g @anthropic-ai/claude-code
 

5. Turn off the buggy auto-updater (the native background auto-updater can trigger the same system freeze later on):

echo 'export DISABLE_AUTOUPDATER=1' >> ~/.bashrc
source ~/.bashrc
 

6. Launch and authenticate:

claude
 

Saturday, June 6, 2026

Install PostgreSQL on Mac

Documentation: https://www.postgresql.org/docs/ 

Download: https://www.postgresql.org/download/ 

Installation log: 

$ brew install postgresql@18
✔︎ JSON API cask.jws.json                                                      Downloaded   16.9MB/ 16.9MB
✔︎ JSON API formula.jws.json                                                   Downloaded   33.2MB/ 33.2MB
Inspect the formula dependency plan before installing with `brew install --ask`.
Enable ask mode by setting `HOMEBREW_ASK=1`.
Hide these hints with `HOMEBREW_NO_ENV_HINTS=1` (see `man brew`).
==> Fetching downloads for: postgresql@18 
✔︎ Bottle Manifest postgresql@18 (18.4)                                        Downloaded   30.5KB/ 30.5KB
✔︎ Bottle ca-certificates (2026-05-14)                                         Downloaded  112.1KB/112.1KB
✔︎ Bottle Manifest openssl@3 (3.6.2)                                           Downloaded   12.0KB/ 12.0KB
✔︎ Bottle postgresql@18 (18.4)                                                 Downloaded   20.8MB/ 20.8MB
✔︎ Bottle openssl@3 (3.6.2)                                                    Downloaded   10.1MB/ 10.1MB
==> Installing dependencies for postgresql@18: ca-certificates and openssl@3
==> Installing postgresql@18 dependency: ca-certificates
==> Pouring ca-certificates--2026-05-14.all.bottle.tar.gz
==> Regenerating CA certificate bundle from keychain, this may take a while...
🍺  /usr/local/Cellar/ca-certificates/2026-05-14: 4 files, 200.9KB
==> Installing postgresql@18 dependency: openssl@3
==> Pouring openssl@3--3.6.2.tahoe.bottle.tar.gz
🍺  /usr/local/Cellar/openssl@3/3.6.2: 7,627 files, 38MB
==> Installing postgresql@18
==> Pouring postgresql@18--18.4.sonoma.bottle.1.tar.gz
==> /usr/local/Cellar/postgresql@18/18.4/bin/initdb --locale=en_US.UTF-8 -E UTF-8 /usr/local/var/postgres
==> Caveats
This formula has created a default database cluster with:
  initdb --locale=en_US.UTF-8 -E UTF-8 /usr/local/var/postgresql@18

When uninstalling, some dead symlinks are left behind so you may want to run:
  brew cleanup --prune-prefix

To start postgresql@18 now and restart at login:
  brew services start postgresql@18
Or, if you don't want/need a background service you can just run:
  LC_ALL="en_US.UTF-8" /usr/local/opt/postgresql@18/bin/postgres -D /usr/local/var/postgresql@18
==> Summary
🍺  /usr/local/Cellar/postgresql@18/18.4: 3,871 files, 74.1MB
==> Running `brew cleanup postgresql@18`...
Disable this behaviour by setting `HOMEBREW_NO_INSTALL_CLEANUP=1`.
Hide these hints with `HOMEBREW_NO_ENV_HINTS=1` (see `man brew`).
==> Caveats
==> postgresql@18
This formula has created a default database cluster with:
  initdb --locale=en_US.UTF-8 -E UTF-8 /usr/local/var/postgresql@18

When uninstalling, some dead symlinks are left behind so you may want to run:
  brew cleanup --prune-prefix

To start postgresql@18 now and restart at login:
  brew services start postgresql@18
Or, if you don't want/need a background service you can just run:
  LC_ALL="en_US.UTF-8" /usr/local/opt/postgresql@18/bin/postgres -D /usr/local/var/postgresql@18

 

Operations: 

  - show services installed via brew: brew services list 

  - start postgresql: brew services start postgresql@18
  - psql postgres
  - \?, \dt (show tables), \du (show users), \l (\list : show databases)
  - \c (\connect : connect to a database)
  - \dn : show schemas
  - \dt *.* : show tables in all schemas
  - select * from information_schema.sql_features;
  - CREATE TABLE users (
      id SERIAL PRIMARY KEY,
      name TEXT NOT NULL
    );
  - INSERT INTO users (name) VALUES ('Alice'), ('Bob'), ('Charlie');
  - select * from users;
  - \d users; (check table structure) 

Thursday, April 16, 2026

Card shuffling problem

A card shuffling algorithm is a method for randomly permuting a deck of cards so that every ordering is equally likely (in a “good” shuffle).

The most important and widely used algorithm is:

Fisher–Yates Shuffle (a.k.a. Knuth Shuffle)

This is the gold standard for unbiased shuffling.

Idea

You go through the deck from the last card to the first, and for each position, swap it with a randomly chosen earlier (or same) position.

Algorithm (array-based deck)

Let A be an array of n cards (array index: [0, ..., n-1]):

for i from n - 1 down to 1:
j = random integer such that 0 ≤ j ≤ i
swap A[i] and A[j]

Why it works

  • Each card has an equal probability of ending in any position.
  • It avoids subtle bias found in naive shuffles (like sorting with random comparator).

Complexity

  • Time: O(n)
  • Space: O(1) (in-place)

Variants you might see

1. Inside-out Fisher–Yates

Useful when building a shuffled array from scratch:

for i from 0 to n-1:
j = random integer in [0, i]
A[i] = A[j]
A[j] = current element

2. Riffle shuffle (card-deck realistic)

Models human shuffling:

  • Split deck into two halves
  • Interleave them probabilistically

Used in probability studies, but needs many repeats (~7 riffle shuffles) to approximate randomness.


Practical note

In most programming languages:

  • Use a built-in shuffle (e.g., random.shuffle in Python), which implements Fisher–Yates.


Monday, April 13, 2026

Avoid auto-zoom in mobile browser

Question: with a html5 based self-adapted web application on mobile, if click in a textbox, it zoom in. How to avoid zoom in and always keep screen fully fit?

This is a classic mobile browser behavior (especially on iOS Safari and Chrome on Android): when a text input is focused, the browser auto-zooms if it thinks the text is too small.

 

ChatGPT answer: 

✅ The main cause

Auto-zoom usually happens when:

  • The font size of the <input> or <textarea> is less than 16px

✅ Fix #1 (Best & recommended)

Set the font size of all input fields to at least 16px:

input, textarea, select {
font-size: 16px;
}

This alone prevents zoom on most mobile browsers.


⚠️ Fix #2 (Viewport meta tag)

You can also control zoom behavior via the viewport:

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

But be careful:

  • user-scalable=no disables pinch zoom entirely (bad for accessibility)
  • Apple (Safari) may ignore some of these settings

✅ Fix #3 (iOS-specific trick)

If you must use smaller font sizes visually, you can fake it:

input {
font-size: 16px;
transform: scale(0.9);
transform-origin: left top;
}

This keeps the logical font size ≥16px while appearing smaller.


✅ Fix #4 (Prevent layout shift)

Also ensure your layout doesn’t resize oddly:

html {
-webkit-text-size-adjust: 100%;
}

🧠 Summary

  • ✔ Best solution: use font-size: 16px or larger
  • ✔ Avoid disabling zoom unless absolutely necessary
  • ✔ Use viewport tweaks carefully
  • ✔ iOS Safari is the main browser enforcing this behavior

If you want, tell me your layout/framework (React, Vue, plain HTML), and I can give you a cleaner drop-in fix.

plain html

Got it—since you’re using plain HTML, you can fix this cleanly with just a couple of tweaks.


✅ The simplest working solution

1. Set input font size to at least 16px

This is the key fix (especially for iOS Safari):

<style>
input, textarea, select {
font-size: 16px;
}
</style>

👉 This alone prevents the zoom-in when focusing inputs on most mobile browsers.


2. Add a proper viewport meta tag

<meta name="viewport" content="width=device-width, initial-scale=1">

✔ Keeps your layout responsive
✔ Avoids unnecessary scaling issues
❌ Don’t add user-scalable=no unless you really want to disable zoom entirely


⚠️ If you want smaller-looking inputs (optional)

If 16px feels too big visually, you can “fake” a smaller size:

<style>
input {
font-size: 16px;
transform: scale(0.9);
transform-origin: left top;
}
</style>

✅ Full minimal example

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">

<style>
body {
margin: 0;
padding: 20px;
}

input {
font-size: 16px;
padding: 10px;
width: 100%;
box-sizing: border-box;
}
</style>
</head>
<body>

<input type="text" placeholder="Tap me (no zoom)" />

</body>
</html>

🧠 Why this works

Mobile browsers (again, mainly iOS Safari) auto-zoom when:

  • Text is too small to read comfortably (<16px)

So by meeting that threshold, the browser stops helping you—which is exactly what you want here.


If it’s still zooming after this, tell me:

  • your exact CSS for the input
  • or share a snippet

There are a couple of edge cases (like inherited font sizes or transforms) I can help debug quickly.

Monday, April 6, 2026

Productionize a Django website

 Recommended minimal permissions of files in a Django site:

# Database
sudo chown www-data:www-data db.sqlite3
sudo chmod 664 db.sqlite3

# DB directory
sudo chown www-data:www-data .
sudo chmod 775 .

# Static/media (if needed)
sudo chown -R www-data:www-data static media 

Blog Archive

Followers