Letterhead Editor banner

Letterhead Editor

9 devlogs
18h 26m 8s

It's a Letterhead editor! You can make a letterhead for yourself here by editing your logo, name, qualifications and more…
A micro-text feature ensures uniqueness of work and credibility (use 1200DPI printer for hardcopy). QR codes can be added…

It’s a Letterhead editor! You can make a letterhead for yourself here by editing your logo, name, qualifications and more…
A micro-text feature ensures uniqueness of work and credibility (use 1200DPI printer for hardcopy). QR codes can be added to verify real letters and match them to metadata.

This project uses AI

Used GitHub Copilot suggestions for code completion.
Used Claude Haiku 4,5 as part of GitHub SDP to get a grip on XML and Java.

Used Google Gemini 3.1 Pro to make the README.md

Demo Repository

Loading README...

adityarajmalviyaa

Shipped this project!

Hours: 24.26
Cookies: 🍪 531
Multiplier: 21.89 cookies/hr

I built a Letterhead Editor—a fully air-gapped, offline-first Android and PC webapp designed to help professionals or organizations draft letters in a standard format.
It allows the user to input dynamic credentials, digital signatures, and local QR codes, outputting a perfect vector-based PDF. I completely stripped all INTERNET permissions from the Android Manifest to ensure it is 100% tamper-proof and offline.

The hardest part by far was fighting the Android WebView engine and its native Print Spooler. Porting a desktop-first CSS layout to mobile trapped me in a non-scrollable “100vh prison” at first. Then, getting the Android PDF generator to strictly respect A4 dimensions without adding ugly black margins or randomly splitting into two pages took hours of media-query debugging. I even had a 0.5pt “security micro-text” feature that worked flawlessly on PC, but I eventually had to write a kill-switch to axe it from the mobile build because Android’s accessibility auto-scaler aggressively refused to let text render that small!

I figured it out by hard-locking the print dimensions to 296mm to satisfy the print spooler, moving my QR library from a CDN to a local asset, and using a Java JavascriptInterface bridge to handle native printing securely. I am really proud of the fact that it is completely “ghost” software—it operates completely offline with zero data leaks.

adityarajmalviyaa

This was the final sprint to lock down the end. Android’s WebView engine is completely different game from desktop browsers, can’t seem to figure out what it renders and what it doesn’t. But anyways: https://github.com/adibuddies/letterhead.editor/commit/aa8a12022572545eab154070f2714d40372aa69d

  1. I had completely removed all internet permissions so the HTML wasn’t able to communicate with qrcode.min.js on the url given. I fixed it by downloading the javascript file into the assets folder.
  2. The micro-text features in android webview were just so not possible. Partially because I can’t expect a high-density display of a smartphone to render me a 0.5pt line (1/144th of an inch).
  3. I fixed it by leaving no trace for the micro-text in the android app while it worked as usual with PC version.

Finally, an APK is available to download and test in the repo. Please do check out!

Attachment
0
adityarajmalviyaa
  1. Eliminated the unwanted black margins.
    Injected an initial @media print block to force a white background and reset the .preview-area. I also set the .letterhead to a fixed 210mm width to override the mobile 100% view.
    The placement was still off, and the letter was still going into a second page on the PDF.
    Then comes the attempt to correct—
  2. .letter-content increased the top margin to 2.5in
  3. Reduced height to 296mm
  4. overflow: hidden in the print CSS to guarantee a 1-page output

Success! 😎

0
adityarajmalviyaa

Diff view link: https://github.com/adibuddies/letterhead.editor/commit/b4d89278ce281316d5a8cf15f8f1789d360052e9

I implemented @media (max-width: 600px) logic to completely overhaul the layout as the index.html was a desktop-first design.
I swapped the main body from flex-direction: row to column, now instead of horizontal space the control features now sit on top of the letterhead vertically.
I had to use !important on almost every font size and padding value because the original desktop styles were acting higher and refused to be overridden by media queries.
I also scaled the name down to 18pt.

Now here’s the problem—
I fixed the “squashed” look, but I’ve run into a serious usability wall.
Because the sidebar is so long with all the new identity fields, it’s taking up the entire viewport. I can’t scroll past the “Print PDF” button to actually reach the letter body. If I can’t scroll, I can’t type, which basically makes it a very pretty, very useless screen right now.

I’m stopping here for the day before I smash my head against the keyboard.🥲

Once these issues are resolved I am going to make the Gen. QR button work and look if the code needs any more refining.

Attachment
Attachment
Attachment
0
adityarajmalviyaa

Changelogs: https://github.com/adibuddies/letterhead.editor/commits/LetterheadEditorbyMiracle/

Had to compress due to exceeding char limit

Phase 1 — Initialization (Android Studio, Java, API 24)

  1. Incorrect asset root caused crash; fixed by relocating to src/main/assets and updating WebView to file:///android_asset/index.html.
  2. A4 layout rendered incorrectly due to desktop-oriented CSS in WebView.

Phase 2 — Security & Isolation

  1. Removed INTERNET permission; enforced no-cache via:
    myWebView.clearCache(true);
    s.setCacheMode(WebSettings.LOAD_NO_CACHE);
  2. Bundled fonts (Playfair Display, EB Garamond, Inter) and localized Phosphor icons.
  3. Fixed CSS font paths (../fonts/Phosphor.woff2).
  4. Disabled content access and cross-file interaction.

Phase 3 — Functionality (WebView ↔ Android bridge)

  1. Implemented WebChromeClient for image upload without broad storage permissions.
  2. Added JavascriptInterface to route window.print to Android Print Spooler.
  3. Tested on Android 12 (unsigned APK); all implemented features working as intended.
0
adityarajmalviyaa

😎
This update was about breaking the previous hardcoded version into a flexible local app: professional letter tool.
Yk the previous version had a lot of info which was immutable using the UI/UX.

Changelog: https://github.com/adibuddies/letterhead.editor/commit/1588299078f86fcff3d937cfb9c0ba0756fdf11f

  1. I replaced the hardcoded src paths for the logo (/watermark) and Signature with a FileReader logic. You can now upload your own logo and digital signature directly through the sidebar options.
  2. I added several new metadata fields to the identity container, including Memberships, Phone Number, and a combined Socials line (LinkedIn/GitHub/Web).
  3. Instead of a static string of text in the footer, I built a JavaScript repeat-logic function. (I was idiotic for hardcoding it multiple times). You can now type a single security phrase in the sidebar, and the system uses .repeat() to automatically generate those repeating anti-copy lines for the footer (30x) and the wet-signature area (15x).
  4. I removed the strict gatekeeper in the initiatePrint function. Afixing a QR is optional now.
  5. Kept the previous formatting options as it is.
  6. Expanded the sidebar to 380px.
  7. Used the section-tags to keep the sidebar still clean after adding hell lot more options.

P.S: forgot to add variable feature to the .crest-img ’s 0.15 opacity 🥲

0
adityarajmalviyaa

changelog: https://github.com/adibuddies/letterhead.editor/commit/9be2fb6864183cee992234a359adef834e5d6018

  1. the sidebar now uses a translucent glass effect (rgba overlays) and a thin gold border.
  2. I implemented a micro-text separator (0.5pt) that repeats “IUM-LETTER-AUTHENTIC-DONOTCOPY” (had it hardcoded, didn’t think of limited extension)
  3. I built a Print Modal. Now, when you hit print, it asks if the use case is Digital (it affixes a high-res digital signature) or Physical (it hides the signature and adds a specialized physical-sign line)
  4. The physical sign line is also a micro-text (.5pt again) “IUM-PHYSICAL-SIGNATURE-AUTHENTIC-DONOTCOPY” (again hardcoded).
  5. qrcode.js : You can now generate a dynamic verification QR code that sits in the bottom right. (the only problem is it need QR before printing, so first upload a metadata to a webpage and add that URL to your QR. Problematic for those who don’t need it)
  6. Phosphor Icon library for the toolbar

Good that this works!

P.S.: this is still not final since it can’t be used by all yet. There are a lot of elements still hardcoded, thus will replace it with a lot of editable variables in next session. Thankyou

0
adityarajmalviyaa

My goal was to build a professional tool for my sister. Choosing HTML was the best way forward I think, for the most part, the use is local and doesn’t need hosting.
So this particular tool was for a letterhead editor. But there is still a lot to work on the css. The looks are not quite aligned and are unsettling.

  1. I tried to make the editor responsive, but the A4 sheet kept shrinking so used min-height and fixed-width rather than width=device-width.
  2. I’ve imported Playfair Display for the names and EB Garamond for the body and assure you it’s not just another MSWord.
  3. Used basic contenteditable attribute for content in A4.
  4. I can type directly onto the paper space.
  5. I have also added formatting using Italic and Bold. But don’t know how that will mess up and complicate my code when I try to bring order to the editor’s css later.
  6. I can also print the letter once written using Ctrl + P and unchecking Header/Footer option. Refinement on it’s way!

There are some issues however:

  1. The footer doesn’t have good styling, it touches the footer line (separator).
  2. Also the UI is too dark.
  3. I’ll also need to format the logo ‘Miracle’ on top better.
0