A very minimal pastebin type api.
- Python 58.8%
- Shell 18.2%
- HTML 16.9%
- JavaScript 5.4%
- Dockerfile 0.7%
|
|
||
|---|---|---|
| app | ||
| .env.example | ||
| .gitignore | ||
| claude.md | ||
| CLOUDFLARE_TUNNEL_SETUP.md | ||
| docker-compose.yml | ||
| Dockerfile | ||
| drafts-action.js | ||
| DRAFTS_ACTION_SETUP.md | ||
| pyproject.toml | ||
| pyrightconfig.json | ||
| README.md | ||
| requirements.txt | ||
| test.sh | ||
snipstore
A minimal personal pastebin service built with FastAPI. Store and share text snippets with markdown rendering support.
Features
- Create pastes with random or custom URL slugs
- Markdown rendering with syntax highlighting
- Copy-to-clipboard functionality
- Raw text access for each paste
- No expiration - pastes persist indefinitely
- Private paste listing with API key authentication
- File-based storage (no database required)
Setup
Prerequisites
- Docker and Docker Compose (for Docker deployment)
- uv (for local development)
- A secret API key for authentication
Installation
- Clone the repository:
git clone <repository-url>
cd snipstore
- Create a
.envfile from the example:
cp .env.example .env
- Edit
.envand set your API key:
API_KEY=your-secret-api-key-here
- Start the service:
docker-compose up -d
The service will be available at http://localhost:33333
Usage
Creating a Paste
With random slug:
curl -X POST http://localhost:33333/api/paste \
-H "Content-Type: application/json" \
-d '{
"api_key": "your-secret-api-key-here",
"content": "# Hello World\n\nThis is my paste content."
}'
With custom slug:
curl -X POST http://localhost:33333/api/paste \
-H "Content-Type: application/json" \
-d '{
"api_key": "your-secret-api-key-here",
"content": "# My Custom Paste",
"slug": "my-custom-slug"
}'
Response:
{
"url": "/p/my-custom-slug/",
"slug": "my-custom-slug"
}
Viewing a Paste
- Rendered view:
http://localhost:33333/p/{slug}/ - Raw text:
http://localhost:33333/p/{slug}/raw
Listing All Pastes
curl "http://localhost:33333/pastes/?api_key=your-secret-api-key-here"
Response:
[
{
"slug": "clever-ocean-dance",
"last_modified": "December 17, 2025 at 03:45 PM"
},
{
"slug": "my-custom-slug",
"last_modified": "December 17, 2025 at 02:30 PM"
}
]
Deleting a Paste
curl -X DELETE http://localhost:33333/api/paste/my-custom-slug \
-H "Content-Type: application/json" \
-d '{
"api_key": "your-secret-api-key-here"
}'
URL Structure
/- Returns 404 page/p/{slug}/- Rendered markdown view/p/{slug}/raw- Raw text content/pastes/- List all pastes (requires API key)/api/paste- Create or update paste (POST)/api/paste/{slug}- Delete paste (DELETE)
Configuration
Environment variables (set in .env):
| Variable | Default | Description |
|---|---|---|
API_KEY |
(required) | Secret key for API authentication |
DATA_DIR |
/data |
Directory for storing paste files |
MAX_PASTE_SIZE |
1048576 |
Maximum paste size in bytes (1MB) |
Data Storage
Pastes are stored as plain text files in the /data directory:
- File format:
{slug}.txt - Timestamps are tracked via filesystem metadata
- The
/datadirectory is mounted as a Docker volume for persistence
Development
Running Locally with uv
- Install uv if you haven't already:
curl -LsSf https://astral.sh/uv/install.sh | sh
- Sync dependencies:
uv sync
- Set environment variables:
export API_KEY=your-secret-api-key-here
export DATA_DIR=./data
- Run the server:
uv run uvicorn app.main:app --host 0.0.0.0 --port 33333 --reload
Adding Dependencies
To add new dependencies:
uv add <package-name>
To add development dependencies:
uv add --dev <package-name>
Testing
A comprehensive test suite is provided in test.sh. The tests use curl to verify all API endpoints.
Running Tests
- Start the server (in one terminal):
export API_KEY=test-key
export DATA_DIR=./data
uv run uvicorn app.main:app --host 0.0.0.0 --port 33333
- Run the tests (in another terminal):
export API_KEY=test-key
./test.sh
You can also customize the base URL:
BASE_URL=http://localhost:33333 API_KEY=test-key ./test.sh
Test Coverage
The test suite includes:
- Creating pastes with random and custom slugs
- Retrieving pastes (HTML and raw views)
- Overwriting existing pastes
- Listing all pastes
- Deleting pastes
- API key authentication (valid and invalid)
- Non-existent paste handling
- Invalid slug format validation
- Markdown rendering
Security Notes
- Keep your API key secret and secure
- The API key is required for creating, deleting, and listing pastes
- Slug validation ensures only alphanumeric characters and hyphens are allowed
- Maximum paste size is enforced to prevent abuse
License
MIT