Lalabase
Tickets, Doku, Zeiterfassung und Kundengespräche an einem Ort, durchsuchbar per KI. Für Softwarefirmen mit Kundenprojekten. Open Source: auf deinem eigenen Server oder in unserer Cloud in Deutschland.
Translation pending
PatrolKit streamlines ski patrol administration — duty scheduling, time tracking, ski swap management, and patrol-wide engagement tools in one place.
Translation pending
BusinessTypeScript · JavaScriptGitHub @PatrolKitOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Ski patrol operations in one app: ski swap check-in, tags, Square sales, PayPal seller payouts, time clock and provisioned devices. Self-host it on AWS.
Translation pending
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
PatrolKit runs a ski patrol's organization:
• members and permissions;
• a ski swap: seller check-in, tags and printing, sales through Square, payouts to sellers through PayPal;
• a time clock;
• provisioned devices: check-in iPads, plus print and scanner bridges.
One installation hosts many organizations. Each one connects its own Square and PayPal accounts from inside the app.
This repository holds the API and the web app. This README covers running it locally and deploying it on your own AWS account.Read the full README ↗PatrolKit runs a ski patrol's organization:
One installation hosts many organizations. Each one connects its own Square and PayPal accounts from inside the app.
This repository holds the API and the web app. This README covers running it locally and deploying it on your own AWS account.
┌──────────────── EC2 instance ────────────────┐
app.example.org ──▶ │ Caddy (TLS) ──▶ Node.js app on :4000 (pm2) │ ──▶ RDS MySQL 8
swap.example.org ──▶ │ API + staff and seller web │ ──▶ S3, SES, SNS
└───────────────────────────────────────────────┘
▲
Square and PayPal (per org) ───┘ Square API calls; PayPal payout webhooks
/api/v1, the staff app under /app, and the seller-facing site at the root.Needs:
.npmrc):pnpm config set "//npm.fontawesome.com/:_authToken" <your Font Awesome package token>
Then:
node scripts/dev-setup.mjs
pnpm dev
dev-setup.mjs is safe to rerun. It:
docker-compose.yml);apps/api/.env from .env.example, with fresh JWT keys;Once pnpm dev is running:
/api to the API.GET /readyz checks the app and its database.To sign in, go to /app/auth/login with any seeded user from TESTING.md. Outbound email and SMS are off by default, so the page shows the sign-in code itself.
| Command | What it does |
|---|---|
pnpm dev | API and web in watch mode |
pnpm build · pnpm lint · pnpm test | Build, lint, unit tests (Jest for the API, Vitest for the web) |
pnpm db:migrate · pnpm db:seed | prisma migrate dev, and the seed (permissions, modules, the super admin, demo data in development) |
pnpm release | Deploy to your server (below) |
| Resource | Notes |
|---|---|
| EC2 instance | Amazon Linux 2023. Give it an Elastic IP. Its security group allows 80 and 443 from anywhere, and SSH only from you (or use EC2 Instance Connect). |
| RDS MySQL 8 | A database named, say, patrolkit. Its security group allows 3306 only from the instance's. |
| DNS | A records for your staff and seller hostnames, pointing at the Elastic IP. |
| SES | Verify your sending domain (DKIM). Request production access, or SES will only send to verified addresses. Sign-in links, invites and receipts all go by email. |
| S3 bucket (optional) | Item photos and org logos, read publicly from PHOTO_BASE_URL, so allow public s3:GetObject. Without it, logos live in the database and photos go only to Square. |
| SNS (optional) | Texted sign-in codes, US and Canadian numbers only. Needs an origination number: a toll-free number registered through AWS End User Messaging. Without it, everyone signs in by email. |
| IAM role for the instance | The policy below. |
{
"Version": "2012-10-17",
"Statement": [
{ "Effect": "Allow", "Action": ["ses:SendEmail"], "Resource": "*" },
{ "Effect": "Allow", "Action": ["sns:Publish"], "Resource": "*" },
{ "Effect": "Allow", "Action": ["s3:PutObject", "s3:GetObject", "s3:DeleteObject"], "Resource": "arn:aws:s3:::YOUR-PHOTO-BUCKET/*" }
]
}
If you use DEVICE_IMAGE_BUCKET for bridge firmware, add s3:GetObject on that bucket too.
npm install -g pm2) and Caddy. Run pm2 startup once, so the app comes back after a reboot./home/ec2-user/patrolkit. The release script deploys there./etc/caddy/Caddyfile, then sudo systemctl enable --now caddy. Caddy gets and renews the TLS certificates itself.app.example.org, swap.example.org {
reverse_proxy localhost:4000
}
Create /home/ec2-user/patrolkit/.env from .env.example. These matter in production:
| Variable | Set it to |
|---|---|
NODE_ENV | production |
DATABASE_URL | Your RDS connection string |
JWT_PRIVATE_KEY, JWT_PUBLIC_KEY | A pair from node scripts/gen-keys.mjs |
SQUARE_ENCRYPTION_KEY | openssl rand -hex 32. Keep it: changing it orphans every org's stored Square token. |
APP_URL | https://app.example.org |
SELLER_SITE_URL | https://swap.example.org |
COOKIE_DOMAIN | example.org |
OUTBOUND_NOTIFICATIONS | on. Anything else sends no email or SMS at all. |
MAIL_TRANSPORT, EMAIL_FROM, SES_REGION, AWS_REGION | ses, a verified sender, and your regions |
SEED_SUPERADMIN_EMAIL | Your email: the platform's first super admin |
PHOTO_BUCKET, PHOTO_BASE_URL, AWS_SNS_ORIGINATION_NUMBER | If you set up S3 and SNS |
scripts/release.mjs deploys over SSH. At the top of the script, set SERVER (e.g. [email protected]) and KEY (your SSH key). When you deploy, set VITE_SELLER_SITE_URL to your seller URL, since it's built into the web bundle.
VITE_SELLER_SITE_URL=https://swap.example.org pnpm release
The release:
prisma/ to the server;prisma migrate deploy and the seed;/readyz to answer.It warns if SELLER_SITE_URL is unset or OUTBOUND_NOTIFICATIONS isn't on. Run the same command for every later deploy.
https://app.example.org/app/auth/login with SEED_SUPERADMIN_EMAIL.https://app.example.org/api/v1/webhooks/paypal; register that URL in your PayPal application.pnpm release.pnpm release it. The migrations stay, and the older code ignores what it doesn't know.GET /readyz checks the app and its database. Point an uptime check or a load balancer at it..env, so keep a copy of .env somewhere safe.apps/api/scripts/smoke-*.mjs exercise a feature end to end against a running API. Each one's header says how to run it.
patrolkit-smoke, plus an empty patrolkit-smoke-other that checks one org can't see another's data.PAYOUTS_STUB=1 and the SMOKE_*_FILE variables)._fixture.mjs to the server and run it there with the .env loaded (set -a && . ./.env && set +a).The Bindings lookup says whether a binding model is on its maker's indemnified list. The models themselves are public, and ship in the item taxonomy. Which ones are indemnified, season by season, comes from licensed lists (NSSRA's combined list is for its members only), so this repository doesn't include it.
To use the lookup, get each season's lists yourself and convert them to the CSV format in docs/plan/44_binding_indemnification. Then load them through Platform Admin → Bindings, or with pnpm --filter api db:import-indemnification -- <season folder>. pnpm --filter api db:export-indemnification -- <folder> writes a database's lists back out in the same format, for a private backup. Keep these files out of any public repository.
server/
├─ apps/
│ ├─ api/ # NestJS API; serves the built web app in production
│ │ ├─ prisma/ # schema, migrations, seed, item taxonomy
│ │ └─ scripts/ # smoke scripts and one-off tools
│ └─ web/ # React + Vite: the staff app (/app) and the seller site (/)
├─ docs/plan/ # one folder per feature: its implementation plan and iPad handoff
├─ scripts/ # dev-setup.mjs, release.mjs, gen-keys.mjs
├─ docker-compose.yml # MySQL 8 + Mailpit, for local development
└─ .env.example # every variable the API reads
| Concern | What it uses |
|---|---|
| API | NestJS, TypeScript, Prisma on MySQL 8 |
| Web | React, Vite, TypeScript, Tailwind, TanStack Query, React Router, Font Awesome Pro |
| Sign-in | Passwordless: emailed sign-in links and texted codes; EdDSA JWTs; device tokens for provisioned devices |
| Email, SMS | Amazon SES; Amazon SNS. Locally, Mailpit. |
| Payments | Square (catalog, inventory, sales) and PayPal (payouts), connected per organization |
| Hosting | EC2, Caddy, pm2; RDS; S3 |
MIT, © 2026 ovrEngineered, LLC. Font Awesome Pro is licensed separately, by Fonticons, Inc.