@pylonsync/create-pylon 0.3.295 → 0.3.296

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pylonsync/create-pylon",
3
- "version": "0.3.295",
3
+ "version": "0.3.296",
4
4
  "description": "Scaffold a new Pylon app — realtime backend + web/mobile/expo frontends in one command. Run via `npm create @pylonsync/pylon@latest`.",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -139,7 +139,14 @@
139
139
  body {
140
140
  background-color: var(--color-background);
141
141
  color: var(--color-foreground);
142
- font-family: Inter, ui-sans-serif, system-ui, -apple-system, sans-serif;
142
+ font-family: var(
143
+ --font-sans,
144
+ Inter,
145
+ ui-sans-serif,
146
+ system-ui,
147
+ -apple-system,
148
+ sans-serif
149
+ );
143
150
  -webkit-font-smoothing: antialiased;
144
151
  }
145
152
  button {
@@ -45,12 +45,10 @@ export default function RootLayout({ children, url, auth }: LayoutProps) {
45
45
  <meta charSet="utf-8" />
46
46
  <meta name="viewport" content="width=device-width, initial-scale=1" />
47
47
  {/* No <title> here — each page's exported `metadata` sets it. */}
48
- <link rel="preconnect" href="https://fonts.googleapis.com" />
49
- <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
50
- <link
51
- rel="stylesheet"
52
- href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
53
- />
48
+ {/* Inter is declared in app.ts (fonts: [...]) and self-hosted by the
49
+ build — the runtime injects @font-face + <link rel=preload> + a
50
+ size-adjusted fallback here automatically. No third-party request,
51
+ no layout shift; change the family in app.ts. */}
54
52
  {/* Tailwind is compiled by Pylon from app/globals.css and injected here. */}
55
53
  </head>
56
54
  <body className="flex min-h-screen flex-col bg-background text-foreground antialiased">
@@ -5,6 +5,7 @@ import {
5
5
  auth,
6
6
  buildManifest,
7
7
  discoverAppRoutes,
8
+ font,
8
9
  } from "@pylonsync/sdk";
9
10
 
10
11
  // ---------------------------------------------------------------------------
@@ -276,6 +277,20 @@ const manifest = buildManifest({
276
277
  // Email/password is on by default against the User entity above. No orgs, no
277
278
  // billing — a single studio is single-tenant (one business, one owner).
278
279
  auth: auth(),
280
+ // Self-hosted Inter (next/font parity): the build fetches the woff2, serves it
281
+ // same-origin (no third-party request, no FOUT), preloads it, and synthesizes a
282
+ // size-adjusted fallback face so there's no layout shift. globals.css reads it
283
+ // via `var(--font-sans, …)`; layout.tsx carries no font <link>.
284
+ fonts: [
285
+ font({
286
+ family: "Inter",
287
+ variable: "--font-sans",
288
+ weights: ["400", "500", "600", "700"],
289
+ subsets: ["latin"],
290
+ display: "swap",
291
+ preload: true,
292
+ }),
293
+ ],
279
294
  routes: await discoverAppRoutes(),
280
295
  });
281
296
 
@@ -139,7 +139,14 @@
139
139
  body {
140
140
  background-color: var(--color-background);
141
141
  color: var(--color-foreground);
142
- font-family: Inter, ui-sans-serif, system-ui, -apple-system, sans-serif;
142
+ font-family: var(
143
+ --font-sans,
144
+ Inter,
145
+ ui-sans-serif,
146
+ system-ui,
147
+ -apple-system,
148
+ sans-serif
149
+ );
143
150
  -webkit-font-smoothing: antialiased;
144
151
  }
145
152
  button {
@@ -36,12 +36,10 @@ export default function RootLayout({ children, url, auth }: LayoutProps) {
36
36
  <head>
37
37
  <meta charSet="utf-8" />
38
38
  <meta name="viewport" content="width=device-width, initial-scale=1" />
39
- <link rel="preconnect" href="https://fonts.googleapis.com" />
40
- <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
41
- <link
42
- rel="stylesheet"
43
- href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
44
- />
39
+ {/* Inter is declared in app.ts (fonts: [...]) and self-hosted by the
40
+ build — the runtime injects @font-face + <link rel=preload> + a
41
+ size-adjusted fallback here automatically. No third-party request,
42
+ no layout shift; change the family in app.ts. */}
45
43
  </head>
46
44
  <body className="bg-background text-foreground antialiased">
47
45
  {isBare ? (
@@ -5,6 +5,7 @@ import {
5
5
  auth,
6
6
  buildManifest,
7
7
  discoverAppRoutes,
8
+ font,
8
9
  } from "@pylonsync/sdk";
9
10
 
10
11
  // ---------------------------------------------------------------------------
@@ -113,6 +114,20 @@ const manifest = buildManifest({
113
114
  actions: [],
114
115
  policies: [conversationPolicy, messagePolicy, userPolicy],
115
116
  auth: auth(),
117
+ // Self-hosted Inter (next/font parity): the build fetches the woff2, serves it
118
+ // same-origin (no third-party request, no FOUT), preloads it, and synthesizes a
119
+ // size-adjusted fallback face so there's no layout shift. globals.css reads it
120
+ // via `var(--font-sans, …)`; layout.tsx carries no font <link>.
121
+ fonts: [
122
+ font({
123
+ family: "Inter",
124
+ variable: "--font-sans",
125
+ weights: ["400", "500", "600", "700"],
126
+ subsets: ["latin"],
127
+ display: "swap",
128
+ preload: true,
129
+ }),
130
+ ],
116
131
  routes: await discoverAppRoutes(),
117
132
  });
118
133
 
@@ -139,7 +139,14 @@
139
139
  body {
140
140
  background-color: var(--color-background);
141
141
  color: var(--color-foreground);
142
- font-family: Inter, ui-sans-serif, system-ui, -apple-system, sans-serif;
142
+ font-family: var(
143
+ --font-sans,
144
+ Inter,
145
+ ui-sans-serif,
146
+ system-ui,
147
+ -apple-system,
148
+ sans-serif
149
+ );
143
150
  -webkit-font-smoothing: antialiased;
144
151
  }
145
152
  button {
@@ -36,12 +36,10 @@ export default function RootLayout({ children, url, auth }: LayoutProps) {
36
36
  <head>
37
37
  <meta charSet="utf-8" />
38
38
  <meta name="viewport" content="width=device-width, initial-scale=1" />
39
- <link rel="preconnect" href="https://fonts.googleapis.com" />
40
- <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
41
- <link
42
- rel="stylesheet"
43
- href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
44
- />
39
+ {/* Inter is declared in app.ts (fonts: [...]) and self-hosted by the
40
+ build — the runtime injects @font-face + <link rel=preload> + a
41
+ size-adjusted fallback here automatically. No third-party request,
42
+ no layout shift; change the family in app.ts. */}
45
43
  </head>
46
44
  <body className="bg-background text-foreground antialiased">
47
45
  {isBare ? (
@@ -5,6 +5,7 @@ import {
5
5
  auth,
6
6
  buildManifest,
7
7
  discoverAppRoutes,
8
+ font,
8
9
  } from "@pylonsync/sdk";
9
10
 
10
11
  // ---------------------------------------------------------------------------
@@ -100,6 +101,20 @@ const manifest = buildManifest({
100
101
  actions: [],
101
102
  policies: [generationPolicy, userPolicy],
102
103
  auth: auth(),
104
+ // Self-hosted Inter (next/font parity): the build fetches the woff2, serves it
105
+ // same-origin (no third-party request, no FOUT), preloads it, and synthesizes a
106
+ // size-adjusted fallback face so there's no layout shift. globals.css reads it
107
+ // via `var(--font-sans, …)`; layout.tsx carries no font <link>.
108
+ fonts: [
109
+ font({
110
+ family: "Inter",
111
+ variable: "--font-sans",
112
+ weights: ["400", "500", "600", "700"],
113
+ subsets: ["latin"],
114
+ display: "swap",
115
+ preload: true,
116
+ }),
117
+ ],
103
118
  routes: await discoverAppRoutes(),
104
119
  });
105
120
 
@@ -139,7 +139,14 @@
139
139
  body {
140
140
  background-color: var(--color-background);
141
141
  color: var(--color-foreground);
142
- font-family: Inter, ui-sans-serif, system-ui, -apple-system, sans-serif;
142
+ font-family: var(
143
+ --font-sans,
144
+ Inter,
145
+ ui-sans-serif,
146
+ system-ui,
147
+ -apple-system,
148
+ sans-serif
149
+ );
143
150
  -webkit-font-smoothing: antialiased;
144
151
  }
145
152
  button {
@@ -45,12 +45,10 @@ export default function RootLayout({ children, url, auth }: LayoutProps) {
45
45
  <meta charSet="utf-8" />
46
46
  <meta name="viewport" content="width=device-width, initial-scale=1" />
47
47
  {/* No <title> here — each page's exported `metadata` sets it. */}
48
- <link rel="preconnect" href="https://fonts.googleapis.com" />
49
- <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
50
- <link
51
- rel="stylesheet"
52
- href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
53
- />
48
+ {/* Inter is declared in app.ts (fonts: [...]) and self-hosted by the
49
+ build — the runtime injects @font-face + <link rel=preload> + a
50
+ size-adjusted fallback here automatically. No third-party request,
51
+ no layout shift; change the family in app.ts. */}
54
52
  {/* Tailwind is compiled by Pylon from app/globals.css and injected here. */}
55
53
  </head>
56
54
  <body className="flex min-h-screen flex-col bg-background text-foreground antialiased">
@@ -5,6 +5,7 @@ import {
5
5
  auth,
6
6
  buildManifest,
7
7
  discoverAppRoutes,
8
+ font,
8
9
  } from "@pylonsync/sdk";
9
10
 
10
11
  // ---------------------------------------------------------------------------
@@ -125,6 +126,20 @@ const manifest = buildManifest({
125
126
  // Email/password is on by default against the User entity above. No orgs,
126
127
  // no billing — a newsletter is single-tenant (one business, one owner).
127
128
  auth: auth(),
129
+ // Self-hosted Inter (next/font parity): the build fetches the woff2, serves it
130
+ // same-origin (no third-party request, no FOUT), preloads it, and synthesizes a
131
+ // size-adjusted fallback face so there's no layout shift. globals.css reads it
132
+ // via `var(--font-sans, …)`; layout.tsx carries no font <link>.
133
+ fonts: [
134
+ font({
135
+ family: "Inter",
136
+ variable: "--font-sans",
137
+ weights: ["400", "500", "600", "700"],
138
+ subsets: ["latin"],
139
+ display: "swap",
140
+ preload: true,
141
+ }),
142
+ ],
128
143
  routes: await discoverAppRoutes(),
129
144
  });
130
145
 
@@ -144,7 +144,14 @@
144
144
  body {
145
145
  background-color: var(--color-background);
146
146
  color: var(--color-foreground);
147
- font-family: Inter, ui-sans-serif, system-ui, -apple-system, sans-serif;
147
+ font-family: var(
148
+ --font-sans,
149
+ Inter,
150
+ ui-sans-serif,
151
+ system-ui,
152
+ -apple-system,
153
+ sans-serif
154
+ );
148
155
  -webkit-font-smoothing: antialiased;
149
156
  }
150
157
  button {
@@ -205,20 +205,12 @@ export default function RootLayout({ children, url, auth }: LayoutProps) {
205
205
  `generateMetadata` sets it. A hardcoded title in the layout would
206
206
  render first and win over the page's, so every tab would read
207
207
  "Acme". */}
208
- {/* Inter the marketing pages look best in a clean grotesk. Swap for
209
- your own font or drop this link to fall back to the system stack. */}
210
- <link rel="preconnect" href="https://fonts.googleapis.com" />
211
- <link
212
- rel="preconnect"
213
- href="https://fonts.gstatic.com"
214
- crossOrigin="anonymous"
215
- />
216
- <link
217
- rel="stylesheet"
218
- href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
219
- />
220
- {/* Tailwind is compiled by Pylon from app/globals.css and the
221
- stylesheet link is injected here automatically. */}
208
+ {/* Inter is declared in app.ts (`fonts: [font({ family: "Inter", })]`)
209
+ and self-hosted by the build the runtime injects the @font-face,
210
+ <link rel=preload>, and a size-adjusted fallback here automatically.
211
+ No third-party Google Fonts request, no layout shift. Swap the family
212
+ in app.ts to change it. Tailwind's compiled stylesheet is injected
213
+ here too. */}
222
214
  </head>
223
215
  <body className="flex min-h-screen flex-col bg-background text-foreground antialiased">
224
216
  {isBare ? (
@@ -5,6 +5,7 @@ import {
5
5
  auth,
6
6
  buildManifest,
7
7
  discoverAppRoutes,
8
+ font,
8
9
  } from "@pylonsync/sdk";
9
10
  // Per-workspace Stripe billing — see lib/billing.ts. `billing.manifest` brings
10
11
  // the StripeSubscription entity + checkout/portal/cancel/restore/webhook actions
@@ -186,6 +187,20 @@ const manifest = buildManifest({
186
187
  // above are named with the framework defaults (Org / OrgMember / OrgInvite),
187
188
  // so `/api/auth/orgs/*` + `/api/auth/select-org` work with no extra config.
188
189
  auth: auth(),
190
+ // Self-hosted Inter (next/font parity): the build fetches the woff2, serves it
191
+ // same-origin (no third-party request, no FOUT), preloads it, and synthesizes a
192
+ // size-adjusted fallback face so there's no layout shift. globals.css reads it
193
+ // via `var(--font-sans, …)`; layout.tsx carries no font <link>.
194
+ fonts: [
195
+ font({
196
+ family: "Inter",
197
+ variable: "--font-sans",
198
+ weights: ["400", "500", "600", "700"],
199
+ subsets: ["latin"],
200
+ display: "swap",
201
+ preload: true,
202
+ }),
203
+ ],
189
204
  routes: await discoverAppRoutes(),
190
205
  });
191
206
 
@@ -139,7 +139,14 @@
139
139
  body {
140
140
  background-color: var(--color-background);
141
141
  color: var(--color-foreground);
142
- font-family: Inter, ui-sans-serif, system-ui, -apple-system, sans-serif;
142
+ font-family: var(
143
+ --font-sans,
144
+ Inter,
145
+ ui-sans-serif,
146
+ system-ui,
147
+ -apple-system,
148
+ sans-serif
149
+ );
143
150
  -webkit-font-smoothing: antialiased;
144
151
  }
145
152
  button {
@@ -45,12 +45,10 @@ export default function RootLayout({ children, url, auth }: LayoutProps) {
45
45
  <meta charSet="utf-8" />
46
46
  <meta name="viewport" content="width=device-width, initial-scale=1" />
47
47
  {/* No <title> here — each page's exported `metadata` sets it. */}
48
- <link rel="preconnect" href="https://fonts.googleapis.com" />
49
- <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
50
- <link
51
- rel="stylesheet"
52
- href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
53
- />
48
+ {/* Inter is declared in app.ts (fonts: [...]) and self-hosted by the
49
+ build — the runtime injects @font-face + <link rel=preload> + a
50
+ size-adjusted fallback here automatically. No third-party request,
51
+ no layout shift; change the family in app.ts. */}
54
52
  {/* Tailwind is compiled by Pylon from app/globals.css and injected here. */}
55
53
  </head>
56
54
  <body className="flex min-h-screen flex-col bg-background text-foreground antialiased">
@@ -5,6 +5,7 @@ import {
5
5
  auth,
6
6
  buildManifest,
7
7
  discoverAppRoutes,
8
+ font,
8
9
  } from "@pylonsync/sdk";
9
10
 
10
11
  // ---------------------------------------------------------------------------
@@ -138,6 +139,20 @@ const manifest = buildManifest({
138
139
  actions: [],
139
140
  policies: [listingPolicy, submissionPolicy, userPolicy],
140
141
  auth: auth(),
142
+ // Self-hosted Inter (next/font parity): the build fetches the woff2, serves it
143
+ // same-origin (no third-party request, no FOUT), preloads it, and synthesizes a
144
+ // size-adjusted fallback face so there's no layout shift. globals.css reads it
145
+ // via `var(--font-sans, …)`; layout.tsx carries no font <link>.
146
+ fonts: [
147
+ font({
148
+ family: "Inter",
149
+ variable: "--font-sans",
150
+ weights: ["400", "500", "600", "700"],
151
+ subsets: ["latin"],
152
+ display: "swap",
153
+ preload: true,
154
+ }),
155
+ ],
141
156
  routes: await discoverAppRoutes(),
142
157
  });
143
158
 
@@ -139,7 +139,14 @@
139
139
  body {
140
140
  background-color: var(--color-background);
141
141
  color: var(--color-foreground);
142
- font-family: Inter, ui-sans-serif, system-ui, -apple-system, sans-serif;
142
+ font-family: var(
143
+ --font-sans,
144
+ Inter,
145
+ ui-sans-serif,
146
+ system-ui,
147
+ -apple-system,
148
+ sans-serif
149
+ );
143
150
  -webkit-font-smoothing: antialiased;
144
151
  }
145
152
  button {
@@ -39,12 +39,10 @@ export default function RootLayout({ children, url, auth }: LayoutProps) {
39
39
  <head>
40
40
  <meta charSet="utf-8" />
41
41
  <meta name="viewport" content="width=device-width, initial-scale=1" />
42
- <link rel="preconnect" href="https://fonts.googleapis.com" />
43
- <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
44
- <link
45
- rel="stylesheet"
46
- href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
47
- />
42
+ {/* Inter is declared in app.ts (fonts: [...]) and self-hosted by the
43
+ build — the runtime injects @font-face + <link rel=preload> + a
44
+ size-adjusted fallback here automatically. No third-party request,
45
+ no layout shift; change the family in app.ts. */}
48
46
  </head>
49
47
  <body className="flex min-h-screen flex-col bg-background text-foreground antialiased">
50
48
  <SectionScroller />
@@ -5,6 +5,7 @@ import {
5
5
  auth,
6
6
  buildManifest,
7
7
  discoverAppRoutes,
8
+ font,
8
9
  } from "@pylonsync/sdk";
9
10
 
10
11
  // ---------------------------------------------------------------------------
@@ -123,6 +124,20 @@ const manifest = buildManifest({
123
124
  actions: [],
124
125
  policies: [bookingPolicy, bookedSlotPolicy, userPolicy],
125
126
  auth: auth(),
127
+ // Self-hosted Inter (next/font parity): the build fetches the woff2, serves it
128
+ // same-origin (no third-party request, no FOUT), preloads it, and synthesizes a
129
+ // size-adjusted fallback face so there's no layout shift. globals.css reads it
130
+ // via `var(--font-sans, …)`; layout.tsx carries no font <link>.
131
+ fonts: [
132
+ font({
133
+ family: "Inter",
134
+ variable: "--font-sans",
135
+ weights: ["400", "500", "600", "700"],
136
+ subsets: ["latin"],
137
+ display: "swap",
138
+ preload: true,
139
+ }),
140
+ ],
126
141
  routes: await discoverAppRoutes(),
127
142
  });
128
143
 
@@ -139,7 +139,14 @@
139
139
  body {
140
140
  background-color: var(--color-background);
141
141
  color: var(--color-foreground);
142
- font-family: Inter, ui-sans-serif, system-ui, -apple-system, sans-serif;
142
+ font-family: var(
143
+ --font-sans,
144
+ Inter,
145
+ ui-sans-serif,
146
+ system-ui,
147
+ -apple-system,
148
+ sans-serif
149
+ );
143
150
  -webkit-font-smoothing: antialiased;
144
151
  }
145
152
  button {
@@ -39,12 +39,10 @@ export default function RootLayout({ children, url, auth }: LayoutProps) {
39
39
  <head>
40
40
  <meta charSet="utf-8" />
41
41
  <meta name="viewport" content="width=device-width, initial-scale=1" />
42
- <link rel="preconnect" href="https://fonts.googleapis.com" />
43
- <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
44
- <link
45
- rel="stylesheet"
46
- href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
47
- />
42
+ {/* Inter is declared in app.ts (fonts: [...]) and self-hosted by the
43
+ build — the runtime injects @font-face + <link rel=preload> + a
44
+ size-adjusted fallback here automatically. No third-party request,
45
+ no layout shift; change the family in app.ts. */}
48
46
  </head>
49
47
  <body className="flex min-h-screen flex-col bg-background text-foreground antialiased">
50
48
  <SectionScroller />
@@ -5,6 +5,7 @@ import {
5
5
  auth,
6
6
  buildManifest,
7
7
  discoverAppRoutes,
8
+ font,
8
9
  } from "@pylonsync/sdk";
9
10
 
10
11
  // ---------------------------------------------------------------------------
@@ -107,6 +108,20 @@ const manifest = buildManifest({
107
108
  actions: [],
108
109
  policies: [reservationPolicy, reservationSlotPolicy, userPolicy],
109
110
  auth: auth(),
111
+ // Self-hosted Inter (next/font parity): the build fetches the woff2, serves it
112
+ // same-origin (no third-party request, no FOUT), preloads it, and synthesizes a
113
+ // size-adjusted fallback face so there's no layout shift. globals.css reads it
114
+ // via `var(--font-sans, …)`; layout.tsx carries no font <link>.
115
+ fonts: [
116
+ font({
117
+ family: "Inter",
118
+ variable: "--font-sans",
119
+ weights: ["400", "500", "600", "700"],
120
+ subsets: ["latin"],
121
+ display: "swap",
122
+ preload: true,
123
+ }),
124
+ ],
110
125
  routes: await discoverAppRoutes(),
111
126
  });
112
127
 
@@ -139,7 +139,14 @@
139
139
  body {
140
140
  background-color: var(--color-background);
141
141
  color: var(--color-foreground);
142
- font-family: Inter, ui-sans-serif, system-ui, -apple-system, sans-serif;
142
+ font-family: var(
143
+ --font-sans,
144
+ Inter,
145
+ ui-sans-serif,
146
+ system-ui,
147
+ -apple-system,
148
+ sans-serif
149
+ );
143
150
  -webkit-font-smoothing: antialiased;
144
151
  }
145
152
  button {
@@ -45,12 +45,10 @@ export default function RootLayout({ children, url, auth }: LayoutProps) {
45
45
  <meta charSet="utf-8" />
46
46
  <meta name="viewport" content="width=device-width, initial-scale=1" />
47
47
  {/* No <title> here — each page's exported `metadata` sets it. */}
48
- <link rel="preconnect" href="https://fonts.googleapis.com" />
49
- <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
50
- <link
51
- rel="stylesheet"
52
- href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
53
- />
48
+ {/* Inter is declared in app.ts (fonts: [...]) and self-hosted by the
49
+ build — the runtime injects @font-face + <link rel=preload> + a
50
+ size-adjusted fallback here automatically. No third-party request,
51
+ no layout shift; change the family in app.ts. */}
54
52
  {/* Tailwind is compiled by Pylon from app/globals.css and injected here. */}
55
53
  </head>
56
54
  <body className="flex min-h-screen flex-col bg-background text-foreground antialiased">
@@ -5,6 +5,7 @@ import {
5
5
  auth,
6
6
  buildManifest,
7
7
  discoverAppRoutes,
8
+ font,
8
9
  } from "@pylonsync/sdk";
9
10
 
10
11
  // ---------------------------------------------------------------------------
@@ -126,6 +127,20 @@ const manifest = buildManifest({
126
127
  actions: [],
127
128
  policies: [productPolicy, orderPolicy, userPolicy],
128
129
  auth: auth(),
130
+ // Self-hosted Inter (next/font parity): the build fetches the woff2, serves it
131
+ // same-origin (no third-party request, no FOUT), preloads it, and synthesizes a
132
+ // size-adjusted fallback face so there's no layout shift. globals.css reads it
133
+ // via `var(--font-sans, …)`; layout.tsx carries no font <link>.
134
+ fonts: [
135
+ font({
136
+ family: "Inter",
137
+ variable: "--font-sans",
138
+ weights: ["400", "500", "600", "700"],
139
+ subsets: ["latin"],
140
+ display: "swap",
141
+ preload: true,
142
+ }),
143
+ ],
129
144
  routes: await discoverAppRoutes(),
130
145
  });
131
146
 
@@ -139,7 +139,14 @@
139
139
  body {
140
140
  background-color: var(--color-background);
141
141
  color: var(--color-foreground);
142
- font-family: Inter, ui-sans-serif, system-ui, -apple-system, sans-serif;
142
+ font-family: var(
143
+ --font-sans,
144
+ Inter,
145
+ ui-sans-serif,
146
+ system-ui,
147
+ -apple-system,
148
+ sans-serif
149
+ );
143
150
  -webkit-font-smoothing: antialiased;
144
151
  }
145
152
  button {
@@ -44,12 +44,10 @@ export default function RootLayout({ children, url, auth }: LayoutProps) {
44
44
  <meta charSet="utf-8" />
45
45
  <meta name="viewport" content="width=device-width, initial-scale=1" />
46
46
  {/* No <title> here — each page's exported `metadata` sets it. */}
47
- <link rel="preconnect" href="https://fonts.googleapis.com" />
48
- <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
49
- <link
50
- rel="stylesheet"
51
- href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
52
- />
47
+ {/* Inter is declared in app.ts (fonts: [...]) and self-hosted by the
48
+ build — the runtime injects @font-face + <link rel=preload> + a
49
+ size-adjusted fallback here automatically. No third-party request,
50
+ no layout shift; change the family in app.ts. */}
53
51
  {/* Tailwind is compiled by Pylon from app/globals.css and injected here. */}
54
52
  </head>
55
53
  <body className="flex min-h-screen flex-col bg-background text-foreground antialiased">
@@ -5,6 +5,7 @@ import {
5
5
  auth,
6
6
  buildManifest,
7
7
  discoverAppRoutes,
8
+ font,
8
9
  } from "@pylonsync/sdk";
9
10
 
10
11
  // ---------------------------------------------------------------------------
@@ -125,6 +126,20 @@ const manifest = buildManifest({
125
126
  // Email/password is on by default against the User entity above. No orgs,
126
127
  // no billing — a waitlist is single-tenant (one business, one owner).
127
128
  auth: auth(),
129
+ // Self-hosted Inter (next/font parity): the build fetches the woff2, serves it
130
+ // same-origin (no third-party request, no FOUT), preloads it, and synthesizes a
131
+ // size-adjusted fallback face so there's no layout shift. globals.css reads it
132
+ // via `var(--font-sans, …)`; layout.tsx carries no font <link>.
133
+ fonts: [
134
+ font({
135
+ family: "Inter",
136
+ variable: "--font-sans",
137
+ weights: ["400", "500", "600", "700"],
138
+ subsets: ["latin"],
139
+ display: "swap",
140
+ preload: true,
141
+ }),
142
+ ],
128
143
  routes: await discoverAppRoutes(),
129
144
  });
130
145