Skip to content

Commit 7fbcadb

Browse files
committed
Improve website mobile layout and SEO
1 parent bda113c commit 7fbcadb

17 files changed

Lines changed: 588 additions & 312 deletions

website/lib/main.dart

Lines changed: 47 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -33,25 +33,25 @@ class _PatternsWebsiteState extends State<PatternsWebsite> {
3333
initialRoute: '/',
3434
routes: {
3535
'/': (context) => _HomePage(
36-
isDark: _themeMode == ThemeMode.dark,
37-
onThemeToggle: () {
38-
setState(() {
39-
_themeMode = _themeMode == ThemeMode.dark
40-
? ThemeMode.light
41-
: ThemeMode.dark;
42-
});
43-
},
44-
),
36+
isDark: _themeMode == ThemeMode.dark,
37+
onThemeToggle: () {
38+
setState(() {
39+
_themeMode = _themeMode == ThemeMode.dark
40+
? ThemeMode.light
41+
: ThemeMode.dark;
42+
});
43+
},
44+
),
4545
'/privacy': (context) => PrivacyPage(
46-
isDark: _themeMode == ThemeMode.dark,
47-
onThemeToggle: () {
48-
setState(() {
49-
_themeMode = _themeMode == ThemeMode.dark
50-
? ThemeMode.light
51-
: ThemeMode.dark;
52-
});
53-
},
54-
),
46+
isDark: _themeMode == ThemeMode.dark,
47+
onThemeToggle: () {
48+
setState(() {
49+
_themeMode = _themeMode == ThemeMode.dark
50+
? ThemeMode.light
51+
: ThemeMode.dark;
52+
});
53+
},
54+
),
5555
},
5656
);
5757
}
@@ -76,11 +76,11 @@ class _HomePageState extends State<_HomePage> {
7676
final _downloadKey = GlobalKey();
7777

7878
Map<String, GlobalKey> get _sectionKeys => {
79-
'hero': _heroKey,
80-
'features': _featuresKey,
81-
'preview': _previewKey,
82-
'download': _downloadKey,
83-
};
79+
'hero': _heroKey,
80+
'features': _featuresKey,
81+
'preview': _previewKey,
82+
'download': _downloadKey,
83+
};
8484

8585
void _scrollToDownload() {
8686
final ctx = _downloadKey.currentContext;
@@ -108,27 +108,31 @@ class _HomePageState extends State<_HomePage> {
108108
SingleChildScrollView(
109109
controller: _scrollController,
110110
child: Column(
111-
children: [
112-
const SizedBox(height: 68),
113-
Container(
114-
key: _heroKey,
115-
child: HeroSection(
116-
isDark: widget.isDark,
117-
onDownloadTap: _scrollToDownload,
118-
)),
119-
Container(
120-
key: _featuresKey,
121-
child: FeaturesSection(isDark: widget.isDark)),
122-
Container(
123-
key: _previewKey,
124-
child: PreviewSection(isDark: widget.isDark)),
125-
Container(
126-
key: _downloadKey,
127-
child: DownloadSection(isDark: widget.isDark)),
128-
FooterSection(isDark: widget.isDark),
129-
],
130-
),
111+
children: [
112+
const SizedBox(height: 68),
113+
Container(
114+
key: _heroKey,
115+
child: HeroSection(
116+
isDark: widget.isDark,
117+
onDownloadTap: _scrollToDownload,
118+
),
119+
),
120+
Container(
121+
key: _featuresKey,
122+
child: FeaturesSection(isDark: widget.isDark),
123+
),
124+
Container(
125+
key: _previewKey,
126+
child: PreviewSection(isDark: widget.isDark),
127+
),
128+
Container(
129+
key: _downloadKey,
130+
child: DownloadSection(isDark: widget.isDark),
131+
),
132+
FooterSection(isDark: widget.isDark),
133+
],
131134
),
135+
),
132136
// Fixed navbar
133137
Positioned(
134138
top: 0,

website/lib/screens/privacy_page.dart

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ class _PrivacyPageState extends State<PrivacyPage> {
2121
@override
2222
Widget build(BuildContext context) {
2323
return Scaffold(
24-
backgroundColor: widget.isDark ? WebTheme.darkSurface : WebTheme.lightSurface,
24+
backgroundColor: widget.isDark
25+
? WebTheme.darkSurface
26+
: WebTheme.lightSurface,
2527
body: Stack(
2628
children: [
2729
SingleChildScrollView(
@@ -33,11 +35,14 @@ class _PrivacyPageState extends State<PrivacyPage> {
3335
Padding(
3436
padding: const EdgeInsets.symmetric(vertical: 40),
3537
child: TextButton(
36-
onPressed: () => Navigator.of(context).pushReplacementNamed('/'),
38+
onPressed: () =>
39+
Navigator.of(context).pushReplacementNamed('/'),
3740
child: Text(
3841
'← Back to Home',
3942
style: TextStyle(
40-
color: widget.isDark ? WebTheme.primaryYellow : WebTheme.primaryGold,
43+
color: widget.isDark
44+
? WebTheme.primaryYellow
45+
: WebTheme.primaryGold,
4146
),
4247
),
4348
),

website/lib/sections/download_section.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,13 @@ class _DownloadSectionState extends State<DownloadSection> {
102102
fontSize: isMobile ? 32 : 48,
103103
fontWeight: FontWeight.w800,
104104
height: 1.1,
105-
letterSpacing: -1.5,
105+
letterSpacing: 0,
106106
color: textColor,
107107
),
108108
),
109109
const SizedBox(height: 16),
110-
SizedBox(
111-
width: 480,
110+
ConstrainedBox(
111+
constraints: const BoxConstraints(maxWidth: 480),
112112
child: Text(
113113
'Download Patterns for free and take the first step toward understanding your mind better.',
114114
textAlign: TextAlign.center,
@@ -295,6 +295,7 @@ class _DownloadCardState extends State<_DownloadCard> {
295295
onTap: widget.onDownload,
296296
child: AnimatedContainer(
297297
duration: const Duration(milliseconds: 250),
298+
width: double.infinity,
298299
constraints: const BoxConstraints(maxWidth: 400),
299300
padding: const EdgeInsets.all(32),
300301
decoration: BoxDecoration(

website/lib/sections/features_section.dart

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ class FeaturesSection extends StatelessWidget {
1414
final screen = Responsive.getScreenSize(context);
1515
final isMobile = screen == ScreenSize.mobile;
1616
final textColor = isDark ? WebTheme.darkText : WebTheme.lightText;
17-
final secondaryText =
18-
isDark ? WebTheme.darkTextSecondary : WebTheme.lightTextSecondary;
17+
final secondaryText = isDark
18+
? WebTheme.darkTextSecondary
19+
: WebTheme.lightTextSecondary;
1920
final accent = isDark ? WebTheme.primaryYellow : WebTheme.primaryGold;
2021

2122
final features = [
@@ -68,12 +69,13 @@ class FeaturesSection extends StatelessWidget {
6869
child: Column(
6970
children: [
7071
Container(
71-
padding:
72-
const EdgeInsets.symmetric(horizontal: 14, vertical: 6),
72+
padding: const EdgeInsets.symmetric(
73+
horizontal: 14,
74+
vertical: 6,
75+
),
7376
decoration: BoxDecoration(
7477
borderRadius: BorderRadius.circular(100),
75-
border:
76-
Border.all(color: accent.withValues(alpha: 0.25)),
78+
border: Border.all(color: accent.withValues(alpha: 0.25)),
7779
),
7880
child: Text(
7981
'FEATURES',
@@ -93,13 +95,13 @@ class FeaturesSection extends StatelessWidget {
9395
fontSize: isMobile ? 32 : 48,
9496
fontWeight: FontWeight.w800,
9597
height: 1.1,
96-
letterSpacing: -1.5,
98+
letterSpacing: 0,
9799
color: textColor,
98100
),
99101
),
100102
const SizedBox(height: 16),
101-
SizedBox(
102-
width: 480,
103+
ConstrainedBox(
104+
constraints: const BoxConstraints(maxWidth: 480),
103105
child: Text(
104106
'Designed to be simple, focused, and respectful of your privacy.',
105107
textAlign: TextAlign.center,
@@ -120,8 +122,8 @@ class FeaturesSection extends StatelessWidget {
120122
final crossAxisCount = isMobile
121123
? 1
122124
: screen == ScreenSize.tablet
123-
? 2
124-
: 3;
125+
? 2
126+
: 3;
125127
return Wrap(
126128
spacing: 24,
127129
runSpacing: 24,
@@ -131,7 +133,7 @@ class FeaturesSection extends StatelessWidget {
131133
final itemWidth = crossAxisCount == 1
132134
? constraints.maxWidth
133135
: (constraints.maxWidth - (crossAxisCount - 1) * 24) /
134-
crossAxisCount;
136+
crossAxisCount;
135137
return AnimatedOnScroll(
136138
delay: Duration(milliseconds: idx * 100),
137139
child: SizedBox(
@@ -193,8 +195,9 @@ class _FeatureCardState extends State<_FeatureCard> {
193195
@override
194196
Widget build(BuildContext context) {
195197
final border = widget.isDark ? WebTheme.darkBorder : WebTheme.lightBorder;
196-
final surfaceAlt =
197-
widget.isDark ? WebTheme.darkSurfaceAlt : WebTheme.lightSurfaceAlt;
198+
final surfaceAlt = widget.isDark
199+
? WebTheme.darkSurfaceAlt
200+
: WebTheme.lightSurfaceAlt;
198201

199202
return MouseRegion(
200203
onEnter: (_) => setState(() => _hovered = true),
@@ -221,11 +224,7 @@ class _FeatureCardState extends State<_FeatureCard> {
221224
color: widget.accent.withValues(alpha: 0.1),
222225
borderRadius: BorderRadius.circular(12),
223226
),
224-
child: Icon(
225-
widget.feature.icon,
226-
size: 24,
227-
color: widget.accent,
228-
),
227+
child: Icon(widget.feature.icon, size: 24, color: widget.accent),
229228
),
230229
const SizedBox(height: 20),
231230
Text(

0 commit comments

Comments
 (0)