pack.page is a privacy-focused URL shortener that emphasises conciseness and simplicify in generating easily shareable URLs and collecting aggregated ethical metrics on user traffic.
To start shortening, go to pack.page or packpage.dev (for the development server).
The supported public domains as of 24 April 2025 and as defined in as an environment variable PUBLIC_HOSTS as
comma-separated values.
Private domain customers are entirely managed via the API within the DomainAPIMap model in the database.
Install requirements in a virtual environment and runserver using uvicorn:
uvicorn main:app --reload --port=8001
To use another port make sure to change the port in your .env file for PRINCIPAL_HOST
Production Mode:
uvicorn main:app --host 0.0.0.0 --port ${PORT:-8080}
If you are setting up a new database, you will need to run the following commands:
The settings file holds information about the models using Tortoise ORM:
- Run Aerich setup using:
aerich init -t aerich_conf.tortoise_config - Run initial migration using:
aerich init-db - Run makemigration using:
aerich migrate --name "migration message" - Run migrate using:
aerich upgrade
TEST using pytest:
pytestIn theory you can query any of the TLDs that are hosted on the server, but there are some differences:
-
If you choose a TLD that is not the principal domain that you get redirected to on the web client (e.g. pack0.page -> pack.page), you will automatically generate a link under that TLD.
-
If you choose a TLD that is the principal domain, your 'host' preference in the JSON request will be accepted if provided. If no preference is provided, the server will randomly select a TLD from the list of TLDs that are hosted on the server.
You can make a POST APP/JSON request to the following endpoint in the following format:
f"https://{PRINCIPAL_HOST}/ify" with the following JSON parameters:
- URL (mandatory field)
- mode 0,1,2,3 (optional field)
- host (optional field)
- passphrase (optional field)
Note that host field supports both public and private domains. If private, the server will expect an API key in the x-api-key header which it will validate against the DomainAPIMap model in the database.
The response will return a string object of the domain and link_id.
Development Mode:
npm run tw:dev
Production Mode:
npm run tw:prod
Static files are all files within the static directory of the project. The local static files are used for development and the remote static files are used for production served by Google Cloud Storage when
ENV_TYPE=prod.
Ensure that you update the remote static files when deploying to production as there is no automatic mechanism for this.
For adding a NEW language:
pybabel init -i messages.pot -d translations -l <LANG>
To make messages:
pybabel extract -F babel.cfg -o messages.pot .- For each language:
pybabel update -i messages.pot -d translations -l <LANG>
To compile:
pybabel compile -d translations