Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false
44 changes: 44 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Bug report
description: Report a reproducible problem in StackRunway
title: "[Bug]: "
labels: [bug]
body:
- type: markdown
attributes:
value: Thanks for helping improve StackRunway. Do not include private financial data or exported JSON contents.
- type: textarea
id: problem
attributes:
label: What happened?
description: Describe the problem and what you expected instead.
validations:
required: true
- type: textarea
id: reproduce
attributes:
label: Steps to reproduce
placeholder: "1. Open…\n2. Add…\n3. Select…"
validations:
required: true
- type: input
id: browser
attributes:
label: Browser and version
placeholder: Safari 26.0, Chrome 140, Firefox 142
validations:
required: true
- type: dropdown
id: edition
attributes:
label: Edition
options:
- GitHub Pages
- Downloaded index.html
- Forked copy
validations:
required: true
- type: textarea
id: evidence
attributes:
label: Additional context
description: Add a screenshot if useful. Remove account balances and other private information first.
5 changes: 5 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Security concern
url: https://github.com/Skylab008/StackRunway/security/policy
about: Read the security policy before reporting a vulnerability.
28 changes: 28 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Feature request
description: Propose a focused improvement to StackRunway
title: "[Idea]: "
labels: [enhancement]
body:
- type: textarea
id: problem
attributes:
label: Developer problem
description: What problem should StackRunway solve?
validations:
required: true
- type: textarea
id: outcome
attributes:
label: Desired outcome
description: Describe the result rather than prescribing an implementation.
validations:
required: true
- type: checkboxes
id: principles
attributes:
label: Project fit
options:
- label: This can preserve local-only data and the no-login model.
required: true
- label: This can preserve the downloadable single-file edition.
required: true
16 changes: 16 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
## What changed

<!-- Describe the change and the developer problem it addresses. -->

## Verification

<!-- Explain the checks performed. Include screenshots for visible changes. -->

- [ ] `npm test` passes
- [ ] The app still opens directly from `index.html`
- [ ] No analytics, tracking, backend or runtime dependency was introduced
- [ ] User-facing changes are recorded in `CHANGELOG.md`

## Privacy impact

<!-- State "None" or explain any effect on local storage, JSON backups or network behaviour. -->
22 changes: 22 additions & 0 deletions .github/workflows/quality.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Quality

on:
pull_request:
push:
branches: [main]

permissions:
contents: read

jobs:
verify:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 22
- name: Verify standalone application
run: npm test
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Changelog

Meaningful user-facing changes to StackRunway are recorded here.

This project follows [Semantic Versioning](https://semver.org/).

## [1.0.0] — 2026-08-25

### Added

- Date-aware 30, 60 and 90-day developer expense runway calculations
- Minimum opening balance statement with exact coverage dates
- Most-expensive-week and first-funding-gap insights
- Annual-renewal exposure with monthly-equivalent comparison
- Pause modelling for subscriptions and other expenses
- Weekly, fortnightly, monthly, quarterly, annual and one-off schedules
- Local browser autosave
- Portable JSON export and restore
- Responsive, dependency-free single-file interface
- GitHub Pages edition and MIT Licence
9 changes: 9 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Code of Conduct

StackRunway welcomes thoughtful participation from people of every background and experience level.

Be respectful, specific and constructive. Discuss the work rather than the person. Harassment, intimidation, discriminatory language, deliberate disruption and the publication of another person's private information are not acceptable.

Maintainers may edit or remove contributions that breach these standards and may temporarily or permanently restrict participation when necessary to protect the project and its community.

If conduct needs attention, raise it privately with the repository maintainer where possible. Do not use a public issue to disclose personal or sensitive information.
34 changes: 34 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Contributing to StackRunway

StackRunway is deliberately small: a private, local-first developer tool that runs from one HTML file. Contributions are welcome when they preserve that clarity.

## Before opening a pull request

Search existing issues first. For a material feature or behavioural change, open a feature request before writing code so the direction can be agreed without wasting anyone's time.

Bug fixes, accessibility improvements, calculation corrections and careful interface refinements are especially valuable.

## Project principles

- Keep the application usable without an account, backend or build step.
- Keep user financial data inside the browser.
- Do not add analytics, advertising, tracking or bank connections.
- Avoid runtime dependencies unless there is a compelling security or accessibility reason.
- Preserve the downloadable single-file `index.html` edition.
- Use clear language and accessible interaction patterns.

## Development

Open `index.html` directly in a modern browser or serve the repository with any static server.

Run the repository checks before submitting:

```bash
npm test
```

## Pull requests

Keep each pull request focused. Explain the user problem, the change and how it was tested. Include screenshots for visible interface changes. Update `CHANGELOG.md` when the change affects users.

By contributing, you agree that your contribution may be distributed under the repository's [MIT Licence](LICENSE).
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

---

![StackRunway developer subscription runway](assets/stackrunway-preview.webp)

Developer expenses rarely arrive in a neat monthly bundle. Hosting renews on Tuesday. API credits run out on Friday. Three annual tools land in the same week and the account balance that looked comfortable suddenly is not.

**StackRunway answers the question ordinary expense trackers miss:**
Expand Down Expand Up @@ -69,4 +71,6 @@ Useful software does not always need a gate, a funnel or another subscription.

Released under the [MIT Licence](LICENSE).

[Contributing](CONTRIBUTING.md) · [Security](SECURITY.md) · [Code of Conduct](CODE_OF_CONDUCT.md) · [Changelog](CHANGELOG.md)

<sub>Planning estimates only. StackRunway does not predict taxes, exchange-rate movements, price changes or usage-based overages.</sub>
17 changes: 17 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Security policy

## Supported version

The latest version on the `main` branch is supported.

## Reporting a vulnerability

Please do not publish exploit details in a public issue.

Use GitHub's private vulnerability reporting option for this repository when it is available. If it is not available, open a minimal issue stating that you need to report a security concern privately, without including sensitive details or a proof of concept.

Reports should identify the affected behaviour, the potential impact, reproducible conditions and any suggested remediation. Acknowledgement should be expected within seven days.

## Security model

StackRunway has no server, account system, bank connection, analytics or runtime dependency. Expense data is stored in the user's browser and can be exported to a local JSON file. Users are responsible for protecting exported backups and devices on which browser data is stored.
Binary file added assets/stackrunway-preview.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "stackrunway",
"version": "1.0.0",
"private": true,
"description": "A private, local-first developer subscription runway calculator.",
"scripts": {
"test": "node scripts/check.mjs"
},
"license": "MIT"
}
23 changes: 23 additions & 0 deletions scripts/check.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import vm from "node:vm";

const html = await readFile(new URL("../index.html", import.meta.url), "utf8");

assert.match(html, /^<!doctype html>/i, "index.html must declare HTML5");
assert.match(html, /<title>StackRunway/, "document title is missing");
assert.match(html, /id="startDate"/, "runway start control is missing");
assert.match(html, /data-days="30"/, "30-day runway option is missing");
assert.match(html, /data-days="60"/, "60-day runway option is missing");
assert.match(html, /data-days="90"/, "90-day runway option is missing");
assert.match(html, /Export JSON/, "JSON export control is missing");
assert.match(html, /Restore JSON/, "JSON restore control is missing");
assert.doesNotMatch(html, /<script[^>]+src=/i, "runtime script dependencies are not permitted");
assert.doesNotMatch(html, /<link[^>]+rel=["']stylesheet/i, "runtime stylesheet dependencies are not permitted");
assert.doesNotMatch(html, /\b(fetch|XMLHttpRequest|WebSocket)\s*\(/, "network calls are not permitted");

const scripts = [...html.matchAll(/<script>([\s\S]*?)<\/script>/gi)];
assert.equal(scripts.length, 1, "exactly one inline application script is expected");
new vm.Script(scripts[0][1], { filename: "index.html:inline-script" });

console.log("StackRunway checks passed: structure, privacy boundaries and JavaScript syntax.");
Loading