g1t/apps/web/app/routes/pricing.tsx

518 lines25,238 bytesCodeBlame

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

Prices keep themselves current with what g1t pays1import { ArrowUpRight } from "lucide-react";
2
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas3import { type FeaturePlan, type FreeTier, MICROS_PER_DOLLAR, type Price } from "@g1t/contracts";
Prices keep themselves current with what g1t pays4
5import type { Route } from "./+types/pricing";
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look6import { wholeDollars } from "../lib/billing";
Social cards for every page: og.g1t.sh7import { page } from "../lib/meta";
Prices keep themselves current with what g1t pays8import { TimeAgo } from "../components/ui";
9import { billing } from "../lib/services.server";
10
Social cards for every page: og.g1t.sh11export function meta(args: Route.MetaArgs) {
12 return page(args, {
13 title: "Pricing · g1t",
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put14 description:
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look15 "The forge is free. One plan, $20 a month per workspace with $10 of usage included; usage at what it costs g1t plus 20%. No seats, ever.",
Social cards for every page: og.g1t.sh16 });
Prices keep themselves current with what g1t pays17}
18
19export async function loader() {
Billing accounts, terms and enterprises; g1t is no longer free20 const [book, status] = await Promise.all([billing.prices().catch(() => null), billing.status().catch(() => null)]);
21 return { book, free: status?.free ?? false };
Prices keep themselves current with what g1t pays22}
23
24/** A price in dollars, with as many digits as it needs to say anything. */
25function money(micros: number): string {
26 const dollars = micros / MICROS_PER_DOLLAR;
27 if (dollars >= 1) return `$${dollars.toFixed(2)}`;
28 if (dollars >= 0.01) return `$${dollars.toFixed(3)}`;
29 return `$${dollars.toPrecision(2)}`;
30}
31
32/** Per second is easier to read per minute. */
33function perUnit(price: Price, micros: number): string {
34 return price.unit === "second" ? `${money(micros * 60)} a minute` : `${money(micros)} per ${price.unit}`;
35}
36
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put37function gigabytes(bytes: number): string {
38 return `${Math.round((bytes / 1e9) * 10) / 10} GB`;
39}
40
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look41function count(n: number): string {
42 return n.toLocaleString("en-US");
43}
44
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put45/** What the page says when billing cannot be reached: the published defaults. */
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look46const DEFAULT_FREE: Required<FreeTier> = {
47 trialWorkspaceMicros: 5_000_000,
48 trialMonthlyPoolMicros: 100_000_000,
49 ossPoolMicros: 25_000_000,
50 ossRepoMicros: 2_000_000,
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put51 freePrivateStorageBytes: 1_000_000_000,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look52 auditRetentionDays: 90,
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put53 minChargeMicros: 5_000_000,
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas54 gitOperationsIncluded: 50_000,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look55 paidStartCeilingMicros: 100_000_000,
56 overageForgiveCostMicros: 50_000_000,
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put57};
58
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look59const DEFAULT_PLAN: FeaturePlan = {
60 feature: "plan",
61 title: "g1t",
62 monthlyCents: 2000,
63 includes: [
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas64 "$10 of usage each month at cost plus 20%, used first",
65 "Everyone in the workspace at one price, never per person",
66 "Unlimited projects, previews and repositories",
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look67 "Agents, checks, workflows, the merge queue, deployments and semantic search",
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas68 "Usage past $10 is charged at cost plus 20%, up to your spend limit",
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look69 ],
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas70 overage: "Everything is metered from the first unit at what it costs g1t plus 20%. Unused included usage does not roll over.",
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look71};
72
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put73/** The ways to reach g1t about an enterprise account. */
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look74const ENTERPRISE_MAIL = "mailto:hey@flagon.io?subject=Enterprise%20billing%20for%20g1t";
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put75
Prices keep themselves current with what g1t pays76const HOW = [
77 {
78 title: "Our cost, passed through",
Prices are what g1t pays plus 20%, from the first second79 body: "Every sandbox second, build, app request and model token costs g1t money at Cloudflare or a model provider. Each is metered and charged at that cost plus 20%, from the first second and the first request. Use a little, pay a little.",
Prices keep themselves current with what g1t pays80 },
81 {
82 title: "Prices follow costs, by themselves",
83 body: "Model runs are charged at what Cloudflare's AI Gateway priced each request at, so a provider's price change reaches you the same day. Every day, each Cloudflare cost is checked against what Cloudflare billed g1t; when one moves, its price moves with it, and the change is listed below.",
84 },
85 {
Prices are what g1t pays plus 20%, from the first second86 title: "The 20% is the overhead",
87 body: "It pays for running g1t and for building and keeping up the features you use. The same 20% on everything, and nothing bundled in.",
88 },
89 {
Prices keep themselves current with what g1t pays90 title: "No seats, ever",
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look91 body: "Add as many people and agents as you like. A workspace pays one flat price for the plan, and for what it uses past what the plan includes.",
Prices keep themselves current with what g1t pays92 },
93];
94
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look95/** One row of the free-and-plan table. */
96type Row = { what: string; free: string; plan: string; note?: string };
97
98function rows(tier: Required<FreeTier>): Row[] {
99 return [
100 {
101 what: "The forge",
102 free: "Free",
103 plan: "Included",
104 note: "Public and private repositories, issues, pull requests, reviews, protected branches, code owners, search and Explore.",
105 },
106 {
107 what: "Agents, checks, workflows, merge queue",
108 free: "After a card check: the trial, and the open-source pool for checks, workflows and the merge queue on public repositories",
109 plan: "From the plan's included usage, then at cost plus 20%",
110 },
111 {
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas112 what: "Projects and previews",
113 free: "Not available: deployments run on g1t's machines",
114 plan: "Unlimited, and never charged for. An app no one visits costs nothing.",
115 },
116 {
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look117 what: "Deployments",
118 free: "Not available",
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas119 plan: "Builds by the second, app requests, CPU time and custom domains, each from the first at cost plus 20%",
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look120 },
121 {
122 what: "Semantic search",
123 free: "After a card check, from the trial",
124 plan: "From the plan's included usage, then at cost plus 20%",
125 },
126 {
127 what: "Private storage",
128 free: `${gigabytes(tier.freePrivateStorageBytes)}, never charged. Past it, pushes to private repositories stop until you make room or start the plan.`,
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas129 plan: `${gigabytes(tier.freePrivateStorageBytes)} free, then at cost plus 20%. Pushes never stop.`,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look130 note: "Public repositories are never charged for storage.",
131 },
132 {
133 what: "Git operations",
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas134 free: `${count(tier.gitOperationsIncluded)} a month, never charged. Past it, slowed to 60 an hour until the month turns.`,
135 plan: `${count(tier.gitOperationsIncluded)} a month free, then at cost plus 20%. Never slowed.`,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look136 note: "Clones, fetches and pushes through g1t.",
137 },
138 {
139 what: "Audit log",
140 free: `${tier.auditRetentionDays} days, with export`,
141 plan: `${tier.auditRetentionDays} days, with export`,
142 },
143 { what: "Secret push protection", free: "Included", plan: "Included" },
144 { what: "Single sign-on", free: "On every plan, once it is built", plan: "On every plan, once it is built" },
145 { what: "Members", free: "Unlimited", plan: "Unlimited" },
146 {
147 what: "Usage past what is included",
148 free: "Not possible: a free workspace never runs up a bill",
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas149 plan: "Charged at cost plus 20%, up to a spend limit you set. No quotas: only your limit stops anything.",
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look150 },
151 ];
152}
153
Prices keep themselves current with what g1t pays154export default function Pricing({ loaderData }: Route.ComponentProps) {
Billing accounts, terms and enterprises; g1t is no longer free155 const { book, free } = loaderData;
Prices keep themselves current with what g1t pays156 const checked = book?.prices.map((p) => p.checkedAt).filter((at): at is string => !!at).sort().at(-1);
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look157 const given = Object.fromEntries(Object.entries(book?.free ?? {}).filter(([, value]) => value != null));
158 const tier: Required<FreeTier> = { ...DEFAULT_FREE, ...given };
159 const plan = book?.plans?.find((p) => p.feature === "plan") ?? DEFAULT_PLAN;
160 const price = plan.monthlyCents / 100;
161 const dollars = wholeDollars;
Prices keep themselves current with what g1t pays162 return (
163 <main className="mx-auto max-w-4xl px-4 py-12">
164 <p className="text-sm font-medium text-accent">Pricing</p>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look165 <h1 className="mt-2 text-3xl font-semibold tracking-tight sm:text-4xl">One plan, and usage at cost plus 20%</h1>
Prices keep themselves current with what g1t pays166 <p className="mt-3 max-w-2xl text-muted">
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look167 The forge is free for everyone. Work that runs on g1t's machines is metered at what it costs g1t, plus 20%. The
168 numbers on this page are the live price book g1t charges from.
Prices keep themselves current with what g1t pays169 </p>
Billing accounts, terms and enterprises; g1t is no longer free170 {free && (
171 <div className="mt-5 rounded-xl border border-accent/30 bg-accent/5 px-4 py-3 text-sm">
172 <span className="font-medium">Free while g1t is being built out.</span>{" "}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look173 <span className="text-muted">Usage is recorded at these prices but not charged for now. The plan is charged.</span>
Billing accounts, terms and enterprises; g1t is no longer free174 </div>
175 )}
Prices keep themselves current with what g1t pays176
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look177 <section className="mt-10 rounded-xl border border-accent/40 bg-surface p-6">
178 <div className="flex flex-wrap items-baseline justify-between gap-3">
179 <h2 className="text-xl font-semibold tracking-tight">{plan.title}</h2>
180 <p>
181 <span className="text-3xl font-semibold tabular-nums">${price}</span>{" "}
182 <span className="text-sm text-muted">a month per workspace</span>
183 </p>
184 </div>
185 <ul className="mt-4 space-y-1.5 text-sm text-muted">
186 {plan.includes.map((line) => (
187 <li key={line} className="flex gap-2">
188 <span aria-hidden className="text-accent">
189 ✓
190 </span>
191 {line}
192 </li>
193 ))}
194 </ul>
195 <p className="mt-3 text-xs text-faint">{plan.overage}</p>
196 <div className="mt-5 grid gap-5 border-t border-line pt-5 text-sm sm:grid-cols-2">
197 <div>
198 <p className="font-medium">Where the ${price} goes</p>
199 <p className="mt-1 text-muted">
200 $10 comes back to you as usage: agents, sandboxes, builds and deployments at cost plus 20%, used before
201 anything else. The other $10 pays for running g1t, the free forge for everyone, and the people building it.
202 </p>
203 </div>
204 <div>
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas205 <p className="font-medium">No quotas</p>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look206 <p className="mt-1 text-muted">
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas207 No count of projects, previews, builds, requests or git operations ever stops a workspace on the plan. Past
208 the $10, usage is charged at cost plus 20%, and only your spend limit stops it. Unused included usage does
209 not roll over.
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look210 </p>
211 </div>
212 </div>
213 <p className="mt-5 text-sm text-muted">An owner starts the plan from the workspace's Billing page.</p>
214 </section>
215
216 <h2 className="mt-14 text-xl font-semibold tracking-tight">Free and the plan, side by side</h2>
217 <p className="mt-1 text-sm text-muted">No security feature is held back for a plan.</p>
218 {/* On a phone, one row at a time with both answers under it; a table that wide would scroll. */}
219 <ul className="mt-4 divide-y divide-line rounded-xl border border-line text-sm sm:hidden">
220 {rows(tier).map((row) => (
221 <li key={row.what} className="px-4 py-3">
222 <p className="font-medium">{row.what}</p>
223 {row.note && <p className="text-xs text-faint">{row.note}</p>}
224 <dl className="mt-2 grid grid-cols-[4.5rem_1fr] gap-x-3 gap-y-1.5">
225 <dt className="text-xs leading-5 text-faint">Free</dt>
226 <dd className="text-muted">{row.free}</dd>
227 <dt className="text-xs leading-5 text-faint">{plan.title}</dt>
228 <dd className="text-muted">{row.plan}</dd>
229 </dl>
230 </li>
231 ))}
232 </ul>
233 <div className="mt-4 hidden overflow-x-auto rounded-xl border border-line sm:block">
234 <table className="w-full min-w-[36rem] text-left text-sm">
235 <thead className="border-b border-line text-xs text-muted">
236 <tr>
237 <th className="px-4 py-2.5 font-medium">
238 <span className="sr-only">What</span>
239 </th>
240 <th className="px-4 py-2.5 font-medium">Free</th>
241 <th className="px-4 py-2.5 font-medium">
242 {plan.title}, ${price} a month
243 </th>
244 </tr>
245 </thead>
246 <tbody className="divide-y divide-line">
247 {rows(tier).map((row) => (
248 <tr key={row.what} className="align-top">
249 <td className="px-4 py-3">
250 <p className="font-medium">{row.what}</p>
251 {row.note && <p className="text-xs text-faint">{row.note}</p>}
252 </td>
253 <td className="px-4 py-3 text-muted">{row.free}</td>
254 <td className="px-4 py-3 text-muted">{row.plan}</td>
255 </tr>
256 ))}
257 </tbody>
258 </table>
259 </div>
260 <p className="mt-3 text-sm text-muted">
261 Git operations cost g1t money too: Cloudflare charges g1t $0.15 per 1,000. {count(tier.gitOperationsIncluded)} a
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas262 month is far more than an active workspace uses; an agent run takes two to four.
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look263 </p>
264
265 <h2 className="mt-14 text-xl font-semibold tracking-tight">No card, no compute</h2>
266 <div className="mt-3 max-w-3xl space-y-3 text-sm text-muted">
267 <p>
268 Agents, checks, workflows, the merge queue, deployments and semantic search run on g1t's machines. They need
269 the plan, or a card check.
270 </p>
271 <p>
272 The reason: compute costs g1t real money from the first second, and free compute draws people who use it to
273 mine cryptocurrency. A card check is the smallest gate that stops that, with one trial per card.
274 </p>
275 <p>
276 A card check is never charged. Stripe saves and verifies the card, with 3-D Secure where your bank asks for it.
277 Nothing is charged until an owner starts the plan, and then the same card is used, without asking for it again.
278 The trial needs a credit or debit card; prepaid cards can still pay for the plan.
279 </p>
280 </div>
281
282 <div className="mt-5 grid gap-4 sm:grid-cols-2">
283 <section className="rounded-xl border border-line bg-surface p-5">
284 <h3 className="font-medium">The trial</h3>
285 <p className="mt-1.5 text-sm text-muted">
286 {dollars(tier.trialWorkspaceMicros)} of usage, once per workspace and once per card, after a card check with a credit or
287 debit card. It comes from a{" "}
288 {dollars(tier.trialMonthlyPoolMicros)} pool each month for everyone; when a month's pool is given out, new
289 trials wait until the 1st. The trial does not cover deployments and never turns into a charge. If the last
290 run on a trial goes past it, g1t covers the difference.
291 </p>
292 </section>
293 <section className="rounded-xl border border-line bg-surface p-5">
294 <h3 className="font-medium">The open-source pool</h3>
295 <p className="mt-1.5 text-sm text-muted">
296 Checks, workflows and the merge queue on public repositories, after a card check:{" "}
297 {dollars(tier.ossPoolMicros)} a month in all, up to {dollars(tier.ossRepoMicros)} a month per repository.
298 Agents do not run from the pool. When the pool or a repository's share is used up, the work waits for the
299 month to turn, or the workspace pays as usual.
300 </p>
301 </section>
302 </div>
303
304 <h2 className="mt-14 text-xl font-semibold tracking-tight">Limits, and how to raise them</h2>
305 <p className="mt-1 max-w-3xl text-sm text-muted">
306 g1t lets usage run ahead of payment only so far. Limits keep a mistake small, for you and for g1t.
307 </p>
308 <ul className="mt-4 grid gap-3 text-sm sm:grid-cols-2">
309 <li className="rounded-xl border border-line bg-surface p-4">
310 <p className="font-medium">{dollars(tier.paidStartCeilingMicros)} in the first month</p>
311 <p className="mt-1 text-muted">
312 A workspace on the plan can use up to {dollars(tier.paidStartCeilingMicros)} in its first month. After that,
313 the limit grows with payments that clear.
314 </p>
315 </li>
316 <li className="rounded-xl border border-line bg-surface p-4">
317 <p className="font-medium">Your own spend limit</p>
318 <p className="mt-1 text-muted">
319 Owners set a monthly spend limit anywhere up to the highest limit the workspace has had, with no approval.
320 Once, you can raise it yourself to twice that.
321 </p>
322 </li>
323 <li className="rounded-xl border border-line bg-surface p-4">
324 <p className="font-medium">Prepay to raise it now</p>
325 <p className="mt-1 text-muted">
326 Prepaying from $25 raises what you can use by the same amount, at once. From $1,000 you can also pay by bank
327 transfer.
328 </p>
329 </li>
330 <li className="rounded-xl border border-line bg-surface p-4">
331 <p className="font-medium">Raise my limit</p>
332 <p className="mt-1 text-muted">
333 Need more? Ask from Billing with the amount, why, and what you expect to spend. You get an answer within one
334 business day, in the app and by email.
335 </p>
336 </li>
337 </ul>
338
339 <h2 className="mt-14 text-xl font-semibold tracking-tight">When usage runs high</h2>
340 <ul className="mt-4 grid gap-3 text-sm sm:grid-cols-2">
341 <li className="rounded-xl border border-line bg-surface p-4">
342 <p className="font-medium">A spike pauses new work</p>
343 <p className="mt-1 text-muted">
344 When an hour's spend is five times your usual hour, and at least $5, new compute waits for an owner to choose
345 Keep going or Stop. Runs already going finish.
346 </p>
347 </li>
348 <li className="rounded-xl border border-line bg-surface p-4">
349 <p className="font-medium">Caps per run and per issue</p>
350 <p className="mt-1 text-muted">
351 One agent run stops at $2 and the agents on one issue at $10 in all, so a run stuck in a loop stops on its own.
352 Owners change both on Billing.
353 </p>
354 </li>
355 <li className="rounded-xl border border-line bg-surface p-4">
356 <p className="font-medium">Alerts at 50, 75, 90 and 100%</p>
357 <p className="mt-1 text-muted">
358 Of the plan's included usage, your spend limit and g1t's limit: in the app and by email.
359 </p>
360 </li>
361 <li className="rounded-xl border border-line bg-surface p-4">
362 <p className="font-medium">Spent more than you meant to? Tell us</p>
363 <p className="mt-1 text-muted">
364 Tell us from Billing what happened. Once in 12 months, g1t can credit back usage you did not mean, always
365 including its 20% on it. Larger credits, or a second one within 12 months, are reviewed by a person.
366 </p>
367 </li>
368 </ul>
369 <p className="mt-3 text-sm text-muted">
370 No card is charged less than {dollars(tier.minChargeMicros)} when a month closes, so a payment's fee is never most
371 of it. Smaller amounts carry over to the next invoice. Charges at a limit always go through.
372 </p>
373
374 <div className="mt-14 grid gap-4 sm:grid-cols-2">
Prices keep themselves current with what g1t pays375 {HOW.map((item) => (
376 <section key={item.title} className="rounded-xl border border-line bg-surface p-5">
377 <h2 className="font-medium">{item.title}</h2>
378 <p className="mt-1.5 text-sm text-muted">{item.body}</p>
379 </section>
380 ))}
381 </div>
382
383 <h2 className="mt-14 text-xl font-semibold tracking-tight">Usage</h2>
384 <p className="mt-1 text-sm text-muted">
385 {checked ? (
386 <>
387 Last checked against Cloudflare's bill <TimeAgo at={checked} />.
388 </>
389 ) : (
390 "Starting from Cloudflare's published prices; checked against its bill daily."
391 )}
392 </p>
393 <div className="mt-4 overflow-x-auto rounded-xl border border-line">
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look394 <table className="w-full text-left text-sm sm:min-w-[36rem]">
Prices keep themselves current with what g1t pays395 <thead className="border-b border-line text-xs text-muted">
396 <tr>
397 <th className="px-4 py-2.5 font-medium">What</th>
398 <th className="px-4 py-2.5 font-medium">Costs g1t</th>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look399 {/* The markup is in what you pay; on a phone the column gives way. */}
400 <th className="hidden px-4 py-2.5 font-medium sm:table-cell">Markup</th>
Prices keep themselves current with what g1t pays401 <th className="px-4 py-2.5 font-medium">You pay</th>
402 </tr>
403 </thead>
404 <tbody className="divide-y divide-line">
405 <tr>
406 <td className="px-4 py-3">
407 <p className="font-medium">Models</p>
408 <p className="text-xs text-faint">g1t's hosted models, through AI Gateway</p>
409 </td>
410 <td className="px-4 py-3 text-muted">What the provider charges, per request</td>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look411 <td className="hidden px-4 py-3 tabular-nums sm:table-cell">{book?.modelMarginPercent ?? 20}%</td>
Prices keep themselves current with what g1t pays412 <td className="px-4 py-3 text-muted">Cost + {book?.modelMarginPercent ?? 20}%</td>
413 </tr>
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas414 <tr>
415 <td className="px-4 py-3">
416 <p className="font-medium">Projects, previews and apps</p>
417 <p className="text-xs text-faint">An app costs only the requests and CPU it answers with</p>
418 </td>
419 <td className="px-4 py-3 text-muted">Next to nothing</td>
420 <td className="hidden px-4 py-3 tabular-nums sm:table-cell">—</td>
421 <td className="px-4 py-3 text-muted">Not charged</td>
422 </tr>
423 {(book?.prices ?? []).filter((price) => price.meter !== "app_month").map((price) => (
Prices keep themselves current with what g1t pays424 <tr key={price.meter}>
425 <td className="px-4 py-3">
426 <p className="font-medium">{price.title}</p>
427 <p className="text-xs text-faint">
428 {price.source === "cloudflare" ? "Measured from Cloudflare's bill" : "Cloudflare's published price"}
429 </p>
430 </td>
431 <td className="px-4 py-3 font-mono text-xs tabular-nums text-muted">{perUnit(price, price.costMicros)}</td>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look432 <td className="hidden px-4 py-3 tabular-nums sm:table-cell">{price.markupPercent}%</td>
Prices keep themselves current with what g1t pays433 <td className="px-4 py-3 font-mono text-xs tabular-nums">{perUnit(price, price.priceMicros)}</td>
434 </tr>
435 ))}
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put436 </tbody>
437 </table>
438 </div>
439
440 <h2 className="mt-14 text-xl font-semibold tracking-tight">Enterprise</h2>
441 <p className="mt-1 text-sm text-muted">
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look442 For organizations with several workspaces: one invoice and one limit. The prices are the ones on this page.
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put443 </p>
Prices keep themselves current with what g1t pays444 <section className="mt-4 rounded-xl border border-line bg-surface p-5">
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put445 <ul className="grid gap-3 text-sm sm:grid-cols-2">
446 <li>
447 <p className="font-medium">Consolidated invoicing</p>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look448 <p className="text-muted">One monthly invoice for every workspace, paid by card or bank transfer.</p>
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put449 </li>
450 <li>
451 <p className="font-medium">Custom terms</p>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look452 <p className="text-muted">One limit across every workspace, invoice terms and a billing contact, set with you.</p>
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put453 </li>
454 <li>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look455 <p className="font-medium">Security on every plan</p>
456 <p className="text-muted">
457 The audit log for {tier.auditRetentionDays} days with export, and secret push protection, for every workspace.
458 </p>
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put459 </li>
460 <li>
461 <p className="font-medium">
462 Single sign-on <span className="ml-1 rounded bg-raised px-1.5 py-0.5 text-xs text-muted">Coming</span>
463 </p>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look464 <p className="text-muted">Through your identity provider, on every plan once it is built. Not available yet.</p>
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put465 </li>
466 </ul>
467 <a
468 href={ENTERPRISE_MAIL}
469 className="mt-5 inline-flex items-center gap-1.5 rounded-md border border-line px-3 py-1.5 text-sm hover:border-line-strong"
470 >
471 Write to us about enterprise
472 <ArrowUpRight size={14} />
473 </a>
Prices keep themselves current with what g1t pays474 </section>
475
476 <h2 className="mt-14 text-xl font-semibold tracking-tight">Price changes</h2>
477 {book && book.changes.length > 0 ? (
478 <ul className="mt-4 divide-y divide-line rounded-xl border border-line">
479 {book.changes.map((change) => {
480 const title = book.prices.find((p) => p.meter === change.meter)?.title ?? change.meter;
Prices are what g1t pays plus 20%, from the first second481 // What you pay moved: the cost, the markup, or both.
482 const before = change.oldCostMicros * (100 + (change.oldMarkupPercent ?? change.markupPercent));
483 const after = change.newCostMicros * (100 + change.markupPercent);
484 const up = after > before;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look485 const fresh = after === before || before === 0;
Prices keep themselves current with what g1t pays486 return (
487 <li key={`${change.meter}-${change.createdAt}`} className="px-4 py-3 text-sm">
488 <p>
489 <span className="font-medium">{title}</span>{" "}
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put490 {fresh ? (
491 <span className="text-muted">new</span>
492 ) : (
493 <span className={up ? "text-warn" : "text-accent"}>
494 {up ? "up" : "down"} {Math.abs((after / before - 1) * 100).toFixed(1)}%
495 </span>
496 )}
Prices keep themselves current with what g1t pays497 </p>
498 <p className="mt-0.5 text-xs text-faint">
499 {change.reason} · <TimeAgo at={change.createdAt} />
500 </p>
501 </li>
502 );
503 })}
504 </ul>
505 ) : (
Prices are what g1t pays plus 20%, from the first second506 <p className="mt-2 text-sm text-muted">None yet. When a price moves, it is listed here with why.</p>
Prices keep themselves current with what g1t pays507 )}
508
509 <a
510 href="https://docs.g1t.sh/guides/usage-and-billing/"
511 className="mt-12 inline-flex items-center gap-1.5 text-sm text-accent hover:underline"
512 >
513 How usage and billing work
514 <ArrowUpRight size={14} />
515 </a>
516 </main>
517 );
518}