Changelog
The latest features and improvements across ShipAny templates.
v1.0.7
Paid guest posts, appearance settings, user-center switches and a renewal fix
paymentadminuisecurity
- Paid guest posts — outside authors write at
/settings/guest-postsand pay to submit. Admins review at/admin/guest-posts: approve to publish on/blog, request changes (the author resubmits for free) or reject with a full refund. A public/guest-postpage pitches it. Off by default; turn it on at Settings → Users → Guest Posts - Search-engine safe — guest posts carry a Sponsored label, every external link renders
rel="sponsored nofollow"and gets UTM tags at render time. Authors pick their slug and can preview before publishing; word and link limits are checked the same way in the editor and on the server - Guest post packages live in code — prices and link limits are
kind: 'guest_post'entries insrc/config/pricing.ts, like the main plans. A new genericorder.reference(<kind>:<id>) ties an order to the record it buys, so payment, publishing and refunds happen in one atomic write - Appearance settings — admins can pick light/dark, a color theme (Classic, Forest, Ocean, Violet, Sunset, Rose, Slate), font, font size and the sidebar layout at Settings → General → Appearance, and optionally let users choose their own theme color. Rendered on the server, so there is no flash. Off by default: the site keeps its look from code
- User-center switches — credits, billing, payments, API keys and tickets can each be turned off at Settings → Users → User Features. Hidden pages redirect and their APIs refuse. Signup and role settings moved to the new Users tab
- Dashboard polish — the sidebar shows your logo next to the toggle, and only the first nav group (plus the one you're in) starts expanded. Confirmations use a shared dialog instead of the browser's
- Subscription renewals no longer skip credits — Stripe usually sends the subscription update before the renewal payment. When it did, the renewal was treated as already handled: the user was charged but got no renewal order or credits (Creem and PayPal went through the same path). Renewals are now claimed by a unique order number derived from the billing period, so event order doesn't matter
- Dependency security upgrade —
pnpm auditgoes from 189 advisories to 2. drizzle-orm 0.45, latest TanStack Start/Router, Vite, nitro and wrangler (no major bumps), and Next.js is no longer installed as better-auth's unused peer - Separate dev sessions per project — several projects on
localhostno longer sign each other out; the session cookie prefix comes fromAUTH_COOKIE_PREFIXor, in dev, the app name. Production cookies are unchanged - Plausible's allowed script hosts are read at runtime (
PLAUSIBLE_SCRIPT_HOSTS), so changing them needs no rebuild, and a rejected host no longer blocks saving the other analytics settings - Payment notifications show the correct list price when a coupon is applied at checkout. Bot messages now start with 【app name】, and checkout return URLs keep the buyer's language
AGENTS.mdgains sections on guest posts, user-center switches and appearance; thedesign-themeskill knows about the color themes- New test suites:
pnpm test:guest-postsandpnpm test:payment, including renewal events arriving in either order - Attribution: an
X-Powered-By: ShipAnyheader and a generator meta tag. The "Built with ShipAny" footer badge is optional per the LICENSE and now matches your theme colors - The README was rewritten for ShipAny TanStack
- Schema: one new table,
guest_post, and one nullable column,order.reference.schema.tsisn't tracked by git, so copy them in, then migrate - New permissions: run
pnpm admin:token sync-permissionsto registeradmin.guest-posts.read,.reviewand.reject - Dependencies: run
pnpm install. In your own server functions, rename.inputValidator()to.validator(); the old name no longer exists at runtime - API keys: the user-center API keys page is now off by default. Turn it on if your users rely on it
- Missed renewals: if you ran recurring plans on the 2026-10-11 code, compare the provider's paid renewal invoices with your
reneworders and grant any missing credits - The full checklist is the 2026-10-17 and 2026-10-28 entries in
UPGRADING.mdat the repo root
v1.0.6
User activity timeline, custom event reporting and admin password reset
adminanalyticsagent
- User activity timeline — the user detail page shows everything a user did, in time order: sign-up, orders created and paid, subscriptions, credit grants and charges, AI generations that succeeded or failed, and tickets. It is built from existing tables, so history shows up as soon as you upgrade
- Readable and clickable — oldest first by default, so it reads top to bottom as the user's path to paying; switch to newest first for recent activity. Each row opens its order, subscription, credit record or ticket. Events in the same instant follow the real flow (order → payment → subscription → credits)
- Custom event reporting — register a kind in
src/config/events.ts, then report it withrecordEvent()on the server ortrack()in the browser, and it appears in the timeline. Three examples ship: plan picked (reported by the pricing table), paywall hit, and risk flag - Plug in your own tables — events your project already stores (a gift log, say) join the timeline through a loader in
timeline-sources.ts, with an admin page to open on click - Set user passwords — "Set password" in the users list menu signs the user out everywhere and gives OAuth-only users an email/password login. It needs the dedicated
admin.passwords.resetpermission, can't target accounts above the caller, and is refused for agent keys - Agents can read a user's history — the new
users_timelineoperation lets an agent answer "how did this user convert, and where did they stall?" - The users list menu is wider so labels don't wrap; subscriptions and credits lists accept a search term from the URL
- Reporting is in the rules and skills:
AGENTS.mdgains a "Product events" section.new-module,new-pageandquick-startprompt agents to report events at paywalls and key actions, andshipany-adminshows how to investigate a user with the timeline - Safe by default: only kinds marked client-reportable can come from the browser; payment, risk and permission events are server-only. Browser reports require a signed-in user on your own pages, are rate-limited, and carry only a small flat
detail - Tests for event reporting, timeline ordering and paging, and password reset
- Schema: one new table,
user_event; existing tables are unchanged.schema.tsisn't tracked by git, so copy the table into it, then migrate - New permission: run
pnpm admin:token sync-permissionsto registeradmin.passwords.reset - The full checklist is the 2026-10-12 entry in
UPGRADING.mdat the repo root
v1.0.5
Agent API, analytics, refunds, atomic writes on D1 and a security sweep
agentadminpaymentsecuritycloudflare
- Agent API — create agent accounts on the new "Agent API" admin page, grant them roles, and issue
sa_admin_keys that can expire and are shown only once. Agents such as Claude Code and Codex run the admin console through a Skill or MCP. Every call is journaled for idempotency, and the Logs tab shows the calls per agent - Multi-site Skill client — one agent can manage several ShipAny sites, with each site's key kept in a private local file (mode 0600) and selected by project name
- Analytics — overview KPIs (users, 30-day net revenue, active subscriptions, open tickets) and a cohort conversion funnel filterable by UTM, referrer and country. The new
analytics_reportoperation lets agents write daily and weekly reports - Admin refunds for Stripe, Creem, PayPal, Alipay and WeChat Pay. A refund claws back the order's credits and can cancel the subscription. It needs the dedicated
admin.payments.refundpermission, which only super admins hold by default - User detail page with signup attribution (UTM, referrer, country), roles, and order and credit totals. The users list gains ID, effective-role and utm_source filter columns
- Admin lists — payments, subscriptions, credits and tickets show users as avatar + name + email, linking to the detail page. Search is case-insensitive and matches email, name or user ID
- Bot notifications for new orders and ticket activity via Telegram, Feishu, WeCom or a generic webhook
- Cookie consent banner, enabled from admin settings, with a "Cookie settings" link in the footer
- CNY pricing — products can set
cnyPriceInCents, and Alipay and WeChat Pay charge that price
- Payment notifications: on top of the signature check, Alipay and WeChat Pay notifications must match the configured
app_id/ merchant ID and the order amount, so another merchant's transaction can't settle your order - Credits are granted exactly once: settlement is guarded, and grants carry a per-order unique transaction number. The admin order edit can only close an unpaid order and can no longer move a paid order back to pending
- No privilege escalation: role and permission assignment can't exceed the caller's own permissions, and an admin role can't be the default role for new users
- Account takeover: with better-auth 1.7, OAuth sign-in no longer links to a password account whose email was never verified
- Secret exfiltration: changing the OpenAI, Anthropic, R2, Telegram or webhook endpoint requires re-entering its secret
- Script injection: analytics, ads and support-widget IDs are validated on save and on render. Plausible scripts load only from a same-site path, plausible.io, or hosts listed in the deployment env
VITE_PLAUSIBLE_SCRIPT_HOSTS - Rate limits and uploads: limits are keyed by IP and user, so swapping cookies no longer bypasses them. Uploads are capped at 10 files and 20 MB per request, and SVG is refused
- On Workers the client IP comes from the unspoofable
cf-connecting-ip;serovalis pinned to 1.6.8
- Atomic writes on D1: D1 has no interactive transactions, so
db().transaction()ran statement by statement there. A failure halfway could leave a paid order without credits, or a half-charged balance. The newatomic()commits with a singlebatch()on D1, SQLite and Turso and uses a real transaction on Postgres and MySQL. Checkout settlement, renewals, refunds, credit charges and revokes, AI task creation and invite redemption all use it, with concurrency tests on local D1, SQLite and Postgres - No more USD amounts charged as CNY: Alipay and WeChat Pay refuse products that have no CNY price
- Workers database connections: Postgres and MySQL get a client per request, and Hyperdrive query caching is off by default so order status, balances and settings are never up to 60 s stale
- Deploy:
compatibility_dateis pinned, so builds no longer fail when local time is a day ahead of UTC - Successful checkout now lands on
/settings/payments; subscription search, previously ignored by the API, now filters
- AGENTS.md gains two sections. "Atomic writes" shows how to use
atomic(). "Security & Integrity Rules" turns this round's findings into rules for new features: money, webhooks, permissions, secrets, rate limits and tests - New
UPGRADING.mdwalks agents through pulling template updates into an existing project: port the schema, migrate, register new permissions, and the manual steps - New
pnpm test:atomic,test:atomic:d1andtest:atomic:pg, plus regression tests for payments, refunds and permissions pnpm admin:tokenCLI creates agents, issues keys and registers new permissions
- Schema: additive only.
schema.tsisn't tracked by git, so copy the new columns into it, then migrate - Alipay / WeChat Pay: set
cnyPriceInCentson products, or those providers can't take orders - Self-hosted Plausible: if the script is a full URL on your own host, add that host to
VITE_PLAUSIBLE_SCRIPT_HOSTSand rebuild (it is baked in at build time), or the script stops loading. Same-site proxy paths like/js/script.jsare unaffected - New permissions: run
pnpm admin:token sync-permissions - The full checklist is in
UPGRADING.mdat the repo root
v1.0.4
Webhook reliability, admin workflows, desktop auth hand-off
paymentauthadmindx
- Admin workflows — order detail/edit dialog on the payments page, reworked users / roles / permissions screens, richer API keys management, ticket handling
- Customer service widgets — Crisp and Tawk.to, toggled from admin settings
- Cloudflare Email provider alongside Resend; auth emails now go through a provider-agnostic sender
- Return-to-origin redirects — sign-in, Google One Tap, the support widget and checkout all bring the user back to the page they started from
- Desktop hand-off — a new
/auth-callbackpage hands a session token to app protocol URLs (myapp://…), limited to the schemes allow-listed in the newdesktop_auth_schemessetting (empty by default) - Signup grants — the "grant credits on signup" toggle and the default role are finally applied to new users
- /ads.txt route and AdSense support
- AUTH_TRUSTED_ORIGINS accepts hostname-suffix wildcards (
.e2b.app) for sandbox preview domains
- Stripe webhooks on Cloudflare Workers: signature verification switched to
constructEventAsync()— the sync call threw "SubtleCryptoProvider cannot be used in a synchronous context" and broke every event - Webhook failures return 500 so providers retry. They previously answered HTTP 200, so Stripe marked failed deliveries as succeeded and silently dropped renewals, periodic credits and subscription status syncs. Events the app doesn't handle are still acked with 2xx
- Subscription renewals: renewal invoices are routed to the renewal handler instead of the first-purchase path, and deduped by provider + invoice ID
- Admin settings: saved values take effect immediately (config cache refresh); the public config endpoint no longer returns secrets
- Selects: a closed trigger shows the item label instead of the raw value
- Docker build: reads
.env.productionand setsNODE_ENVin the builder stage soVITE_*vars get inlined - Dev server: allows e2b sandbox preview hosts
- design-theme skill v2 — derives a distinctive visual identity from the project brief, with a 9-direction style library and an anti-slop checklist, so a new site never ships the stock look
- Sandbox preview bridge — reports route changes and on-page links to the ShipAny Code parent frame
- AGENTS.md: admin console hand-off, mandatory
pnpm db:pushafter schema changes, Playwright/Chromium availability in the sandbox
v1.0.3
llms.txt, error pages, Creem mapping, email fix, Prettier
seouxpaymentauthdx
- /llms.txt and /llms-full.txt routes — AI-readable site map, auto-generated from pages + blog posts
- Styled error boundary in root route — "Oops" heading, retry button, dev-only error display (replaces TanStack Router default)
- Creem Product IDs Mapping — admin setting to map internal product IDs to Creem
prod_xxxIDs; auto-resolved during checkout
- Email verification: public config API now supports Cloudflare Email provider for
email_verification_enabledandpassword_reset_enabled - Sign-in: detects
EMAIL_NOT_VERIFIEDerror code directly — always redirects to verify-email page - Verify-email Continue: shows toast instead of redirecting to sign-in when not yet verified
- Prettier + husky + lint-staged — auto-format on commit
- New scripts:
pnpm formatandpnpm format:check - Full codebase format pass applied
v1.0.2
OpenAI & Anthropic settings, custom configs, and login redirect
adminaiauth
- Admin AI settings now include OpenAI and Anthropic providers (custom
Base URL+ API Key), each with a live Test that runs a real chat-completion check; Gemini card removed - Provider Test uses the values currently entered in the form — even unsaved — falling back to saved config (masked secrets left untouched)
- New Custom settings tab — manage arbitrary key/value configs with add/remove rows
- Auth: protected pages redirect to sign-in with a
callbackUrland send you back to the original page after login, preserved across the sign-in / sign-up switch
- Turso: fixed
drizzle.config.ts(turso dialect mapping +DATABASE_AUTH_TOKEN) sodb:push/db:generateauthenticate against the remote libsql database
v1.0.1
One-click deploy to Cloudflare Workers
cloudflaredeploy
- One-click deploy to Cloudflare Workers (D1, or Postgres + Hyperdrive)
- New
deploy-cloudflareskill — handles D1, secrets, schema push and redeploy automatically - Fixed a number of SSR and hydration edge cases
v1.0.0
ShipAny TanStack first release
releasetanstack-start
The newest member of the ShipAny family — the full agent-native business engine, now on TanStack Start.
- Brand-new template on TanStack Start (Vite 8 + Nitro + React 19, TypeScript strict)
- File-based routing — no RSC, no
"use client", all plain React components - TanStack Query / Form / Table throughout, backed by a typed api-client
- Paraglide JS i18n — compiled, tree-shakeable message functions
- better-auth + Drizzle ORM, sharing ShipAny's modular business logic (auth, credits, payments & subscriptions, API keys, RBAC)
