Notemod-selfhosted Help (v1.0.2)

1. What is Notemod-selfhosted?

Notemod-selfhosted is a self-hosted edition based on the original Notemod (static UI), specialized for running on your own server with a single JSON file as the source of truth.

It was developed to enable smooth text sharing between a Windows PC and an iPhone, without relying on external services.

Using your own web server helps minimize external dependencies.

Key features

  • No GitHub / Gist dependency (everything is stored in data.json on your server)
  • Provides sync + APIs using PHP (designed for iOS Shortcuts and external tool integrations)
  • Includes a Windows app (ClipboardSender) that sends clipboard text to Notemod
  • Access logging supports two modes (configurable ON/OFF):
  • raw file logs
  • Notemod “Logs” category logs
  • Automatically creates .htaccess in notemod-data/, config/, and logs/ to block direct access
  • The read API supports pretty=2 to return plain text only (body-only)

2. Directory structure (default)

public_html/
├─ index.php                  # Notemod UI
├─ logger.php                 # access logging (file / Notemod logs)
├─ notemod_sync.php           # sync endpoint (save/load)
├─ api/
│  ├─ api.php                 # add note
│  ├─ read_api.php            # read API
│  └─ cleanup_api.php         # delete notes in a category (admin)
├─ notemod-data/
│  └─ data.json               # single data source (runtime)
├─ config/
│  ├─ config.php              # secrets + common settings (DO NOT COMMIT)
│  └─ config.api.php          # API tokens + paths (DO NOT COMMIT)
└─ robots.txt                 # block crawlers (recommended)
  • config/ and api/ are expected to be at the same level as index.php.
  • If you change the structure, update the PHP paths accordingly.

3. Quick start (minimal setup)

3.1 Upload to your server

Upload the whole repository to your public web directory.
Example: public_html/

3.2 Create config files (IMPORTANT)

Rename and edit:

  • config/config.sample.phpconfig/config.php
  • config/config.api.sample.phpconfig/config.api.php

Roles:

  • config.php: SECRET, timezone, logger settings, etc. (sensitive)
  • config.api.php: API tokens, data.json path, etc. (sensitive)

Warning: Never commit config/config.php or config/config.api.php to GitHub.
Manage them locally / on production only, and keep them in .gitignore.

3.3 Initialize (first run only)

Open the public URL in a browser to load Notemod.
Some browsers may show a one-time initial loading error—continue anyway.

Select the UI language and create your first category. This will create:

  • notemod-data/data.json (initial snapshot)
  • notemod-data/.htaccess (auto, blocks direct access)
  • config/.htaccess (auto, blocks direct access)
  • logs/ and logs/.htaccess (auto, only when file logging is enabled)

4. Security (very important)

4.1 Strongly recommended: Basic Auth

Running with tokens only is not recommended. Use at least one (ideally both):

  • Basic Auth for the whole site and /api/ (by default /api/ is accessible)
  • IP restriction if you can use fixed IPs

4.2 Auto-generated .htaccess (blocks direct access)

If .htaccess is missing in protected directories, Notemod-selfhosted generates the following:

<IfModule mod_authz_core.c>
  Require all denied
</IfModule>
<IfModule !mod_authz_core.c>
  Order allow,deny
  Deny from all
</IfModule>

Targets (depending on environment/settings):

  • notemod-data/ (protects data.json)
  • config/ (protects secrets)
  • logs/ (protects access logs)

Some shared hosts may disable or limit .htaccess.
In that case, Basic Auth is your last line of defense.

4.3 robots.txt (anti-indexing)

A robots.txt is included to reduce the chance of being indexed by search engines.

  • Note: robots is only a “polite request” and does not stop malicious access
    → Basic Auth / IP restrictions are the real protection

5. data.json structure (important)

In Notemod, categories and notes are stored as JSON strings inside data.json.

Example:

{
  "categories": "[{...},{...}]",
  "notes": "[{...},{...}]",
  "selectedLanguage": "EN"
}

PHP requires double-decoding:

  • First decode data.json with json_decode()
  • Then decode $data['notes'] with json_decode()

6. Configuration files

6.1 config/config.php (common settings / secrets)

Examples (based on the sample file):

  • SECRET: token for sync (recommended 16+ chars) The term “SECRET” is merely decorative and is planned to be discontinued in the future.
  • TIMEZONE: e.g. Asia/Tokyo
  • DEBUG: true writes logs like _sync_debug.log
  • INITIAL_SNAPSHOT: initial data
  • Logger settings
  • LOGGER_FILE_ENABLED (file logs ON/OFF)
  • LOGGER_NOTEMOD_ENABLED (Notemod Logs category ON/OFF)
  • LOGGER_LOGS_DIRNAME (e.g. logs / logs1)

6.2 config/config.api.php (API settings / secrets)

Examples:

  • EXPECTED_TOKEN: standard API token
  • ADMIN_TOKEN: cleanup token (use a strong value)
  • DATA_JSON: path to notemod-data/data.json
  • DEFAULT_COLOR: default color for created categories/notes
  • CLEANUP_BACKUP_ENABLED: create a backup before cleanup (ON/OFF)

7. logger.php (unified access logging)

Two logging modes are supported (configurable ON/OFF):

  1. Raw file log: /logs/access-YYYY-MM.log
  2. Notemod Logs category: a monthly note access-YYYY-MM inside category Logs

7.1 Logs category rules

  • Category name: Logs
  • Monthly note: access-YYYY-MM
  • Append style: prepend to the top (newest first)
  • read_api.php?action=latest_note always excludes Logs
    (so you can fetch the latest “normal note” easily)

8. notemod_sync.php (server sync: save/load)

8.1 Responsibilities

  • action=save: saves the JSON string received from the client
  • action=load: returns the JSON string stored on the server
  • On first run: if data.json is missing, create it using INITIAL_SNAPSHOT
  • If missing: generate .htaccess in notemod-data/ and config/ (blocks direct access)

8.2 Required parameters

  • token: SECRET in config.php
  • action: save / load

9. api.php (Add Note API)

Endpoint: /api/api.php

Parameters

ParameterRequiredDescription
tokenEXPECTED_TOKEN
textNote body (multi-line allowed)
titleoptionalDefaults to timestamp if omitted
categoryoptionalDefaults to INBOX

Behavior

  • If category is missing, INBOX is created automatically
  • text is stored as HTML (newlines → <br>, XSS-safe via htmlspecialchars)
  • Returns JSON response

Example

https://YOUR_SITE/api/api.php?token=EXPECTED_TOKEN&category=Memo&text=AAA

10. read_api.php (Read API)

Endpoint: /api/read_api.php

10.1 Available actions

  • action=list_categories
  • action=list_notes
  • action=latest_note (always excludes the Logs category)
  • action=get_note (one note by category + title)

10.2 pretty options

  • pretty=1: pretty-printed JSON
  • pretty=2: for latest_note / get_note, returns plain text body only
  • <br> → newline
  • strips HTML tags
  • decodes HTML entities
  • normalizes newlines

Example:

https://YOUR_SITE/api/read_api.php?token=EXPECTED_TOKEN&action=get_note&category=Manual&title=v1.0.0&pretty=2

11. cleanup_api.php (Dangerous: delete all notes in a category)

Endpoint: /api/cleanup_api.php

Behavior

  • POST only
  • Requires confirm=YES (except dry_run=1 is allowed)
  • Uses ADMIN_TOKEN (fallback: EXPECTED_TOKEN)
  • If CLEANUP_BACKUP_ENABLED is ON, creates data.json.bak-YYYYmmdd-HHMMSS first

Backup

  • When backups are enabled in cconfig.api.php, a backup file is created when a delete operation is executed.
  • In addition to exported text files, you can also import from backup files.

Delete all backups

  • The token is ADMIN_TOKEN (or falls back to EXPECTED_TOKEN)
  • Use purge_bak=1 (or purge_bak=true)
  • Add dry_run=1 to return only the list of targets without deleting them
  • When running without dry_run, confirm=YES is still required as before

Delete all logs (.log files in the logs/ directory)

  • The token is ADMIN_TOKEN (or falls back to EXPECTED_TOKEN)
  • Use purge_log=1 (or purge_log=true)
  • Add dry_run=1 to return only the list of targets without deleting them
  • When running without dry_run, confirm=YES is still required as before

12. Basic Auth and calling the APIs

12.1 Accessing via browser

When Basic Auth is enabled, browsers typically prompt for username/password. Enter them to proceed.

The https://user:pass@host/... format is deprecated and may be blocked by modern browsers.

12.2 Recommended: iOS Shortcuts

With “Get Contents of URL”:

  • Header: Authorization: Basic base64(user:pass)
  • Query/body: token, action, etc.

If nothing happens, check:

  • Header is exactly Basic xxxx
  • base64 has no extra newline characters
  • HTTP method is correct (GET vs POST)

13. ClipboardSender (Windows app integration)

Goal: send clipboard text to Notemod immediately, making Windows → iPhone text transfer effortless.

Typical flow

  • ClipboardSender reads Windows clipboard
  • Sends to /api/api.php with text=...&category=INBOX
  • iPhone reads via read_api.php?action=latest_note&pretty=2

Recommended usage

  • Use INBOX as the Windows-sending category
  • Create an iOS Shortcut for “PC → iPhone”
  • Use both Basic Auth + token for layered protection

14. Permissions (typical for shared hosting)

Typical values:

  • Directories: 755
  • PHP files: 644
  • data.json / log files: 600–644 (as long as the server can write)
  • .htaccess: 644

Notes:

  • Writable directories: notemod-data/, and logs/ if file logging is enabled
  • If the server cannot write, logger and sync will fail

15. GitHub publishing notes (must read)

Safe to publish

  • PHP/HTML/JS (index.php, api/, logger.php, notemod_sync.php)
  • config/*.sample.php
  • README / LICENSE / .gitignore / robots.txt

Never publish (DO NOT COMMIT)

  • config/config.php
  • config/config.api.php
  • notemod-data/data.json
  • logs/ or any *.log
  • *.bak-* (backups)

16. API examples

Add a note

  • GET/POST /api/api.php?token=EXPECTED_TOKEN&category=Memo&text=AAA

Get latest note (body only)

  • GET /api/read_api.php?token=EXPECTED_TOKEN&action=latest_note&pretty=2

List notes

  • GET /api/read_api.php?token=EXPECTED_TOKEN&action=list_notes&pretty=1

Body only by category + title

  • GET /api/read_api.php?token=EXPECTED_TOKEN&action=get_note&category=aaa&title=i&pretty=2

(Legacy) Basic Auth URL examples

https://USER:PASS@YOUR_SITE/... may be blocked by modern browsers.

  • GET/POST https://USER:PASS@YOUR_SITE/api/api.php?token=EXPECTED_TOKEN&category=Memo&text=AAA
  • GET https://USER:PASS@YOUR_SITE/api/read_api.php?token=EXPECTED_TOKEN&action=latest_note&pretty=2
  • GET https://USER:PASS@YOUR_SITE/api/read_api.php?token=EXPECTED_TOKEN&action=list_notes&pretty=1
  • GET https://USER:PASS@YOUR_SITE/api/read_api.php?token=EXPECTED_TOKEN&action=get_note&category=aaa&title=i&pretty=2
Language
PAGE TOP