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
1 change: 1 addition & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"ignore": [
"web",
"mobile-app",
"@beakerstack/billing",
"@beakerstack/shared",
"@beakerstack/shared-tests"
],
Expand Down
34 changes: 34 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Bug report
description: Something broken in the template or published packages
title: "[bug]: "
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thanks for reporting. Search [existing issues](https://github.com/Artificer-Innovations/BeakerStack/issues) first.
For usage questions, prefer [Discussions](https://github.com/Artificer-Innovations/BeakerStack/discussions).
- type: textarea
id: description
attributes:
label: What happened?
description: What did you expect vs what you saw?
validations:
required: true
- type: textarea
id: reproduce
attributes:
label: Steps to reproduce
placeholder: "1. npm run setup\n2. ..."
validations:
required: true
- type: input
id: version
attributes:
label: Template tag or commit
placeholder: "2026.001 or abc1234"
- type: input
id: environment
attributes:
label: Environment
placeholder: "Node 20, macOS, local Supabase"
8 changes: 8 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Questions (Discussions)
url: https://github.com/Artificer-Innovations/BeakerStack/discussions
about: Usage help and design questions
- name: Security report
url: https://github.com/Artificer-Innovations/BeakerStack/blob/main/SECURITY.md
about: Report vulnerabilities privately — do not file a public issue
29 changes: 29 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Feature request
description: Propose a change to the upstream template
title: "[feat]: "
labels: ["enhancement"]
body:
- type: markdown
attributes:
value: |
For large or opinionated changes, open a [Discussion](https://github.com/Artificer-Innovations/BeakerStack/discussions) first.
Stack swaps (e.g. different auth or payment provider) usually belong in forks — see [CONTRIBUTING.md](https://github.com/Artificer-Innovations/BeakerStack/blob/main/CONTRIBUTING.md).
- type: textarea
id: problem
attributes:
label: Problem or use case
description: What are you trying to accomplish?
validations:
required: true
- type: textarea
id: proposal
attributes:
label: Proposed solution
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives considered
validations:
required: false
13 changes: 13 additions & 0 deletions .github/RELEASE_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Maintainer: paste this block above the git-cliff-generated body when publishing a CalVer template release. -->

## Summary

[3–4 sentences: what this release represents, headline capabilities, any breaking fork steps.]

- **Landing:** https://beakerstack.com
- **Quick start:** https://github.com/Artificer-Innovations/BeakerStack/blob/main/QUICKSTART.md
- **Feedback:** https://github.com/Artificer-Innovations/BeakerStack/discussions

---

<!-- git-cliff output below -->
2 changes: 1 addition & 1 deletion .github/workflows/check-merge-strategy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:

Using "Squash and merge" on PRs targeting \`main\` can cause merge conflicts when merging \`develop\` → \`main\` later.

See [ARCHITECTURE.md](../../blob/develop/ARCHITECTURE.md#pull-request-process) for details.
See https://github.com/Artificer-Innovations/BeakerStack/blob/develop/docs/ARCHITECTURE.md#pull-request-process for details.

---

Expand Down
44 changes: 44 additions & 0 deletions .github/workflows/deploy-production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:
permissions:
contents: read
id-token: write
deployments: write

concurrency:
group: production-deploy
Expand Down Expand Up @@ -146,6 +147,49 @@ jobs:
--environment prod \
--region "${AWS_REGION_VALUE}"

- name: Create GitHub Deployment (production)
uses: actions/github-script@v7
env:
PRODUCTION_URL: ${{ format('https://{0}/', env.DOMAIN) }}
with:
script: |
const environmentUrl = process.env.PRODUCTION_URL;
const logUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
const deployment = await github.rest.repos.createDeployment({
owner: context.repo.owner,
repo: context.repo.repo,
ref: context.sha,
environment: 'production',
auto_merge: false,
required_contexts: [],
description: 'Production deployment',
});
if (!deployment.data.id) {
core.warning(`createDeployment returned no id (HTTP ${deployment.status}): ${deployment.data.message ?? JSON.stringify(deployment.data)}`);
return;
}
await github.rest.repos.createDeploymentStatus({
owner: context.repo.owner,
repo: context.repo.repo,
deployment_id: deployment.data.id,
state: 'success',
environment_url: environmentUrl,
log_url: logUrl,
description: 'Production deployed',
});

- name: Write Actions run summary
shell: bash
env:
PRODUCTION_URL: ${{ format('https://{0}/', env.DOMAIN) }}
run: |
set -euo pipefail
cat >> "${GITHUB_STEP_SUMMARY}" <<SUMMARY
## Production Deployment

**Production URL:** ${PRODUCTION_URL}
SUMMARY

deploy-mobile-production:
if: vars.MOBILE_ENABLED != 'false'
needs: [deploy-production]
Expand Down
86 changes: 86 additions & 0 deletions .github/workflows/pr-preview-environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -742,3 +742,89 @@ jobs:
--region "${AWS_REGION_VALUE}" \
--supabase-db-url "${SUPABASE_PREVIEW_DB_URL}"

- name: Clean up GitHub Deployment and environment
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
with:
script: |
// Fork PRs cannot write to Deployments API — skip cleanly.
const headRepo = context.payload.pull_request.head.repo?.full_name;
const baseRepo = `${context.repo.owner}/${context.repo.repo}`;
if (!headRepo || headRepo !== baseRepo) {
core.info(`Skipping: fork PR (${headRepo ?? 'deleted repo'}) — Deployments API write not available.`);
return;
}

const environment = `pr-${process.env.PR_NUMBER}-preview`;

// List all deployments for this environment (up to 100).
let deployments = [];
try {
const { data } = await github.rest.repos.listDeployments({
owner: context.repo.owner,
repo: context.repo.repo,
environment,
per_page: 100,
});
deployments = data;
} catch (err) {
if (err.status === 404) {
core.info(`No deployments found for ${environment} — nothing to clean up.`);
return;
}
throw err;
}

if (deployments.length === 0) {
core.info(`No deployments for ${environment} — nothing to clean up.`);
}

for (const dep of deployments) {
// GitHub requires inactive status before a deployment can be deleted.
try {
await github.rest.repos.createDeploymentStatus({
owner: context.repo.owner,
repo: context.repo.repo,
deployment_id: dep.id,
state: 'inactive',
});
} catch (err) {
if (err.status === 404) {
core.info(`Deployment ${dep.id} already gone — skipping inactive status.`);
} else {
core.warning(`Could not mark deployment ${dep.id} inactive: ${err.message}`);
}
}
try {
await github.rest.repos.deleteDeployment({
owner: context.repo.owner,
repo: context.repo.repo,
deployment_id: dep.id,
});
core.info(`Deleted deployment ${dep.id}.`);
} catch (err) {
if (err.status === 404) {
core.info(`Deployment ${dep.id} already deleted.`);
} else {
core.warning(`Could not delete deployment ${dep.id}: ${err.message}`);
}
}
}

// Delete the GitHub environment so it no longer appears in the Environments list.
try {
await github.rest.repos.deleteAnEnvironment({
owner: context.repo.owner,
repo: context.repo.repo,
environment_name: environment,
});
core.info(`Deleted environment ${environment}.`);
} catch (err) {
if (err.status === 404) {
core.info(`Environment ${environment} already gone — nothing to delete.`);
} else {
core.warning(`Could not delete environment ${environment}: ${err.message}`);
}
}

2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
pnpm-lock.yaml
yarn.lock

# Runtime data
pids
Expand Down
3 changes: 3 additions & 0 deletions .markdown-link-check.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
},
{
"pattern": "^https://github.com/<your-org>/<your-repo>"
},
{
"pattern": "^https://deploy\\.yourdomain\\.com"
}
]
}
37 changes: 36 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,20 @@

Thank you for helping improve Beaker Stack.

## What belongs upstream

**Welcome:** bug fixes, documentation, performance improvements to shared logic, opt-in integrations that fit the template’s architecture, and new publishable `@beakerstack/*` packages.

**Usually not upstream:** swapping core stack choices (e.g. Firebase instead of Supabase, Paddle instead of Stripe, Next.js instead of Vite). Those belong in **downstream forks** where you own the tradeoffs.

**Larger changes:** open a [Discussion](https://github.com/Artificer-Innovations/BeakerStack/discussions) first — especially features that affect every adopter’s fork or CI secrets. Link the Discussion in your PR.

Issues: use [GitHub Issues](https://github.com/Artificer-Innovations/BeakerStack/issues) with the appropriate template (bug vs feature). Questions and usage help fit Discussions (Q&A).

## Workflow

**Package manager:** This repo uses **npm** exclusively — `pnpm` and `yarn` are not supported. The `engines` field in `package.json` requires `npm >= 9.0.0` and all CI runs use `npm ci`. Both `pnpm-lock.yaml` and `yarn.lock` are listed in `.gitignore` to prevent accidental commits.

1. Create a branch from `develop` (or the branch your team uses for integration).
2. Make focused changes; match existing style, types, and test patterns.
3. Run checks locally:
Expand All @@ -16,6 +28,25 @@ Thank you for helping improve Beaker Stack.

4. Open a pull request with a clear description of **what** changed and **why**.

## Commits and release notes

**Conventional commits** are required on the integration branch. [git-cliff](https://github.com/orhun/git-cliff) uses them for **template** CalVer release notes.

Examples:

- `feat: add usage summary to billing dashboard`
- `fix: correct PR preview redirect for trailing slash`
- `docs: clarify OAuth redirect URLs in OAUTH guide`
- `chore: bump Supabase CLI in CI`

**Template-only changes** (anything outside publishable `packages/*`) need a conventional commit only — no Changeset.

**Publishable package changes** (`@beakerstack/test-utils` today) require a Changeset — see below.

**Mixed PRs** (template + package): use a conventional commit message and include a Changeset if any publishable package files changed.

Versioning overview: [docs/VERSIONING.md](docs/VERSIONING.md).

## Pre-commit hook

The repository uses [lint-staged](https://github.com/lint-staged/lint-staged) and [Husky](https://typicode.github.io/husky/) to enforce code quality on every commit.
Expand Down Expand Up @@ -117,6 +148,10 @@ See `packages/test-utils/` for a minimal working example.
- **Topic index:** [docs/README.md](docs/README.md).
- Before merging doc-only changes, run **`npm run docs:linkcheck`** (uses [markdown-link-check](https://github.com/tcort/markdown-link-check) with [.markdown-link-check.json](.markdown-link-check.json)).

## Template releases (maintainers)

CalVer template releases use [.github/workflows/release-template.yml](.github/workflows/release-template.yml). Before publishing, paste the prose block from [.github/RELEASE_TEMPLATE.md](.github/RELEASE_TEMPLATE.md) **above** the git-cliff-generated notes in the GitHub Release body.

## Questions

Use GitHub Issues or your team's usual channel. For OAuth-specific setup, start with [docs/oauth/README.md](docs/oauth/README.md).
Use [Discussions](https://github.com/Artificer-Innovations/BeakerStack/discussions) for usage questions and [Issues](https://github.com/Artificer-Innovations/BeakerStack/issues) for bugs. OAuth setup: [docs/OAUTH.md](docs/OAUTH.md).
4 changes: 2 additions & 2 deletions QUICKSTART.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ You should see a banner and a prompt similar to:
```text
========================================================================
+ +
+ BeakerStack +
+ Beaker Stack +
+ +
+ Choose (1) local setup or (2) full cloud wizard. +
+ +
Expand Down Expand Up @@ -164,6 +164,6 @@ Work through these when you are ready; they are intentionally dense.
- [ ] Firebase / Google Cloud OAuth clients; `google-services.json` where required.
- [ ] Supabase Auth Google provider + redirect URLs: [docs/supabase-preview-setup.md](docs/supabase-preview-setup.md), [docs/supabase-staging-production-setup.md](docs/supabase-staging-production-setup.md).

**Deep dives:** [docs/pr-preview-setup.md](docs/pr-preview-setup.md), [ARCHITECTURE.md](ARCHITECTURE.md), [docs/README.md](docs/README.md).
**Deep dives:** [docs/pr-preview-setup.md](docs/pr-preview-setup.md), [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md), [docs/README.md](docs/README.md).

Do not commit `.env*` files; sensitive paths are listed in [.cursorignore](.cursorignore).
Loading
Loading