Coroin Apps SaaS-less software

Coroin Apps

SaaS-less and database-less software that lives in your account (not ours)

bugkit

A portable, framework-agnostic report-a-bug feature for your own apps.

bugkit packages a screenshot-and-submit bug reporter plus an admin triage page as two small libraries that drop into a React app, or a static site with no build step. Bug reports and screenshots land in your own DigitalOcean Spaces — host-agnostic, with auth, storage, and email all injected by your app. Nothing runs in Coroin’s account.

View on GitLab →

Open-source under Apache 2.0. The README covers the libraries, host glue, and a per-app install checklist. Security and quality reviewed November 2026.

Two small libraries

  • bugkit-core — a self-routing backend over injected auth and storage. Pure Node, no React, no AWS SDK.
  • bugkit-ui — a reporter button/modal and an admin triage page, as React components or as a framework-free browser build for hosts without React.

How it fits your app

  • Reports and screenshots live in your own DigitalOcean Spaces — one JSON file per bug, no shared database.
  • Screenshots aren’t publicly readable; the admin view mints short-lived presigned URLs to fetch them.
  • Members submit, admins triage open → fixed → closed. Caller identity comes from your verified login, never the form.
  • Screenshots are resized in the browser to stay under the serverless 1 MB request cap.
  • An optional daily cap on the admin notification mails: past it, a report is still stored and only the mail is skipped.

contactkit

A contact-form spam guard with no third-party CAPTCHA service.

contactkit is a portable spam guard for serverless contact-form handlers — proof-of-work signed token, client fingerprint, honeypot, Origin allowlist, and content scoring, with no third-party dependencies, built on passkit’s sign/verify. It grades submissions instead of blocking them outright, so a false positive costs a glance at a subject line, never a lost lead.

View on GitLab →

Open-source under Apache 2.0. Live on every contact and subscribe form across Coroin’s sites, including bedogivelove.com, coroinbooks.com, and erikcto.com. Security and quality reviewed November 2026.

How it fits your app

  • Never a hard failure. Every submission gets a decision — accept, quarantine, silent-drop, or expired — and grading only throws on host misconfiguration, never on bad or bot input.
  • Bots get no signal. A silent-drop returns a normal-looking success response with no email sent.
  • Soft signals stay soft. A fingerprint mismatch or missing proof-of-work nonce is scored, not rejected by default — a stale cached page or a mobile IP change degrades to "flagged for review," never a dropped inquiry.
  • Single-use tokens. Give it a store and a replayed token is silently dropped. If the store is down it fails closed, and the browser helper re-arms.
  • A real visitor is not lost. A small browser helper keeps the token and proof-of-work solution fresh, and holds a submit until the token is old enough for the guard. With no token it shows a message on the form instead of posting. A form’s own submit handler doesn’t change; a fetch caller handles one rejection.
  • A daily send cap. A solved proof-of-work buys one mail, so a per-day cap bounds how many one form sends. Past it the visitor is asked to try again tomorrow; if the cap’s store is down, mail still goes.

passkit

Magic-link auth, session JWTs, and tiered access for your own backend.

passkit is a portable magic-link auth + HS256 session JWT + tiered RBAC library, extracted from the sign-in pattern several Coroin apps implemented independently. Email delivery, pending-link storage, and tier→permission decisions are all injected by your host app — passkit only verifies that a link checked out and signs the session that follows. It never runs as a service; it ships inside your own deploy.

View on GitLab →

Open-source under Apache 2.0. The README covers the API, error codes, and secret-rotation. Security and quality reviewed November 2026.

How it fits your app

  • Two-step sign-in. requestLink(email) mints a short-lived magic link and calls your injected mailer; verifyLink(token) redeems it once. A redemption that starts after another has claimed the link is refused. Your store needs no compare-and-swap, and the price is a narrow window: two redemptions that overlap exactly can both pass.
  • Tokens know their purpose. A magic-link token is never accepted as a session, and a session is never accepted as a magic link.
  • Tiers are your business logic. passkit only validates a tier name against a whitelist you provide — deciding who is a member or an admin stays entirely in your app.
  • Secret rotation with a grace period. Configure a previous secret alongside a freshly rotated one; tokens signed before rotation keep verifying until they expire.
  • Pairs with sendkit for the email and shardkit for the pending links, but has no dependencies at all. Use it standalone.

qrkit

A branded QR-code generator, with a tracking-link manager for your own DigitalOcean account.

qrkit generates styled SVG QR codes with no database, no redirector, and no custom analytics platform. Each code encodes the destination and UTM params directly, so GA4 sees your channel data natively. It runs at build time or in the browser, and a dependency-light manager and React admin page can keep a catalogue of codes in your own DigitalOcean Spaces.

View on GitLab →

Open-source under Apache 2.0. The generator is live in production; the manager and admin page are tested but not yet running in a production app. Security and quality reviewed November 2026.

Two small libraries

  • qrkit-core — SVG generation and tracked URLs for a build script or the browser, plus backend CRUD and an auth-free dispatcher. Pure TypeScript, no native deps.
  • qrkit-ui — a React admin page with Active / Inactive / Archived tabs and a live style preview, for hosts that already load React.
  • Test doubles — in-memory Spaces and blob mocks so you can unit-test without touching DigitalOcean.
  • SVG styling — configurable module and eye shapes, colors, and an embedded logo with error-correction locking.

How it works

  • Generate — give it a destination URL, a UTM source, and optional styling; qrkit builds the tracked URL and renders the SVG.
  • Embed — drop the generated SVG in with a plain <img> tag. No proxy or redirector — the QR carries the full destination and UTM params.
  • Attribute — UTM params flow into GA4 natively; set up a QR channel group once and track it beside your other channels.
  • Manage — with the manager, each code is an SVG in Spaces and a JSON record; re-style one and the SVG regenerates over the same key, so your embeds keep working.

roadmapkit

One markdown file per repo, with a board on top.

roadmapkit keeps a roadmap as one markdown file per repo instead of in an issue tracker. It parses the file into items, checks it, gives each item a stable id, and says what changed between two versions. A backend and a framework-free board sit on top, with everything stored in your own bucket.

View on GitLab →

Open-source under Apache 2.0. Runs Coroin’s own roadmap board. You write the small sync that moves your files to the bucket. Security and quality reviewed November 2026.

Two small libraries

  • roadmapkit-core — the data model, which does no I/O, plus a handler for your function and a store over DigitalOcean Spaces.
  • roadmapkit-ui — a board with no framework: lanes, search, one-tap edits, and a delivery report. Phone first, light and dark.

How it fits your app

  • Your sign-in decides who can edit. You verify the person and pass a role; a reporter reads the whole board and an edit from one is refused.
  • Edits are requests. Each is its own object until your sync applies it, so the file keeps one writer.
  • A journal of every change. Each one is recorded with who made it, and the report counts what shipped on time, what slipped, and what was dropped.
  • Drafts for review. An agent can put a draft on an item, and a reviewer answers it on the board.

sendkit

Portable outbound email for Node.js — swap transports without touching your app code.

sendkit is a lightweight email composition and dispatch kit for your Node.js backend — serverless functions, Express, anywhere. Pick a transport, inject it once, and sendkit handles escaping, templating, and recipient safety for contact forms and magic-link sign-in. No SaaS dashboard and no framework lock-in: it’s a pure library that ships inside your own deploy.

View on GitLab →

Open-source under Apache 2.0. The README covers quick-start, transport setup, the security model, and testing patterns. Security and quality reviewed November 2026.

Core features

  • Swappable transports — Resend, any SMTP server (Amazon SES, Postmark, self-hosted), plus in-memory and console transports for tests.
  • Safe contact forms — the recipient is resolved server-side, never read from the request body.
  • Magic-link sign-in — sign-in emails with configurable expiry and escaped URLs.
  • Canonical escaping — every user-supplied value is HTML-escaped in your templates.

How it fits your app

  • The transport is injected at initialization — sendkit never reads process.env itself.
  • A low-level send() for custom templates, plus canned sendContactForm and sendMagicLink helpers.
  • Honeypot support for contact forms — a silent no-op when the field is filled.
  • Typed errors with codes (invalid_recipient, send_failed, honeypot_tripped).

shardkit

One-JSON-file-per-record storage on S3-compatible object stores.

shardkit exists because a plain PutObject is last-write-wins: a “read-modify-write one array file” collection silently loses updates under concurrent writers, while a store that shards one record per key does not. It’s a small, portable library over an injected client, with no database and no server of its own.

View on GitLab →

Open-source under Apache 2.0. Powers the storage under coroin.app’s own bugkit reports and magic-link store, and the used-token store on coroinbooks.com. Security and quality reviewed November 2026.

How it fits your app

  • One JSON file per record, at ${prefix}${id}.json — concurrent writers to different ids never collide.
  • The client is injected. Your host constructs a lightweight aws4fetch client pre-bound with credentials and hands it in — shardkit never reads process.env, and stays out of the full AWS SDK’s cold-start cost.
  • Optional read validation via a zod schema or hand-rolled type guard, to catch malformed or legacy-shaped records on the way out.
  • Ships a MemoryShardStore for tests — no network, no bucket.

feedbackkit

Audience feedback for a talk, on your own site and in your own storage.

feedbackkit is what a speaker puts behind the link or QR code on the closing slide. The room answers on their phones in about two minutes, with no app and no account. You get a rating for each question with its spread, the line each person will take away, the quotes they agreed to share, and the people who know an event that should hear you. Every response is stored in your own bucket, so there is no subscription and no cap on your audience.

View on GitLab →

Open-source under Apache 2.0. A library for your own site and serverless function, so you will want a developer to install it. Security and quality reviewed November 2026.

What it decides for you

  • One answer is enough — a single rating is a whole response. An email is asked for only when someone ticks a box that needs a reply.
  • An unticked box stores nothing — names and emails are cut on the server to what each person allowed.
  • A quote needs its own tick — every other takeaway stays private.
  • A form that looks sent is stored — on bad conference Wi-Fi the answers stay on screen until they really go.

The dashboard

Each talk page carries its own code, and every response is filed under it, so one dashboard shows every talk. It sits behind your own sign-in. Responses are never shown on the talk page.

Three rating cards, each with an average out of 5 and a bar for how many people gave each score.
Each rating with its spread. Sample data.
A list of booking leads with name, event and email, and a list of quotes people agreed to share.
Leads, and the quotes people agreed to share. Sample data.

How it works

  • Add it — the form builds into your page, and a small function on your account takes the answers.
  • Store it — each response is its own private record, so a full room answering at once loses nothing, and removing one person is one delete.
  • Read it — the dashboard, or a one-line report: ratings, quotes, leads, and who asked for the recording.

listenkit

A page read aloud, paragraph by paragraph, built for a phone.

listenkit speaks a page with the browser’s own speech engine, so there is no audio to record, no service, and no API key. Your host passes the paragraphs’ text; listenkit speaks them in order and reports which one is being read, so you can highlight it or jump to a tapped one.

View on GitLab →

Open-source under Apache 2.0. Framework-free, with a bundler build and a plain browser build. Security and quality reviewed November 2026.

Built to iOS Safari’s rules

  • A watchdog per paragraph. The end-of-speech event sometimes never fires; the player moves on anyway.
  • A screen wake lock. Speech stops when the screen locks, so the screen stays on while it plays.
  • Voices load late. It prefers a local voice for the language and picks again when the list changes.
  • Leaving stops it. Otherwise iOS keeps talking over the next page.

What a web page can’t do

  • Voice commands, playing with the screen locked, and lock-screen controls are not possible from a web page.

survey v2

Scored diagnostics, built and run on your own Google Drive.

survey v2 turns a spreadsheet into a scored diagnostic: write your own statements, and every respondent gets a personal result by email, not just a thank-you page. Everything lives in your own Google Drive. There's no account, no subscription, and no server holding your data.

Score one overall level, a reading for each facet, or both. Set it from the Backstage menu, no code needed. Every submission is scored automatically and emailed out with the wording and chart you wrote.

Step 1: Sample Survey

Take the Backstage Index — the sample survey that ships with the tool — and get your scored result by email.

Step 2: Find Your Facets

These two prompts run before you have a sheet — they mine your existing material for the lanes your diagnostic should measure. Run them in order with your Gen-AI.

Generate Context

Generate Facets

Step 3: Build It

Copy the template into your Drive and work down the Backstage menu. The guide covers every step, including Google's unverified-app screen. Security and quality reviewed November 2026.

Open the Guide →

Step-by-step, with screenshots, from copied sheet to live survey.

Copy survey v2 →

Copies the v2 template to your Google Drive. Google will confirm before anything is added to your account.

The Rest of the Prompts

Prompts for your statements, your result levels, your result messages, and your email copy now live inside the tool, under Backstage → Writing Prompts. They're generated from your own sheet — they know your facets, your levels, and which statements are reverse-worded — so there is nothing to keep in sync here. Copy the template, then run them from the menu.

survey v1

Retired. Superseded by survey v2.

survey v1 was the original Backstage Form Builder: 20 statements, one composite score, one level. It still works, and existing installs keep running — but it is unsupported, and it will not receive fixes or new features.

An existing install cannot be upgraded. Every copy of the sheet carries its own bound Apps Script project with its own ID, and nothing phones home — so there is no update channel and never was one. Moving to v2 means copying the v2 template and rebuilding your survey in it.

What v2 changes: scores are percentages instead of a raw 20–100 total, and you choose what a respondent sees — one overall score (the closest match to v1, and v2's shipped default), a reading per facet, or both, each levelled in its own words with a personal chart and a named next move when facets are shown. The form is born closed and only opens once a built-in check passes, and there is no code to paste and no trigger to add by hand.

Where to go instead

Read the Migration Guide →

The delta from v1, and the one question that decides whether you should move yet.

Open the v2 Guide →

The v1 quickstart PDF is obsolete — its setup steps no longer exist.