Spaces:
Sleeping
Sleeping
Upload 210 files
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .gitattributes +15 -0
- .gitignore +10 -0
- README.md +1 -20
- about/LICENSE +201 -0
- about/README.md +2 -0
- about/app.py +77 -0
- about/components.py +53 -0
- about/favicon.ico +0 -0
- about/foundations.py +81 -0
- about/main.py +19 -0
- about/overview.py +60 -0
- about/requirements.txt +2 -0
- about/tech.py +88 -0
- about/vision.py +34 -0
- app.css +5 -0
- assets/accordion-minus-icon.svg +4 -0
- assets/accordion-plus-icon.svg +4 -0
- assets/chat-bot.svg +5 -0
- assets/fonts/geist-mono/GeistMonoVF.woff +0 -0
- assets/fonts/geist-mono/GeistMonoVF.woff2 +0 -0
- assets/fonts/geist/Geist-Medium.woff +0 -0
- assets/fonts/geist/Geist-Medium.woff2 +0 -0
- assets/fonts/geist/GeistVF.woff +0 -0
- assets/fonts/geist/GeistVF.woff2 +0 -0
- assets/footer-path.svg +17 -0
- assets/footer-shapes.svg +117 -0
- assets/game-of-life.svg +43 -0
- assets/github-mark/github-mark-white.png +0 -0
- assets/github-mark/github-mark-white.svg +1 -0
- assets/github-mark/github-mark.png +0 -0
- assets/github-mark/github-mark.svg +1 -0
- assets/hello.png +0 -0
- assets/hero-shapes.svg +118 -0
- assets/htmx-meme.png +3 -0
- assets/icons/arrow-left.svg +5 -0
- assets/icons/arrow-right.svg +5 -0
- assets/icons/arrow-up-right-white.svg +3 -0
- assets/icons/arrow-up-right.svg +3 -0
- assets/icons/copy-icon.svg +3 -0
- assets/icons/dot.svg +3 -0
- assets/icons/minus-icon.svg +5 -0
- assets/icons/plus-icon.svg +5 -0
- assets/icons/stack/asgi_logo-color.svg +1 -0
- assets/icons/stack/html-1.svg +1 -0
- assets/icons/stack/html.svg +7 -0
- assets/icons/stack/htmx.svg +15 -0
- assets/icons/stack/http-domain-svgrepo-com.svg +28 -0
- assets/icons/stack/hugging-face.svg +11 -0
- assets/icons/stack/python-anywhere.svg +21 -0
- assets/icons/stack/python.svg +14 -0
.gitattributes
CHANGED
@@ -33,3 +33,18 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
+
assets/htmx-meme.png filter=lfs diff=lfs merge=lfs -text
|
37 |
+
assets/og-image.png filter=lfs diff=lfs merge=lfs -text
|
38 |
+
assets/og-sq.png filter=lfs diff=lfs merge=lfs -text
|
39 |
+
assets/thumb.png filter=lfs diff=lfs merge=lfs -text
|
40 |
+
assets/webdev.jpg filter=lfs diff=lfs merge=lfs -text
|
41 |
+
docs/explains/CreateWebhook.png filter=lfs diff=lfs merge=lfs -text
|
42 |
+
docs/explains/CreateWebhook2.png filter=lfs diff=lfs merge=lfs -text
|
43 |
+
docs/explains/imgs/gh-oauth.png filter=lfs diff=lfs merge=lfs -text
|
44 |
+
docs/explains/refund.png filter=lfs diff=lfs merge=lfs -text
|
45 |
+
docs/explains/StripeDashboard_API_Key.png filter=lfs diff=lfs merge=lfs -text
|
46 |
+
docs/explains/StripePaymentPage.jpg filter=lfs diff=lfs merge=lfs -text
|
47 |
+
docs/site_libs/bootstrap/bootstrap-icons.woff filter=lfs diff=lfs merge=lfs -text
|
48 |
+
docs/tutorials/by_example_files/figure-commonmark/cell-58-1-image.png filter=lfs diff=lfs merge=lfs -text
|
49 |
+
docs/tutorials/by_example_files/figure-html/cell-58-1-image.png filter=lfs diff=lfs merge=lfs -text
|
50 |
+
texts.db filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
*.swp
|
2 |
+
*.db
|
3 |
+
*.db-*
|
4 |
+
*.db_*
|
5 |
+
tags
|
6 |
+
index_files/
|
7 |
+
data/
|
8 |
+
.DS_Store
|
9 |
+
.sesskey
|
10 |
+
__pycache__/
|
README.md
CHANGED
@@ -1,20 +1 @@
|
|
1 |
-
|
2 |
-
title: Home Fasthtml
|
3 |
-
emoji: 🚀
|
4 |
-
colorFrom: red
|
5 |
-
colorTo: red
|
6 |
-
sdk: docker
|
7 |
-
app_port: 8501
|
8 |
-
tags:
|
9 |
-
- streamlit
|
10 |
-
pinned: false
|
11 |
-
short_description: Jeremy Howard FastHTML exploration
|
12 |
-
license: apache-2.0
|
13 |
-
---
|
14 |
-
|
15 |
-
# Welcome to Streamlit!
|
16 |
-
|
17 |
-
Edit `/src/streamlit_app.py` to customize this app to your heart's desire. :heart:
|
18 |
-
|
19 |
-
If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
|
20 |
-
forums](https://discuss.streamlit.io).
|
|
|
1 |
+
fasthtml home page
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
about/LICENSE
ADDED
@@ -0,0 +1,201 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Apache License
|
2 |
+
Version 2.0, January 2004
|
3 |
+
http://www.apache.org/licenses/
|
4 |
+
|
5 |
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
6 |
+
|
7 |
+
1. Definitions.
|
8 |
+
|
9 |
+
"License" shall mean the terms and conditions for use, reproduction,
|
10 |
+
and distribution as defined by Sections 1 through 9 of this document.
|
11 |
+
|
12 |
+
"Licensor" shall mean the copyright owner or entity authorized by
|
13 |
+
the copyright owner that is granting the License.
|
14 |
+
|
15 |
+
"Legal Entity" shall mean the union of the acting entity and all
|
16 |
+
other entities that control, are controlled by, or are under common
|
17 |
+
control with that entity. For the purposes of this definition,
|
18 |
+
"control" means (i) the power, direct or indirect, to cause the
|
19 |
+
direction or management of such entity, whether by contract or
|
20 |
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
21 |
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
22 |
+
|
23 |
+
"You" (or "Your") shall mean an individual or Legal Entity
|
24 |
+
exercising permissions granted by this License.
|
25 |
+
|
26 |
+
"Source" form shall mean the preferred form for making modifications,
|
27 |
+
including but not limited to software source code, documentation
|
28 |
+
source, and configuration files.
|
29 |
+
|
30 |
+
"Object" form shall mean any form resulting from mechanical
|
31 |
+
transformation or translation of a Source form, including but
|
32 |
+
not limited to compiled object code, generated documentation,
|
33 |
+
and conversions to other media types.
|
34 |
+
|
35 |
+
"Work" shall mean the work of authorship, whether in Source or
|
36 |
+
Object form, made available under the License, as indicated by a
|
37 |
+
copyright notice that is included in or attached to the work
|
38 |
+
(an example is provided in the Appendix below).
|
39 |
+
|
40 |
+
"Derivative Works" shall mean any work, whether in Source or Object
|
41 |
+
form, that is based on (or derived from) the Work and for which the
|
42 |
+
editorial revisions, annotations, elaborations, or other modifications
|
43 |
+
represent, as a whole, an original work of authorship. For the purposes
|
44 |
+
of this License, Derivative Works shall not include works that remain
|
45 |
+
separable from, or merely link (or bind by name) to the interfaces of,
|
46 |
+
the Work and Derivative Works thereof.
|
47 |
+
|
48 |
+
"Contribution" shall mean any work of authorship, including
|
49 |
+
the original version of the Work and any modifications or additions
|
50 |
+
to that Work or Derivative Works thereof, that is intentionally
|
51 |
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
52 |
+
or by an individual or Legal Entity authorized to submit on behalf of
|
53 |
+
the copyright owner. For the purposes of this definition, "submitted"
|
54 |
+
means any form of electronic, verbal, or written communication sent
|
55 |
+
to the Licensor or its representatives, including but not limited to
|
56 |
+
communication on electronic mailing lists, source code control systems,
|
57 |
+
and issue tracking systems that are managed by, or on behalf of, the
|
58 |
+
Licensor for the purpose of discussing and improving the Work, but
|
59 |
+
excluding communication that is conspicuously marked or otherwise
|
60 |
+
designated in writing by the copyright owner as "Not a Contribution."
|
61 |
+
|
62 |
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
63 |
+
on behalf of whom a Contribution has been received by Licensor and
|
64 |
+
subsequently incorporated within the Work.
|
65 |
+
|
66 |
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
67 |
+
this License, each Contributor hereby grants to You a perpetual,
|
68 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
69 |
+
copyright license to reproduce, prepare Derivative Works of,
|
70 |
+
publicly display, publicly perform, sublicense, and distribute the
|
71 |
+
Work and such Derivative Works in Source or Object form.
|
72 |
+
|
73 |
+
3. Grant of Patent License. Subject to the terms and conditions of
|
74 |
+
this License, each Contributor hereby grants to You a perpetual,
|
75 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
76 |
+
(except as stated in this section) patent license to make, have made,
|
77 |
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
78 |
+
where such license applies only to those patent claims licensable
|
79 |
+
by such Contributor that are necessarily infringed by their
|
80 |
+
Contribution(s) alone or by combination of their Contribution(s)
|
81 |
+
with the Work to which such Contribution(s) was submitted. If You
|
82 |
+
institute patent litigation against any entity (including a
|
83 |
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
84 |
+
or a Contribution incorporated within the Work constitutes direct
|
85 |
+
or contributory patent infringement, then any patent licenses
|
86 |
+
granted to You under this License for that Work shall terminate
|
87 |
+
as of the date such litigation is filed.
|
88 |
+
|
89 |
+
4. Redistribution. You may reproduce and distribute copies of the
|
90 |
+
Work or Derivative Works thereof in any medium, with or without
|
91 |
+
modifications, and in Source or Object form, provided that You
|
92 |
+
meet the following conditions:
|
93 |
+
|
94 |
+
(a) You must give any other recipients of the Work or
|
95 |
+
Derivative Works a copy of this License; and
|
96 |
+
|
97 |
+
(b) You must cause any modified files to carry prominent notices
|
98 |
+
stating that You changed the files; and
|
99 |
+
|
100 |
+
(c) You must retain, in the Source form of any Derivative Works
|
101 |
+
that You distribute, all copyright, patent, trademark, and
|
102 |
+
attribution notices from the Source form of the Work,
|
103 |
+
excluding those notices that do not pertain to any part of
|
104 |
+
the Derivative Works; and
|
105 |
+
|
106 |
+
(d) If the Work includes a "NOTICE" text file as part of its
|
107 |
+
distribution, then any Derivative Works that You distribute must
|
108 |
+
include a readable copy of the attribution notices contained
|
109 |
+
within such NOTICE file, excluding those notices that do not
|
110 |
+
pertain to any part of the Derivative Works, in at least one
|
111 |
+
of the following places: within a NOTICE text file distributed
|
112 |
+
as part of the Derivative Works; within the Source form or
|
113 |
+
documentation, if provided along with the Derivative Works; or,
|
114 |
+
within a display generated by the Derivative Works, if and
|
115 |
+
wherever such third-party notices normally appear. The contents
|
116 |
+
of the NOTICE file are for informational purposes only and
|
117 |
+
do not modify the License. You may add Your own attribution
|
118 |
+
notices within Derivative Works that You distribute, alongside
|
119 |
+
or as an addendum to the NOTICE text from the Work, provided
|
120 |
+
that such additional attribution notices cannot be construed
|
121 |
+
as modifying the License.
|
122 |
+
|
123 |
+
You may add Your own copyright statement to Your modifications and
|
124 |
+
may provide additional or different license terms and conditions
|
125 |
+
for use, reproduction, or distribution of Your modifications, or
|
126 |
+
for any such Derivative Works as a whole, provided Your use,
|
127 |
+
reproduction, and distribution of the Work otherwise complies with
|
128 |
+
the conditions stated in this License.
|
129 |
+
|
130 |
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
131 |
+
any Contribution intentionally submitted for inclusion in the Work
|
132 |
+
by You to the Licensor shall be under the terms and conditions of
|
133 |
+
this License, without any additional terms or conditions.
|
134 |
+
Notwithstanding the above, nothing herein shall supersede or modify
|
135 |
+
the terms of any separate license agreement you may have executed
|
136 |
+
with Licensor regarding such Contributions.
|
137 |
+
|
138 |
+
6. Trademarks. This License does not grant permission to use the trade
|
139 |
+
names, trademarks, service marks, or product names of the Licensor,
|
140 |
+
except as required for reasonable and customary use in describing the
|
141 |
+
origin of the Work and reproducing the content of the NOTICE file.
|
142 |
+
|
143 |
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
144 |
+
agreed to in writing, Licensor provides the Work (and each
|
145 |
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
146 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
147 |
+
implied, including, without limitation, any warranties or conditions
|
148 |
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
149 |
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
150 |
+
appropriateness of using or redistributing the Work and assume any
|
151 |
+
risks associated with Your exercise of permissions under this License.
|
152 |
+
|
153 |
+
8. Limitation of Liability. In no event and under no legal theory,
|
154 |
+
whether in tort (including negligence), contract, or otherwise,
|
155 |
+
unless required by applicable law (such as deliberate and grossly
|
156 |
+
negligent acts) or agreed to in writing, shall any Contributor be
|
157 |
+
liable to You for damages, including any direct, indirect, special,
|
158 |
+
incidental, or consequential damages of any character arising as a
|
159 |
+
result of this License or out of the use or inability to use the
|
160 |
+
Work (including but not limited to damages for loss of goodwill,
|
161 |
+
work stoppage, computer failure or malfunction, or any and all
|
162 |
+
other commercial damages or losses), even if such Contributor
|
163 |
+
has been advised of the possibility of such damages.
|
164 |
+
|
165 |
+
9. Accepting Warranty or Additional Liability. While redistributing
|
166 |
+
the Work or Derivative Works thereof, You may choose to offer,
|
167 |
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
168 |
+
or other liability obligations and/or rights consistent with this
|
169 |
+
License. However, in accepting such obligations, You may act only
|
170 |
+
on Your own behalf and on Your sole responsibility, not on behalf
|
171 |
+
of any other Contributor, and only if You agree to indemnify,
|
172 |
+
defend, and hold each Contributor harmless for any liability
|
173 |
+
incurred by, or claims asserted against, such Contributor by reason
|
174 |
+
of your accepting any such warranty or additional liability.
|
175 |
+
|
176 |
+
END OF TERMS AND CONDITIONS
|
177 |
+
|
178 |
+
APPENDIX: How to apply the Apache License to your work.
|
179 |
+
|
180 |
+
To apply the Apache License to your work, attach the following
|
181 |
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
182 |
+
replaced with your own identifying information. (Don't include
|
183 |
+
the brackets!) The text should be enclosed in the appropriate
|
184 |
+
comment syntax for the file format. We also recommend that a
|
185 |
+
file or class name and description of purpose be included on the
|
186 |
+
same "printed page" as the copyright notice for easier
|
187 |
+
identification within third-party archives.
|
188 |
+
|
189 |
+
Copyright [yyyy] [name of copyright owner]
|
190 |
+
|
191 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
192 |
+
you may not use this file except in compliance with the License.
|
193 |
+
You may obtain a copy of the License at
|
194 |
+
|
195 |
+
http://www.apache.org/licenses/LICENSE-2.0
|
196 |
+
|
197 |
+
Unless required by applicable law or agreed to in writing, software
|
198 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
199 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
200 |
+
See the License for the specific language governing permissions and
|
201 |
+
limitations under the License.
|
about/README.md
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
# fh-about
|
2 |
+
fastht.ml/about source
|
about/app.py
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from itertools import chain
|
2 |
+
from fasthtml.common import *
|
3 |
+
from functools import partial
|
4 |
+
from monsterui.all import *
|
5 |
+
import fasthtml.common as fh
|
6 |
+
from monsterui.foundations import *
|
7 |
+
|
8 |
+
_A = partial(A, target='_blank')
|
9 |
+
def Markdown(s, **kw): return Div(render_md(s, class_map_mods={'ul':'uk-list uk-list-bullet space-y-2 mb-6 ml-6 text-lg'}), **kw)
|
10 |
+
|
11 |
+
ghurl = 'https://github.com/AnswerDotAI/fasthtml'
|
12 |
+
fhurl = 'https://fastht.ml'
|
13 |
+
docs = '/docs'
|
14 |
+
|
15 |
+
def NavBar(*c, # Component for right side of navbar (Often A tag links)
|
16 |
+
brand=None, # Brand/logo component for left side
|
17 |
+
right_items=None,
|
18 |
+
right_cls='items-center space-x-4', # Spacing for desktop links
|
19 |
+
mobile_cls='space-y-4', # Spacing for mobile links
|
20 |
+
cls='p-4', # Classes for navbar
|
21 |
+
)->FT: # Responsive NavBar
|
22 |
+
"Creates a responsive navigation bar with mobile menu support"
|
23 |
+
menu_id = fh.unqid()
|
24 |
+
mobile_icon = A(UkIcon("menu", width=30, height=30), cls="md:hidden", data_uk_toggle=f"target: #{menu_id}; cls: hidden")
|
25 |
+
return Div(
|
26 |
+
Div(DivFullySpaced(
|
27 |
+
DivLAligned(brand, Div(*c, cls='hidden md:flex space-x-4')), # Brand/logo component for left side
|
28 |
+
mobile_icon, # Hamburger menu icon
|
29 |
+
Div(*right_items,cls=(stringify(right_cls),'hidden md:flex'))), # Desktop Navbar
|
30 |
+
cls=('monster-navbar', stringify(cls))),
|
31 |
+
DivCentered(*c, *right_items,
|
32 |
+
cls=(stringify(mobile_cls),stringify(cls),'hidden md:hidden monster-navbar'),
|
33 |
+
id=menu_id))
|
34 |
+
|
35 |
+
def NavLink(*args, cls='text-gray-800', target='_blank', **kw):
|
36 |
+
return fh.A(*args, cls=(cls, TextT.lg, 'hover:text-yellow-400/60 transition-colors text-sm'), target=target, **kw)
|
37 |
+
|
38 |
+
def BstPage(selidx, title, h2s, *c):
|
39 |
+
navitems = [('About', '/about'), ('Vision', '/about/vision'), ('Foundations', '/about/foundation'),
|
40 |
+
('Technology', '/about/tech'), ('Components', '/about/components'), ('Limits', '#', {'disabled':True})]
|
41 |
+
logo = 'assets/logo.svg'
|
42 |
+
return (
|
43 |
+
Title(title),
|
44 |
+
Container(
|
45 |
+
NavBar(
|
46 |
+
*[NavLink(k, href=v, target=None, cls=TextT.bold if selidx==i else '') for i, (k,v) in enumerate(navitems[:-1])],
|
47 |
+
NavLink('Limits', href='javascript:void(0)', disabled=True, uk_tooltip='No limits!', cls=TextT.gray, target=None),
|
48 |
+
brand=A(Img(src=logo), href=fhurl),
|
49 |
+
right_items=[
|
50 |
+
NavLink('Docs', href=docs),
|
51 |
+
NavLink(Img(src='assets/github-mark/github-mark.svg', width=20, height=20), href=ghurl),
|
52 |
+
],
|
53 |
+
cls='bg-[#3cdd8c] rounded-t-3xl p-2 py-5 px-4'),
|
54 |
+
|
55 |
+
Container(
|
56 |
+
Grid(
|
57 |
+
Div(NavContainer(*[Li(A(h2, href=f'#sec{i+1}')) for i,h2 in enumerate(h2s)],
|
58 |
+
sticky=True, uk_scrollspy_nav=True), cls='hidden md:block col-span-1'),
|
59 |
+
Div(H1(title, cls='mb-12'), *c, cls='col-span-12 md:col-span-5'),
|
60 |
+
cols=6)),
|
61 |
+
|
62 |
+
# Footer
|
63 |
+
DividerLine(),
|
64 |
+
Grid(
|
65 |
+
P("© 2024 onwards AnswerDotAI, Inc", cls=TextPresets.muted_lg),
|
66 |
+
DivCentered(A(Img(src=logo, height=24), href=fhurl)),
|
67 |
+
DivRAligned(A("Home"),
|
68 |
+
_A("Docs",href='/docs'),
|
69 |
+
_A("Company", href='https://www.answer.ai/'), cls=TextPresets.muted_lg+'space-x-4'),
|
70 |
+
),
|
71 |
+
cls='py-8 mb-4' + ContainerT.xl))
|
72 |
+
|
73 |
+
def Sections(h2s, texts):
|
74 |
+
colors = 'yellow', 'pink', 'teal', 'blue'
|
75 |
+
div_cls = 'py-2 px-3 mt-4 mb-2 bg-{}-400/70 rounded-tl-3xl' #bg-{}-100
|
76 |
+
return chain([Div(H2(h2, id=f'sec{i+1}', cls=div_cls.format(colors[i%4])), Div(txt, cls='px-2'))
|
77 |
+
for i,(h2,txt) in enumerate(zip(h2s, texts))])
|
about/components.py
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from about.app import *
|
2 |
+
|
3 |
+
def page():
|
4 |
+
h2s = 'Why', 'How', 'The future'
|
5 |
+
txts = [Markdown(s1), Markdown(s2), Markdown(s3)]
|
6 |
+
secs = Sections(h2s, txts)
|
7 |
+
return BstPage(4, "Python HTML components", h2s, *secs)
|
8 |
+
|
9 |
+
s1 = """
|
10 |
+
FastHTML embeds HTML generation inside Python code. The idea of embedding an HTML generator inside a programming language is not new. It is a particularly popular approach in functional languages, and includes libraries like: Elm-html (Elm), hiccl (Common Lisp), hiccup (Clojure), Falco.Markup (F#), Lucid (Haskell), and dream-html (OCaml). But the idea has now gone far beyond the functional programming world--- JSX, an embedded HTML generator for React, is one of the most popular approaches for creating web apps today.
|
11 |
+
|
12 |
+
However most Python programmers are probably more familiar with template-based approaches, such as Jinja2 or Mako. Templates were originally created for web development in the 1990s, back when web design required complex browser-specific HTML. By using templates, designers were able to work in a familiar language, and programmers could "fill in the blanks" with the data they needed. Today this is not needed, since we can create simple semantic HTML, and use CSS to style it.
|
13 |
+
|
14 |
+
Templates have a number of disadvantages, for instance:
|
15 |
+
|
16 |
+
- They require a separate language to write the templates, which is an additional learning curve
|
17 |
+
- Template languages are generally less concise and powerful than Python
|
18 |
+
- Refactoring a template into sub-components is harder than refactoring Python code
|
19 |
+
- Templates generally require separate files
|
20 |
+
- Templates generally do not support the Python debugger.
|
21 |
+
|
22 |
+
By using Python as the HTML-generation language, we can avoid these disadvantages. More importantly, we can create a rich ecosystem of tools and frameworks available as pip-installable Python modules, which can be used to build web applications.
|
23 |
+
"""
|
24 |
+
|
25 |
+
s2 = """
|
26 |
+
FastHTML's underlying component data structure is called `FT` ("FastTag"). To learn how this works in detail, see the [Explaining FT Components](/docs/explains/explaining_xt_components.html) page. `FT` objects can be created with functions with the Capitalized name of each HTML tag, such as `Div`, `P`, and `Img`. The functions generally take positional and keyword arguments:
|
27 |
+
|
28 |
+
- Positional arguments represent a list of children, which can be strings (in which case they are text nodes), FT child components, or other Python objects (which are stringified).
|
29 |
+
- Keyword arguments represent a dictionary of attributes, which can be used to set the properties of the HTML tag
|
30 |
+
- Keyword arguments starting with `hx_` are used for HTMX attributes.
|
31 |
+
|
32 |
+
Some functions, such as `File`, have special syntax for their arguments. For instance, `File` takes a single filename argument, and creates a DOM subtree representing the contents of the file.
|
33 |
+
|
34 |
+
Any FastHTML handler can return a tree of `FT` components, or a tuple of FT component trees, which will be rendered as HTML partials and sent to the client for processing by HTMX. If a user goes directly to a URL rather than using HTMX, the server will automatically return a full HTML page with the partials embedded in the body.
|
35 |
+
|
36 |
+
Much of the time you'll probably be using pre-written FastHTML components that package up HTML, CSS, and JS. Often, these will in turn hand off much of the work to some general web framework; for instance the site you're reading now uses Bootstrap (and the `fh-bootstrap` FastHTML wrapper). At first, moving from HTML to FT components, can seem odd, but it soon becomes natural -- as Audrey Roy Greenfeld, a hugely experienced Python web programmer author, and educator, told us:
|
37 |
+
|
38 |
+
> "*In my head I had resistance and initial scepticism to converting all my HTML to FT. When I realised that working with the tags in Python is like the elegance of working in the frequency domain after Fourier transform vs. working with time series data in the time domain, I finally gave in, let go, started enjoying the FT tags. The first few times I thought the approach of conversion and then copy pasting was crazy. It was only when I started to understand how to organise the tags into components that it suddenly felt elegant and templates felt crazy.*"
|
39 |
+
|
40 |
+
One good approach to creating components is to find things you like on the web and convert them to FastHTML. There's a simple trick to doing this:
|
41 |
+
|
42 |
+
1. Right-click on the part of a web page that you want to use in your app, and choose 'Inspect'
|
43 |
+
1. In the elements window that pops up, right-click on the element you want, choose 'Copy', and then 'Outer HTML'
|
44 |
+
1. Now you've got HTML in your clipboard, you can automatically convert it to FastHTML: go to [h2f.answer.ai](https://h2x.answer.ai/), paste the HTML into the text area at the top, then the FastHTML code will appear at the bottom. Click the Copy icon at the top right of that code and then paste it into your Python app.
|
45 |
+
|
46 |
+
BTW, the h2f app mentioned above is written in around a dozen lines of code! You can see the [source code here](https://github.com/AnswerDotAI/fasthtml-example/blob/main/h2f/main.py).
|
47 |
+
"""
|
48 |
+
|
49 |
+
s3 = """
|
50 |
+
We want your help! FastHTML is very new, so the ecosystem at this stage is still small. We hope to see FastHTML Python versions of style libraries like Bootstrap, DaisyUI, and Shoelace, as well as versions of all the most popular JavaScript libraries. If you are a Python developer, we would love your help in creating these libraries! If you do create something for FastHTML users, let us know, so we can link to your work (or if you think it would be a useful part of the FastHTML library itself, or one of our extension libraries, feel free to send us a pull request).
|
51 |
+
|
52 |
+
We would also like to see Python modules that hook into FastHTML's and Starlette's extensibility points, such as for authentication, database access, deployment, multi-host support, and so forth. Thanks to Python's flexibility and the power of ASGI, it should be possible for a single FastHTML server to replace a whole stack of separate web servers, proxies, and other components.
|
53 |
+
"""
|
about/favicon.ico
ADDED
|
about/foundations.py
ADDED
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from about.app import *
|
2 |
+
|
3 |
+
def page():
|
4 |
+
h2s = 'ASGI', 'HTMX', 'HTTP', 'HTML/CSS/JS'
|
5 |
+
secs = Sections(h2s, map(Markdown, [s1, s2, s3, s4]))
|
6 |
+
return BstPage(2, 'The foundations of FastHTML', h2s, *secs)
|
7 |
+
|
8 |
+
s1 = """
|
9 |
+
FastHTML brings together and builds on top of two well-established, astonishingly flexible, performant technology frameworks: *ASGI* (implemented in Uvicorn and Starlette), and *HTMX*.
|
10 |
+
|
11 |
+
[ASGI](https://asgi.readthedocs.io/en/latest/) is a small but incredibly clever approach to simplifying how HTTP, the foundation of web communication, works. It converts all the different parts of an HTTP transaction into a basic, well-defined Python API: a single function, which takes three parameters, which provides access to the full HTTP specification.
|
12 |
+
|
13 |
+
Uvicorn is the ASGI server used by FastHTML---that is, it is responsible for listening for HTTP messages, and converting them into the Python ASGI API. Then Starlette is responsible for taking this powerful single-function ASGI foundation and making it more convenient for programmers, by adding a small number of functions and classes that remove the boilerplate you would otherwise need to support ASGI. As a FastHTML user you very rarely need to know anything about the ASGI/Uvicorn/Starlette trio, other than that it is there in the background doing a lot of work for you!
|
14 |
+
|
15 |
+
To learn more about how Uvicorn and Starlette work in FastHTML, see the relevant [technology section](/tech#sec3).
|
16 |
+
"""
|
17 |
+
|
18 |
+
s2 = """
|
19 |
+
HTML on its own provides only the most basic interaction mechanisms: you can click on a link to “get” an HTML page, or you can click a button on a form to “post” form data. In either case, the HTML result from the server replaces the current page (known as a “full page refresh”). These limitations have been there since the earlier days of the web. [HTMX](https://htmx.org/) is a library that removes them, by removing four key constraints:
|
20 |
+
|
21 |
+
1. Any element on a page can call the server, not only links and forms
|
22 |
+
2. Any event can call the server (e.g. mouseover, key-down, or scroll), not only clicks
|
23 |
+
3. Any HTTP method can be used to call the server, not only “get” and “post” methods
|
24 |
+
4. The server response can be used to modify the existing page in any way, deleting elements, adding elements, or changing elements, instead of only replacing the whole page.
|
25 |
+
|
26 |
+
<img src="assets/htmx-meme.png" alt="HTMX meme" class="img-fluid mx-auto d-block">
|
27 |
+
|
28 |
+
HTMX was previously known as [Intercooler](https://intercoolerjs.org/). It is now over 10 years old---so it's a mature technology. HTMX/Intercooler is responsible for the idea that we can build on top of the fundamentals of the web, without sacrificing the ability to create modern, interactive web applications. Without it, FastHTML would not exist. HTMX is famous for its [memes](https://v1.htmx.org/essays/#memes), including the image above, which highlights how HTMX's approach returns us to the simplicity of the early days of the web (although perhaps now we should update that meme to FastHTML 2024, where we would have just 3 parts: browser, DOM, and a python file!)
|
29 |
+
|
30 |
+
To learn more about how HTMX works and how to use it, see the [HTMX technology section](/tech#sec2). To understand the benefits of using HTMX in practice, watch [this talk](https://www.youtube.com/watch?v=3GObi93tjZI), which goes through a real case study of using HTMX to replace React in a complex large application. It shows how HTMX allowed the amount of code to be drastically reduced, the speed of the site got faster, and they were able to simplify their team structure by removing the need for frontend specialists.
|
31 |
+
"""
|
32 |
+
|
33 |
+
s3 = """
|
34 |
+
All web page requests are made by your browser, and returned by the web server, using *HTTP*. Many web programming systems attempt to hide this from the developer, but FastHTML (and the underlying technologies Uvicorn, Starlette, and HTMX) does not. By surfacing this, it means you are working directly with the foundations of the web, not through frequently-changing leaky abstractions. HTTP is, at its heart, a simple text protocol that underlies all web communication. It starts with a request, e.g:
|
35 |
+
|
36 |
+
```
|
37 |
+
GET / HTTP/1.1
|
38 |
+
Host: www.example.com
|
39 |
+
User-Agent: Mozilla/5.0
|
40 |
+
Accept-Language: en-GB,en;q=0.5
|
41 |
+
Accept-Encoding: gzip, deflate, br
|
42 |
+
Connection: keep-alive
|
43 |
+
```
|
44 |
+
|
45 |
+
The first line shows it is a *GET* request for the root URL (`/`). The next lines are *headers*, which provide additional information about the request.
|
46 |
+
|
47 |
+
The server then responds with a status code (here *200*, which represents success), headers, and the content, e.g:
|
48 |
+
|
49 |
+
```
|
50 |
+
HTTP/1.1 200 OK
|
51 |
+
Date: Wed, 08 Jan 2024 23:1:05 GMT
|
52 |
+
Content-Type: text/html; charset=UTF-8
|
53 |
+
Content-Length: 5
|
54 |
+
Server: Apache/2.4.51 (Unix)
|
55 |
+
Connection: close
|
56 |
+
|
57 |
+
hello
|
58 |
+
```
|
59 |
+
|
60 |
+
When you understand that all web applications communicate like this, and your programming framework lets you easily interact with this, you will have no limitations on what you can build. Having said that, working directly with HTTP's text protocol is not easy, which is why the higher-level ASGI protocol exists. It makes all of HTTP available to the Python programmer in a simpler form. In addition, HTMX allows the browser to more fully utilise HTTP.
|
61 |
+
"""
|
62 |
+
|
63 |
+
s4 = """
|
64 |
+
In the previous section, the server responded with the body "`hello`". But in practice, web server responses today generally are either HTML or JSON. With FastHTML (as we'll see in the [HTMX technology section](/tech#sec2)), our responses are nearly always HTML. Here's an example of a basic HTML page with a header and a body containing a paragraph (`<p>` tag).
|
65 |
+
|
66 |
+
```html
|
67 |
+
<html>
|
68 |
+
<head><title>Example</title></head>
|
69 |
+
<body><p>Hello World!</p></body>
|
70 |
+
</html>
|
71 |
+
```
|
72 |
+
|
73 |
+
HTML creates structure, and the browser converts the HTML internally into a Document Object Model (DOM) element tree. To add styling to the browser's representation of a document, we add styles using *CSS*. One approach is to manually define styles in a CSS file---for instance [here's the stylesheet](https://github.com/AnswerDotAI/fh-bootstrap/blob/main/fh_bootstrap/assets/fh-bootstrap.css#L1) we're using for the site you're reading now, with the CSS rule which gives the above HTML block a light grey border and background.
|
74 |
+
|
75 |
+
Most styles in most FastHTML applications won't be manually defined, but instead will come from a CSS framework like Bootstrap, DaisyUI, or Shoelace. FastHTML makes these easily available as [FT components](/components).
|
76 |
+
|
77 |
+
Although most of the logic of your application will generally be written in Python and made available over HTTP using FastHTML, you might well want some self-contained UI updates to happen directly in the browser. For this, you can write JavaScript and add it to the web page using FastHTML. This is not often strictly required, but can make some parts of your app faster, more concise, or add some convenient functionality from the browser's DOM API. For instance, we often add a "Copy" button with sample code in our apps, which requires using the DOM API, and therefore requires adding a little JavaScript. JavaScript was originally designed for this purpose, so it's a particularly good fit for adding client-side behaviours to applications.
|
78 |
+
|
79 |
+
To learn how to add JS libraries to FastHTML, it can help to look at examples. FastHTML includes modules for a number of popular JS libraries, such as [Marked.js](https://marked.js.org/). To see how this is implemented, have a look at the [seven lines of source code](https://github.com/AnswerDotAI/fasthtml/blob/main/fasthtml/js.py#L7) for `MarkdownJS` in Python.
|
80 |
+
"""
|
81 |
+
|
about/main.py
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import about.vision, about.overview, about.foundations, about.tech, about.components
|
2 |
+
from fasthtml.common import *
|
3 |
+
from monsterui.all import *
|
4 |
+
|
5 |
+
hdrs = (
|
6 |
+
*Theme.blue.headers(highlightjs=True, mode='light'),
|
7 |
+
Script(src="https://cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/languages/html.min.js"),
|
8 |
+
*Socials(title='About FastHTML', description='Learn the foundations of FastHTML', site_name='fastht.ml/about',
|
9 |
+
twitter_site='@answerdotai', image=f'/assets/og-sq.png', url=''),
|
10 |
+
)
|
11 |
+
|
12 |
+
app,rt = fast_app(hdrs=hdrs)
|
13 |
+
app.get('/')(about.overview.page)
|
14 |
+
app.get('/components')(about.components.page)
|
15 |
+
app.get('/foundation')(about.foundations.page)
|
16 |
+
app.get('/tech')(about.tech.page)
|
17 |
+
app.get('/vision')(about.vision.page)
|
18 |
+
|
19 |
+
serve()
|
about/overview.py
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from about.app import *
|
2 |
+
|
3 |
+
def page():
|
4 |
+
caption = "'Real' web development shouldn't be this hard..."
|
5 |
+
fig = Figure(DivCentered(Img(src='/assets/webdev.jpg', alt='Web dev'), Caption(caption, cls=TextT.lg+'pt-4')), cls='float-right w-1/2 m-4')
|
6 |
+
h2s = 'Getting started', 'Background', 'Current Status'
|
7 |
+
txts = [Markdown(s1), Div(fig, Markdown(s2)), Markdown(s3)]
|
8 |
+
secs = Sections(h2s, txts)
|
9 |
+
return BstPage(0, 'About FastHTML', h2s, *secs)
|
10 |
+
|
11 |
+
s1 = """
|
12 |
+
FastHTML is a new way to create modern interactive web apps. It scales down to a 6-line python file, and scales up to complex production apps. Auth, DBs, caching, styling, etc are all built-in, and replaceable and extensible. 1-click deploy is available to Railway, Vercel, Huggingface, and more---or deploy to any Python server or VPS, including Azure, GCP, and AWS.
|
13 |
+
|
14 |
+
You're using a FastHTML app right now. We didn't create a separate blog system for this site, because building apps with FastHTML is so easy there's no need for it! Here is the [source code](https://github.com/AnswerDotAI/fh-about/blob/main/overview.py) for the current page, for instance. You'll see that the code is very simple, relying on Python components like `Markdown` to build the page. The components are simple Python functions---here is the [source code for `Markdown`](https://github.com/AnswerDotAI/fh-about/blob/main/app.py#L6), taking just one line of code! Out of the box FastHTML provides authentication, [database](/tech#sec5) access, styles (via [PicoCSS](https://picocss.com/)), and more. Every part of the system is extensible and replacable using pip-installable Python modules.
|
15 |
+
|
16 |
+
The site you're reading right now provides background information about the key concepts and ideas behind FastHTML. The [documentation](/docs) focuses on the code. Because FastHTML brings together many different web technologies, it's worth investing some time to understand how it all fits together. Have a look through the five sections in the green navbar (or hamburger menu if you're on mobile) above to deepen your understanding. As legendary Python coder and "Two Scoops of Django" co-author Audrey Roy Greenfeld told us:
|
17 |
+
|
18 |
+
> "*I think the fact that an experienced web dev can get productive in 1 hour accidentally undersells FastHTML a bit. For me it is like a fractal where the more I explore, the more interesting is and the more I learn. I'm about 40 hours in, enough to realise I know nothing compared with what I can learn.*"
|
19 |
+
|
20 |
+
If you're an experienced web dev, then you can use all your knowledge of CSS, HTML, JS, etc. to build web applications with FastHTML right away. We've heard from expert coders that they have successfully built complete web apps within an hour of getting started with FastHTML. We've got a [Quickstart for Web Developers](/docs/tutorials/quickstart_for_web_devs.html) tutorial that will get you up and running quickly. (Read the rest of the docs while you're there!) Next, read through the heavily-commented source of this [idiomatic fasthtml app](https://github.com/AnswerDotAI/fasthtml/blob/main/examples/adv_app.py). Then study some of the [fasthtml-example applications](https://github.com/AnswerDotAI/fasthtml-example), particularly the first four listed.
|
21 |
+
|
22 |
+
If you haven't done much (or any) web development, try following through each step of the [FastHTML By Example](/docs/tutorials/by_example.html) tutorial. We don't yet have a self-contained guide explaining all the web foundations you'll need to know (HTML, HTTP, CSS, etc.), so you'll probably need to do some self-learning through other resources. But watch this space---we're planning a complete web programming from scratch course soon! In the meantime, here's a 1-hour video lesson to help you get going:
|
23 |
+
|
24 |
+
<div class="embed-responsive embed-responsive-16by9">
|
25 |
+
<iframe width="560" height="315" class="embed-responsive-item" src="https://www.youtube.com/embed/Auqrm7WFc0I?si=3B1ZgtH27yJ3u7d0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
|
26 |
+
</div>
|
27 |
+
"""
|
28 |
+
|
29 |
+
s2 = """
|
30 |
+
FastHTML is a system for writing web applications in Python. It is designed to be simple, powerful, and flexible. It is also designed to be easy to learn and use. The project is inspired by technologies such as React JSX, Hotwire, Astro, FastAPI, and Phoenix LiveView. FastHTML is small and simple---at the time of writing, it's under 1000 lines of code. That's because it's built on top of powerful and flexible foundations: Python, Starlette, Uvicorn, and HTMX. If you're a FastAPI user, much of FastHTML will look very familar; FastAPI was a major inspiration.
|
31 |
+
|
32 |
+
FastHTML was originally started by Jeremy Howard at Answer.AI for a number of reasons:
|
33 |
+
|
34 |
+
- Over 25 years of web development, Jeremy realized that web programming could be easier and more powerful. He was particularly concerned that recent trends had moved away from the power of the web's foundations, resulting in a fractured ecosystem of over-complex frameworks and tools
|
35 |
+
- He saw that two small but ingenious developments had made the web's foundations more powerful and more accessible: **ASGI** and **HTMX**. But the tools available for using them were still too complex, and the barriers to entry were still too high
|
36 |
+
- Jeremy and his wife Rachel had spent the last 8 years working to make artificial intelligence accessible to more people. They saw that the most widely used web development tools were too complex for people who aren't full time coders. This meant that Jeremy and Rachel's students struggled to turn their AI project ideas into working applications.
|
37 |
+
- Jeremy's goal for Answer.AI is to help society benefit from AI, which means creating lots of useful products and services that use AI effectively---so creating those products and services needs to be made as fast and easy as possible.
|
38 |
+
|
39 |
+
FastHTML is a framework that deals with all these issues: it returns to the roots of the web, leveraging ASGI and HTMX, and is usable by both experienced developers and new coders.
|
40 |
+
|
41 |
+
#### A new generation of coders
|
42 |
+
|
43 |
+
Coding is the key to turning the ideas in your head into products and services that can help people. AI has recently made it easier to get started with coding, which means there are more people than ever before who can create useful stuff.
|
44 |
+
|
45 |
+
But this new generation of coders do not generally have the same background as full-time software engineers. They may have been trained in a different field, or they may have learned to code on their own. We hope that FastHTML will make it easier for this new generation of coders to turn their ideas into reality. To create maintainable and scalable solutions.
|
46 |
+
"""
|
47 |
+
|
48 |
+
s3 = """
|
49 |
+
FastHTML works well right now, but it is still young. We are using it for nearly every part of the FastHTML project itself ("almost" because the docs are using [Quarto](https://quarto.org/) for now; we plan to port them to a FastHTML-based documentation system soon). For instance, we worked with a design team to create the [fastht.ml home page](https://www.fastht.ml/), which is implemented in FastHTML---here is the [home page source](https://github.com/AnswerDotAI/home-fasthtml/blob/main/main.py).
|
50 |
+
|
51 |
+
We're working on a number of things to make FastHTML even better. Not everything is ready "out of the box" yet. If you see something missing that you need, please let us know by [creating an issue](https://github.com/AnswerDotAI/fasthtml/issues). Or feel free to add it yourself and send in a pull request!
|
52 |
+
|
53 |
+
The plan is for FastHTML to do just about everything that frameworks like Django, NextJS, and Ruby on Rails do, but it'll take a while to get there! For experienced developers, adding bindings to CSS frameworks, pypi Python modules, and JS libraries is straightforward---if you add one, please put your binding module on pypi so that the community can use it, and let us know so we can link to your project. We invite you to use the "`fh-`" prefix on PyPI to make it easy to identify FastHTML packages there.
|
54 |
+
|
55 |
+
Here's a few of the things on our short to medium term agenda:
|
56 |
+
|
57 |
+
- OAuth support
|
58 |
+
- Support for more databases
|
59 |
+
- Support for more CSS frameworks, including DaisyUI, Bootstrap, Shoelace, and Flowbite (we've already made a start at all of these).
|
60 |
+
"""
|
about/requirements.txt
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
python-fasthtml
|
2 |
+
monsterui
|
about/tech.py
ADDED
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from about.app import *
|
2 |
+
|
3 |
+
def page():
|
4 |
+
h2s = 'Python', 'HTMX', 'Uvicorn', 'Starlette', 'SQLite'
|
5 |
+
txts = [Markdown(s1), Markdown(s2), Markdown(s3), Markdown(s4), Markdown(s5)]
|
6 |
+
secs = Sections(h2s, txts)
|
7 |
+
return BstPage(3, "FastHTML's tech stack", h2s, *secs)
|
8 |
+
|
9 |
+
s1 = """
|
10 |
+
Many of the largest software systems in the world are built using Python, such as much of the code for YouTube, Instagram, Dropbox, and many others. In 2019, Dropbox announced that python was their "most widely used language both for backend services and the desktop client app", with 4 million lines of code.
|
11 |
+
|
12 |
+
If you're already a Python programmer, then you'll know how easy it is to turn your ideas into code using this language. As well as being used for large-scale systems, Python is also popular for the day-to-day work of scientists, engineers, data analysts, and so forth.
|
13 |
+
|
14 |
+
One particular challenge for Python programmers has been that to create a modern web application, they have had to also learn JavaScript, along with a framework like React, Angular, or Vue. Even after learning all this, they still have to deal with the complexity of writing, debugging, and maintaining a multi-language system with complex interactions between the two languages and across the client-server boundary.
|
15 |
+
|
16 |
+
With FastHTML, you'll often find you never have to write any JavaScript at all. Not only does development and debugging become much easier, but many features suddenly become easier to implement. For instance, when we wanted to add caching to speed up our [home page](https://fastht.ml), we simply added a standard decorator to the function that creates it. No need for special infrastructure, because the implementation is all in one place. ASGI makes this particularly powerful---it can handle caching, sessions, authentication, host-based redirects, sub-routing, and more, all in one place. All of this is directly accessible from FastHTML.
|
17 |
+
"""
|
18 |
+
|
19 |
+
s2 = """
|
20 |
+
Nowadays most web applications are built using backend systems that return a combination of JSON and HTML data over HTTP. Javascript, normally using frameworks such as React, Angular, or Vue, is used to combine the JSON and HTML together for display in the browser. This is an *"API based"* approach to web development.
|
21 |
+
|
22 |
+
An alternative "hypermedia-based" approach, used by [HTMX](https://htmx.org/), simplifies things greatly by just returning HTML. FastHTML is designed to create hypermedia applications. Nearly all of the complexity of client-server programming vanishes when using this approach. When going to a page directly, the server will respond with a standard HTML web page:
|
23 |
+
|
24 |
+
```html
|
25 |
+
<html>
|
26 |
+
<head><title>FastHTML Page</title></head>
|
27 |
+
<body>
|
28 |
+
<p id="greet" hx-get="/change">Hello World!</p>
|
29 |
+
</body>
|
30 |
+
</html>
|
31 |
+
```
|
32 |
+
|
33 |
+
This can be generated using this FastHTML code:
|
34 |
+
|
35 |
+
```python
|
36 |
+
@rt('/')
|
37 |
+
def get(): return Div(P('Hello World!'), hx_get="/change")
|
38 |
+
```
|
39 |
+
|
40 |
+
When clicking on this link, the server will respond with an "*HTML partial*"---that is, just a snippet of HTML which will be inserted into the existing page:
|
41 |
+
|
42 |
+
```html
|
43 |
+
<p>Nice to be here!</p>
|
44 |
+
```
|
45 |
+
|
46 |
+
In this case, the returned element will replace the original `P` element (since that's the default behavior of HTMX). Our code to create this `/change` handler is:
|
47 |
+
|
48 |
+
```python
|
49 |
+
@rt('/change')
|
50 |
+
def get(): return P('Nice to be here!')
|
51 |
+
```
|
52 |
+
|
53 |
+
As we discussed in the [HTMX foundations](/foundation#sec2) section, HTMX removes four critical constraints of HTML. It allows any event on any DOM element to call any HTTP method on any path and place the response anywhere in the DOM. If you haven't written a hypermedia-based application before, then we strongly recommend reading the [Hypermedia Systems book](https://hypermedia.systems/). It explains how to build hypermedia applications using HTMX; the techniques you learn there will be directly applicable to FastHTML.
|
54 |
+
"""
|
55 |
+
|
56 |
+
s3 = """
|
57 |
+
[Uvicorn](https://www.uvicorn.org/) is, according to its website, "an ASGI web server". What does that even mean? As [we've discussed](/foundation#sec1), ASGI is a Python API that converts HTTP requests and responses into Python function calls. Uvicorn is a web server which a web browser can talk to, and it in turn talks to an ASGI application, returning its results back to the browser.
|
58 |
+
|
59 |
+
Most of the time you'll run your FastHTML application by simply adding one line of code to the end of your `main.py` file: `serve()`. When you do, a message will be printed letting you know that you now have a web server running on your computer, and if you click on the provided link you'll see your application running. If you look at the source code for `main.py`, you'll see that the line of code that actually runs the server is calling Uvicorn to do the work:
|
60 |
+
|
61 |
+
```python
|
62 |
+
uvicorn.run(f"{fname}:{app}", host=host, port=port, reload=reload)
|
63 |
+
```
|
64 |
+
|
65 |
+
When you deploy your application, you'll often use a service provider like Railway or Vercel. The one-click deployment we provide simply calls `python main.py` for you, and the provider is responsible for connecting the port that Uvicorn is running on to a public IP address. You can also run your application on a server such as a VPS, and either set the `PORT` environment variable to `80` to make it available directly, or add a frontend server like nginx or caddy to forward requests to the port that Uvicorn is running on.
|
66 |
+
"""
|
67 |
+
|
68 |
+
s4 = """
|
69 |
+
Because ASGI is such a simple API (it's literally a single Python function that takes three arguments), counter-intuively that actually makes it quite complex to use. It doesn't do that much for you, so there's quite a lot of boilerplate to write in order to create an ASGI application directly to use with Uvicorn.
|
70 |
+
|
71 |
+
[Starlette](https://www.starlette.io/) makes it much easier to create ASGI applications. It removes a lot of the boilerplate by providing a few simple abstractions, such as `Request`, `Response`, and `Route`. Reading the source code to Starlette is very informative, because you realise how little code is actually involved; it's just converting the minimal ASGI API into a more convenient set of classes and functions.
|
72 |
+
|
73 |
+
Starlette isn't at all opinionated about how you create your web application. Therefore, other libraries have stepped in to provide more specific functionality. For instance, [FastAPI](https://fastapi.tiangolo.com/) provides a framework built on top of Starlette that adds a lot of functionality for creating JSON APIs.
|
74 |
+
|
75 |
+
When Jeremy Howard decided he wanted to create a library to make it easier to build hypermedia applications, he used FastAPI as a role model. In fact, he went through each page of the FastAPI tutorial and attempted to replicate as much as he could, but for hypermedia applications instead of JSON APIs. The creator of FastAPI, Sebastián Ramírez, was extremely generous with his time and advice to Jeremy and helped to explain the thinking behind FastAPI's design.
|
76 |
+
|
77 |
+
The main `FastHTML` class is actually implemented as a subclass of Starlette's `Application` class. That means that you can use any middleware, routing, and other features that are compatible with Starlette. (However, you'll often find that FastHTML provides a more convenient way to do things.)
|
78 |
+
|
79 |
+
Although FastAPI and FastHTML are both built on top of Starlette, and FastHTML is inspired by FastAPI, there are plenty of differences, since they have different purposes. So if you've used FastAPI before, don't assume that everything will be identical!
|
80 |
+
"""
|
81 |
+
|
82 |
+
s5 = """
|
83 |
+
Out of the box, FastHTML provides support for SQLite, via the [Fastlite](https://answerdotai.github.io/fastlite/) library. SQLite is built in to Python, so you don't need to install anything extra. Because it uses a file to store and access the database directly from Python, it's extremely fast to access, and it's very easy to use. Fastlite provides an extremely simple API for database access, and lets you use standard Python builtin functionality such as dataclasses and dicts to read and write data.
|
84 |
+
|
85 |
+
Older versions of SQLite were not scalable, because they didn't support concurrent reads with writes. That limitation however was resolved some years ago through the addition of [write-ahead logging](https://www.sqlite.org/wal.html) (WAL), which FastHTML uses by default. With WAL and a modern multi-core computer and fast SSD, SQLite can support large and popular websites. Systems such as [Litestream](https://litestream.io/) can be used to replicate the database to a remote server.
|
86 |
+
|
87 |
+
Instead of Fastlite and SQLite, you can also use SQLModel, SQLAlchemy, Redis, or any other database server or data storage system. We (and the FastHTML community) will be continually adding more data storage options to FastHTML.
|
88 |
+
"""
|
about/vision.py
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from about.app import *
|
2 |
+
|
3 |
+
def page():
|
4 |
+
caption = "A minimal FastHTML app really is minimal."
|
5 |
+
fig = Figure(DivCentered(Img(src='assets/hello.png', alt='Web dev', cls='h-60'), Caption(caption, cls=TextT.lg+'pt-2')), cls='float-right m-2')
|
6 |
+
h2s = 'No compromise', 'Scaling down', 'Scaling up'
|
7 |
+
txts = [Markdown(s1), Div(fig, Markdown(s2)), Markdown(s3)]
|
8 |
+
secs = Sections(h2s, txts)
|
9 |
+
return BstPage(1, 'The FastHTML Vision', h2s, *secs)
|
10 |
+
|
11 |
+
s1 = """FastHTML is a general-purpose full-stack web programming system, in the same vein as Django, NextJS, and Ruby on Rails. The vision is to make it the easiest way to create quick prototypes, and **also** the easiest way to create scalable, powerful, rich applications.
|
12 |
+
|
13 |
+
It is important to have a system that can scale down, as well as up. That's because the best way to create a big complex application is to first create a small simple application, and then add to it in small steps. If we don't make it easy to create small, simple applications, then fewer people get started and fewer ideas get tried.
|
14 |
+
|
15 |
+
#### Two types of tools
|
16 |
+
|
17 |
+
Most software development platforms that make it easy to get started make it hard to scale in size and complexity. As a result, the development landscape gets segmented into "domain expert tools" like Streamlit, Gradio, and Wordpress, vs "serious programmer tools" like React and Django.
|
18 |
+
|
19 |
+
This means that picking one of those domain expert tools is a compromise: if what you're building is really successful, then at some point you'll have to throw it away and start again---possibly in a whole different programming language. The domain expert tools generally use very high-level abstractions specific to a single tool, which means learning a new set of foundations too. And the serious programmer tools add unnecessary complexity, slowing down both learning and development, and making maintenance harder.
|
20 |
+
"""
|
21 |
+
|
22 |
+
s2 = """
|
23 |
+
FastHTML scales down by picking the most widely used language for "getting stuff done": Python. And then it throws away everything that makes Python web programming complicated. No templates with quirky template languages. No multi-folder multi-file project skeletons. No complex type systems. No separate JavaScript frontend. No single-framework reactive abstractions. No build step. No tree shaking. No nonsense.
|
24 |
+
|
25 |
+
A FastHTML application can start as a single Python file. In fact, it can stay as a single Python file! You only need to break things into multiple files if _you_ decide that will help you build or maintain your software.
|
26 |
+
|
27 |
+
FastHTML applications don't require learning about and installing separate CSS and JavaScript frameworks. You can pip install a complete style library, such as a UI toolkit or template, and use it entirely from Python. We're building FastHTML libraries for DaisyUI, Bootstrap, Shoelace, Flowbite, and more. You can use these, or create your own, and customise them all with Python. You can pip install additional functionality provided by JavaScript and Python libraries, both controllable entirely from Python.
|
28 |
+
"""
|
29 |
+
|
30 |
+
s3 = """
|
31 |
+
FastHTML scales up by taking advantage of the foundations of the web. Because a FastHTML application directly uses HTTP, HTML, JavaScript, and CSS, there's nothing standing between your application and the power of the web. FastHTML comes with powerful yet simple tools for function-level and handler-level caching, async, threading, HTML partials, and much more.
|
32 |
+
|
33 |
+
The most important thing is that the fundamentals you started out with when you scaled down are identical to those you will use when you scale up! Same language, same libraries, same abstractions. As you continue on your web programming journey, all your new skills become more and more powerful!
|
34 |
+
"""
|
app.css
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* app.css */
|
2 |
+
@tailwind base;
|
3 |
+
@tailwind components;
|
4 |
+
@tailwind utilities;
|
5 |
+
|
assets/accordion-minus-icon.svg
ADDED
|
assets/accordion-plus-icon.svg
ADDED
|
assets/chat-bot.svg
ADDED
|
assets/fonts/geist-mono/GeistMonoVF.woff
ADDED
Binary file (67.9 kB). View file
|
|
assets/fonts/geist-mono/GeistMonoVF.woff2
ADDED
Binary file (58 kB). View file
|
|
assets/fonts/geist/Geist-Medium.woff
ADDED
Binary file (50.9 kB). View file
|
|
assets/fonts/geist/Geist-Medium.woff2
ADDED
Binary file (41 kB). View file
|
|
assets/fonts/geist/GeistVF.woff
ADDED
Binary file (66.3 kB). View file
|
|
assets/fonts/geist/GeistVF.woff2
ADDED
Binary file (56.8 kB). View file
|
|
assets/footer-path.svg
ADDED
|
assets/footer-shapes.svg
ADDED
|
assets/game-of-life.svg
ADDED
|
assets/github-mark/github-mark-white.png
ADDED
![]() |
assets/github-mark/github-mark-white.svg
ADDED
|
assets/github-mark/github-mark.png
ADDED
![]() |
assets/github-mark/github-mark.svg
ADDED
|
assets/hello.png
ADDED
![]() |
assets/hero-shapes.svg
ADDED
|
assets/htmx-meme.png
ADDED
![]() |
Git LFS Details
|
assets/icons/arrow-left.svg
ADDED
|
assets/icons/arrow-right.svg
ADDED
|
assets/icons/arrow-up-right-white.svg
ADDED
|
assets/icons/arrow-up-right.svg
ADDED
|
assets/icons/copy-icon.svg
ADDED
|
assets/icons/dot.svg
ADDED
|
assets/icons/minus-icon.svg
ADDED
|
assets/icons/plus-icon.svg
ADDED
|
assets/icons/stack/asgi_logo-color.svg
ADDED
|
assets/icons/stack/html-1.svg
ADDED
|
assets/icons/stack/html.svg
ADDED
|
assets/icons/stack/htmx.svg
ADDED
|
assets/icons/stack/http-domain-svgrepo-com.svg
ADDED
|
assets/icons/stack/hugging-face.svg
ADDED
|
assets/icons/stack/python-anywhere.svg
ADDED
|
assets/icons/stack/python.svg
ADDED
|