Skip to content

Commit bb9c3ae

Browse files
committed
fix(web): responsive layout for landing, signin, and dashboard
Replaced fixed px-[80px] / py-[64px] padding with px-5 md:px-[80px] so content stops colliding with the viewport edge on phones. The hero H1 shrinks to 28px / 34px leading on mobile, the stats grid collapses to one column, the sticky header shrinks to 64px with tighter nav spacing and a shorter CTA, the self-host banner centers on a narrow screen, and the footer stacks vertically. Same pass applied to /signin and the dashboard shell so the whole app is usable on mobile, not just the marketing page.
1 parent 2cfde9c commit bb9c3ae

3 files changed

Lines changed: 56 additions & 25 deletions

File tree

apps/web/src/app/app/layout.tsx

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,12 @@ export default function DashboardLayout({
5757
return (
5858
<main>
5959
<div
60-
className="mx-auto border-l border-r min-h-screen px-[80px] py-[64px]"
60+
className="mx-auto border-l border-r min-h-screen px-5 md:px-[80px] py-10 md:py-[64px]"
6161
style={{ maxWidth: '1080px', borderColor: '#3d3838' }}
6262
>
63-
<h1 className="text-[38px] font-bold leading-[57px] mb-4">API unreachable</h1>
63+
<h1 className="text-[28px] md:text-[38px] font-bold leading-[36px] md:leading-[57px] mb-4">
64+
API unreachable
65+
</h1>
6466
<div
6567
className="mb-6 rounded border px-3 py-2 text-sm leading-[20px] flex items-start gap-2"
6668
style={{
@@ -126,22 +128,28 @@ export default function DashboardLayout({
126128
style={{ maxWidth: '1080px', borderColor: '#3d3838' }}
127129
>
128130
<header
129-
className="sticky top-0 z-10 flex items-center justify-between min-h-[80px] px-[80px] border-b"
131+
className="sticky top-0 z-10 flex items-center justify-between gap-3 min-h-[64px] md:min-h-[80px] px-4 md:px-[80px] border-b"
130132
style={{ backgroundColor: '#131010', borderColor: '#3d3838' }}
131133
>
132134
<Link href="/app" style={{ color: '#f2eded', fontWeight: 700 }}>
133135
<span style={{ color: '#22c55e' }}>[</span>sheetforge
134136
<span style={{ color: '#22c55e' }}>]</span>{' '}
135137
<span style={{ color: '#7f7a7a' }}>dashboard</span>
136138
</Link>
137-
<nav className="flex items-center gap-8 text-sm">
138-
<Link href="/app" className="transition-colors" style={{ color: '#b8b2b2' }}>
139+
<nav className="flex items-center gap-3 md:gap-8 text-xs md:text-sm">
140+
<Link
141+
href="/app"
142+
className="hidden sm:inline transition-colors"
143+
style={{ color: '#b8b2b2' }}
144+
>
139145
Projects
140146
</Link>
141147
<Link href="/" className="transition-colors" style={{ color: '#b8b2b2' }}>
142148
← Home
143149
</Link>
144-
<span style={{ color: '#7f7a7a' }}>{user.email}</span>
150+
<span className="hidden md:inline truncate max-w-[160px]" style={{ color: '#7f7a7a' }}>
151+
{user.email}
152+
</span>
145153
<button
146154
type="button"
147155
onClick={async () => {
@@ -160,7 +168,7 @@ export default function DashboardLayout({
160168
</button>
161169
</nav>
162170
</header>
163-
<div className="px-[80px] py-[48px]">{children}</div>
171+
<div className="px-5 md:px-[80px] py-8 md:py-[48px]">{children}</div>
164172
</div>
165173
<ToastHost />
166174
<ConfirmHost />

apps/web/src/app/page.tsx

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,13 @@ const faqItems = [
104104
function Header() {
105105
return (
106106
<header
107-
className="sticky top-0 z-10 flex items-center justify-between min-h-[80px] px-[80px] border-b"
107+
className="sticky top-0 z-10 flex items-center justify-between min-h-[64px] md:min-h-[80px] px-4 md:px-[80px] border-b"
108108
style={{ backgroundColor: '#131010' }}
109109
>
110110
<a href="/" aria-label="sheetforge home">
111111
<OpenCodeLogo />
112112
</a>
113-
<nav className="flex items-center gap-8">
113+
<nav className="flex items-center gap-3 md:gap-8 text-sm md:text-base">
114114
<a
115115
href="https://github.com/Devansh-365/sheetforge"
116116
className="text-[#b8b2b2] hover:text-[#f2eded] transition-colors"
@@ -119,17 +119,21 @@ function Header() {
119119
>
120120
GitHub <span className="text-[#22c55e]">[★]</span>
121121
</a>
122-
<a href="#faq" className="text-[#b8b2b2] hover:text-[#f2eded] transition-colors">
122+
<a
123+
href="#faq"
124+
className="hidden sm:inline text-[#b8b2b2] hover:text-[#f2eded] transition-colors"
125+
>
123126
FAQ
124127
</a>
125128
<a
126129
href="https://github.com/Devansh-365/sheetforge#quickstart"
127130
target="_blank"
128131
rel="noopener noreferrer"
129-
className="rounded px-4 py-2 font-medium transition-opacity hover:opacity-90 cursor-pointer"
132+
className="rounded px-3 md:px-4 py-1.5 md:py-2 font-medium transition-opacity hover:opacity-90 cursor-pointer whitespace-nowrap"
130133
style={{ backgroundColor: '#22c55e', color: '#0c0c0e' }}
131134
>
132-
Self-host it →
135+
<span className="hidden sm:inline">Self-host it →</span>
136+
<span className="sm:hidden">Self-host →</span>
133137
</a>
134138
</nav>
135139
</header>
@@ -139,7 +143,7 @@ function Header() {
139143
function SelfHostBanner() {
140144
return (
141145
<div
142-
className="px-[80px] py-3 border-b flex items-center justify-center gap-2 text-sm"
146+
className="px-4 md:px-[80px] py-3 border-b flex items-start md:items-center justify-center gap-2 text-[13px] md:text-sm text-center md:text-left"
143147
style={{
144148
backgroundColor: '#0f1a12',
145149
borderColor: '#14532d',
@@ -177,7 +181,10 @@ function HeroSection() {
177181
};
178182

179183
return (
180-
<section className="px-[80px] py-[64px] border-b" style={{ borderColor: '#3d3838' }}>
184+
<section
185+
className="px-5 md:px-[80px] py-10 md:py-[64px] border-b"
186+
style={{ borderColor: '#3d3838' }}
187+
>
181188
<div className="flex items-center gap-3 mb-8">
182189
<span
183190
className="border px-2 py-0.5 text-sm font-medium"
@@ -199,7 +206,7 @@ function HeroSection() {
199206
</p>
200207
</div>
201208

202-
<h1 className="text-[38px] font-bold leading-[57px] text-[#f2eded] mb-4">
209+
<h1 className="text-[28px] md:text-[38px] font-bold leading-[34px] md:leading-[57px] text-[#f2eded] mb-4">
203210
The Google Sheets backend that behaves like a real database
204211
</h1>
205212
<p className="text-[#b8b2b2] mb-8 leading-[24px]">
@@ -283,7 +290,10 @@ function HeroSection() {
283290

284291
function FeaturesSection() {
285292
return (
286-
<section className="px-[80px] py-[64px] border-b" style={{ borderColor: '#3d3838' }}>
293+
<section
294+
className="px-5 md:px-[80px] py-10 md:py-[64px] border-b"
295+
style={{ borderColor: '#3d3838' }}
296+
>
287297
<h2 className="text-[16px] font-bold text-[#f2eded] mb-3">What is sheetforge?</h2>
288298
<p className="text-[#b8b2b2] mb-8 leading-[24px]">
289299
A race-condition-safe REST API layer for Google Sheets with auto-generated TypeScript and
@@ -306,14 +316,17 @@ function FeaturesSection() {
306316

307317
function StatsSection() {
308318
return (
309-
<section className="px-[80px] py-[64px] border-b" style={{ borderColor: '#3d3838' }}>
319+
<section
320+
className="px-5 md:px-[80px] py-10 md:py-[64px] border-b"
321+
style={{ borderColor: '#3d3838' }}
322+
>
310323
<h2 className="text-[16px] font-bold text-[#f2eded] mb-3">Built on numbers that matter</h2>
311324
<p className="text-[#b8b2b2] leading-[32px] mb-8">
312325
<span style={{ color: '#22c55e' }}>[*]</span> The write queue handles 1000 concurrent POSTs
313326
to the same sheet and produces exactly 1000 rows, in order — zero race conditions, sub-100ms
314327
cached reads globally.
315328
</p>
316-
<div className="grid grid-cols-3 gap-6">
329+
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4 sm:gap-6">
317330
<div className="border rounded p-6 flex flex-col gap-3" style={{ borderColor: '#3d3838' }}>
318331
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" aria-hidden="true">
319332
<title>Parallel writes converging into an ordered stream</title>
@@ -396,7 +409,10 @@ function StatsSection() {
396409

397410
function PrivacySection() {
398411
return (
399-
<section className="px-[80px] py-[64px] border-b" style={{ borderColor: '#3d3838' }}>
412+
<section
413+
className="px-5 md:px-[80px] py-10 md:py-[64px] border-b"
414+
style={{ borderColor: '#3d3838' }}
415+
>
400416
<h2 className="text-[16px] font-bold text-[#f2eded] mb-3">
401417
Your data never leaves your infrastructure
402418
</h2>
@@ -413,7 +429,11 @@ function FAQSection() {
413429
const [openIndex, setOpenIndex] = useState<number | null>(0);
414430

415431
return (
416-
<section id="faq" className="px-[80px] py-[64px] border-b" style={{ borderColor: '#3d3838' }}>
432+
<section
433+
id="faq"
434+
className="px-5 md:px-[80px] py-10 md:py-[64px] border-b"
435+
style={{ borderColor: '#3d3838' }}
436+
>
417437
<h2 className="text-[16px] font-bold text-[#f2eded] mb-8">FAQ</h2>
418438
<div className="space-y-0">
419439
{faqItems.map((item, i) => (
@@ -439,7 +459,10 @@ function FAQSection() {
439459

440460
function ZenSection() {
441461
return (
442-
<section className="px-[80px] py-[64px] border-b" style={{ borderColor: '#3d3838' }}>
462+
<section
463+
className="px-5 md:px-[80px] py-10 md:py-[64px] border-b"
464+
style={{ borderColor: '#3d3838' }}
465+
>
443466
<h2 className="text-[16px] font-bold text-[#f2eded] mb-3">
444467
Self-host today. Hosted SaaS on the way.
445468
</h2>
@@ -470,9 +493,9 @@ function ZenSection() {
470493

471494
function Footer() {
472495
return (
473-
<footer className="px-[80px] py-4 flex items-center justify-between text-sm text-[#4a4545]">
496+
<footer className="px-5 md:px-[80px] py-4 flex flex-col sm:flex-row gap-2 sm:gap-0 items-start sm:items-center justify-between text-sm text-[#4a4545]">
474497
<span>&copy;2026 sheetforge · MIT OSS · self-hosted</span>
475-
<div className="flex items-center gap-6">
498+
<div className="flex items-center gap-4 md:gap-6">
476499
<a href="#faq" className="hover:text-[#4ade80] transition-colors">
477500
FAQ
478501
</a>

apps/web/src/app/signin/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export default function SignInPage() {
4545
>
4646
{/* Header */}
4747
<header
48-
className="flex items-center justify-between min-h-[80px] px-[80px] border-b"
48+
className="flex items-center justify-between min-h-[64px] md:min-h-[80px] px-4 md:px-[80px] border-b"
4949
style={{ backgroundColor: '#131010', borderColor: '#3d3838' }}
5050
>
5151
<Link href="/" aria-label="sheetforge home">
@@ -57,7 +57,7 @@ export default function SignInPage() {
5757
</header>
5858

5959
{/* Card */}
60-
<div className="flex-1 flex items-center justify-center px-[80px] py-[64px]">
60+
<div className="flex-1 flex items-center justify-center px-5 md:px-[80px] py-10 md:py-[64px]">
6161
<div className="w-full max-w-md">
6262
<div
6363
className="border rounded p-8"

0 commit comments

Comments
 (0)