- TypeScript 61.3%
- Astro 25.7%
- MDX 7.3%
- JavaScript 3.1%
- CSS 1.6%
- Other 1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .github/workflows | ||
| .vscode | ||
| drizzle | ||
| public | ||
| scripts | ||
| src | ||
| .dockerignore | ||
| .editorconfig | ||
| .env.example | ||
| .envrc | ||
| .gitignore | ||
| .npmrc | ||
| .prettierignore | ||
| .prettierrc.js | ||
| .prettierrc.json | ||
| AGENTS.md | ||
| ARCHITECTURE.md | ||
| astro.config.mjs | ||
| CHANGELOG.md | ||
| components.json | ||
| Dockerfile | ||
| documentation.html | ||
| drizzle.config.ts | ||
| eslint.config.mjs | ||
| flake.lock | ||
| flake.nix | ||
| hire-us.html | ||
| LICENSE.md | ||
| local.db | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| SECURITY-HARDENING.md | ||
| shirtigoapi.md | ||
| tsconfig.json | ||
JANJON — Storefront
Print-on-demand clothing shop ("JANJON", running on https://janjon.xanten.cc). Kleidung mit eigenen Designs — Print on Demand, aus Xanten. Built with Astro (SSR), React 19, Tailwind CSS v4, Drizzle + Turso/LibSQL, better-auth, Stripe, Shirtigo (POD) and Resend.
Table of Contents
- Prerequisites
- Quick Start
- Available Commands
- Environment Variables
- Configuration
- Type Checking & Linting
- Building for Production
- Deployment (Docker + Coolify)
- Going Live Checklist
- Further Reading
Prerequisites
-
Nix with flakes — recommended. The repo ships a
flake.nixthat provides the exact toolchain (Node.js 22 + pnpm), so you never depend on a system install:nix developWith direnv enabled, the repo's
.envrcloads it automatically oncd:direnv allowAll commands below are run inside the dev shell (
nix develop -c <command>works too). -
Or manually: Node.js 22+ and pnpm (corepack:
corepack enable).
Quick Start
# 1. Enter the dev shell (Node 22 + pnpm)
nix develop
# 2. Install dependencies
pnpm install
# 3. Create your environment file and fill in the values
cp .env.example .env
# 4. Initialize the database tables (plain Node — run from within the dev shell)
TURSO_DATABASE_URL=file:local.db node scripts/init-db.mjs
The database is a local SQLite file during development. Keep
TURSO_DATABASE_URL=file:local.dbin.envlocally — switch it tofile:/data/local.db(Coolify) or a Turso Cloud URL only for deployment. Node scripts do not read.envautomatically; pass the variable explicitly as shown above.
# 5. Start the dev server
pnpm dev
The site is now available at http://localhost:4321.
Auth redirects and
trustedOriginsuseSITE_URLfrom.env. Leave it athttps://janjon.xanten.cc(or your local domain) — it must always match where the app is served from, otherwise login/passkey flows break.
Available Commands
| Command | Action |
|---|---|
dev |
Start the Astro dev server with hot-reload at http://localhost:4321 |
build |
Create a production build (dist/) for the SSR server |
preview |
Preview the production build locally |
cache-images |
Pre-cache Shirtigo product images (node scripts/cache-images.mjs) |
astro check |
Full Astro type check (syncs .astro types first) |
check-types |
tsc --noEmit — works after .astro/types.d.ts was generated (run pnpm dev or pnpm astro check once on a fresh clone) |
lint / lint:fix |
ESLint (fix errors in place with lint:fix) |
format |
Prettier formatting across src/ |
clean |
Remove the .astro build cache |
Environment Variables
See .env.example for the full, commented list. Summary:
| Variable | Required | Purpose |
|---|---|---|
SITE_URL |
yes | Canonical domain — auth redirects, sitemap, OG/canonical URLs |
TURSO_DATABASE_URL |
yes | file:/data/local.db (Coolify) or Turso Cloud URL |
TURSO_AUTH_TOKEN |
for Turso Cloud | Auth token (not needed for local file DBs) |
STRIPE_SECRET_KEY |
yes | Stripe server key |
PUBLIC_STRIPE_PUBLISHABLE_KEY |
yes | Stripe publishable key (client) |
STRIPE_WEBHOOK_SECRET |
yes | Verifies Stripe webhooks |
SHIRTIGO_API_TOKEN |
yes | Shirtigo print-on-demand API |
SHIRTIGO_WEBHOOK_SECRET |
yes | Verifies Shirtigo webhooks |
RESEND_API_KEY |
yes | Transactional email (Resend) |
RESEND_FROM |
no | Sender, default JANJON <noreply@janjon.xanten.cc> |
ADMIN_ORDER_EMAIL |
no | Order-notification recipient, default steltner@pm.me |
CONTACT_EMAIL |
no | Contact-form recipient, default steltner@pm.me |
ENCRYPTION_KEY |
yes | Base64 32-byte AES key — openssl rand -base64 32. Never rotate once orders exist (encrypted addresses/emails) |
Optional: SHIRTIGO_PROJECTS_CACHE_TTL_MS, SHIRTIGO_PRODUCTS_CACHE_TTL_MS,
SHIRTIGO_PRODUCT_PRICE_FIELD, SHIRTIGO_DISABLE_CACHE.
Configuration
- Site / brand / legal data: edit
src/consts.ts(SITE_URL,SITE_TITLE,COMPANY_INFO,INVOICE_CONFIG). Company address, contact, and invoice details are currently placeholders — fill in real data before going live. - Legal pages:
src/pages/impressum.astro,widerruf.astro,agb.astro,datenschutz.astro. The shop operates under the Kleinunternehmerregelung (§ 19 UStG) — invoices show no USt and no USt-ID. - Site URL:
astro.config.mjsreadsSITE_URL;src/consts.tsuses it for canonical/OG metadata andbetter-authtrustedOrigins.
Type Checking & Linting
pnpm astro check # full Astro-aware type check (recommended)
pnpm check-types # plain tsc — needs .astro types generated first
pnpm lint # ESLint
pnpm lint:fix # auto-fix lint errors
pnpm format # Prettier
Run astro check before committing — it catches type errors in .astro files,
import.meta.env access, and API routes.
Building for Production
SITE_URL=https://janjon.xanten.cc pnpm build
The build emits an SSR server (dist/server/entry.mjs) plus static assets
(dist/client). The sitemap and canonical URLs are derived from SITE_URL.
Deployment (Docker + Coolify)
The Dockerfile builds the standalone Node.js server, exposing port 3000.
Startup sequence (Docker CMD):
node scripts/init-db.mjs— ensures DB tables existnode scripts/cache-images.mjs— pre-caches Shirtigo product imagesnode ./dist/server/entry.mjs— starts the Astro SSR server
docker build -t ink-shop .
docker run -p 3000:3000 --env-file .env ink-shop
On Coolify:
- Set all env vars from
.env.examplein the Coolify environment. - Expose port
3000. SITE_URLmust match the domain assigned in Coolify (https://janjon.xanten.cc).TURSO_DATABASE_URL=file:/data/local.dbwith a persistent volume mounted at/data(seescripts/backup-db.shfor the nightly backup setup on the host).
Going Live Checklist
Before opening the shop to the public:
- Real company data in
src/consts.ts(COMPANY_INFO,INVOICE_CONFIG) and on the legal pages (impressum,widerruf,agb,datenschutz). - Stripe webhook →
https://<SITE_URL>/api/webhooks/stripe(events:payment_intent.succeeded,payment_intent.payment_failed). - Shirtigo webhook →
https://<SITE_URL>/api/webhooks/shirtigo. - Resend: verify the sending domain (DKIM/SPF) in the Resend dashboard.
- Admin role:
UPDATE user SET role='admin' WHERE email='steltner@pm.me'; - Backups: set up
scripts/backup-db.shvia cron (seeARCHITECTURE.md§12).
Further Reading
ARCHITECTURE.md— tech stack, DB schema, payment/fulfillment flow, API routes, backupsSECURITY-HARDENING.md— security layers and hardening roadmap