AnswerDotAI / fasthtml

The fastest way to create an HTML app
https://fastht.ml/
Apache License 2.0
5.08k stars 206 forks source link

[FEATURE] Ability to use frontend components created using vercel v0 with fasthtml #367

Closed bevenky closed 3 weeks ago

bevenky commented 3 weeks ago

Vercel V0 allows creating frontend components super quickly which is essentially a react component frontend. Python frameworks like reflex allow using react components. Would there be a way to do that with Fasthtml to enable a large and vast ecosystem of app front ends being created quickly vs having to redo all that from scratch.

pydanny commented 3 weeks ago

~Adding React is out of scope for FastHTML itself. However, if you created a wrappers or utilities for FastHTML that allowed it to work with Vercel VO that would be very interesting to see!~ 😄

pydanny commented 3 weeks ago

Actually, Vercel VO supports traditional HTML exports. You can therefore take any component and use https://h2f.answer.ai and convert it to FT components. Check out what I did here using Vercel VO!


Style(':root{--background:0 0% 100%;--foreground:240 10% 3.9%;--card:0 0% 100%;--card-foreground:240 10% 3.9%;--popover:0 0% 100%;--popover-foreground:240 10% 3.9%;--primary:240 5.9% 10%;--primary-foreground:0 0% 98%;--secondary:240 4.8% 95.9%;--secondary-foreground:240 5.9% 10%;--muted:240 4.8% 95.9%;--muted-foreground:240 3.8% 45%;--accent:240 4.8% 95.9%;--accent-foreground:240 5.9% 10%;--destructive:0 72% 51%;--destructive-foreground:0 0% 98%;--border:240 5.9% 90%;--input:240 5.9% 90%;--ring:240 5.9% 10%;--chart-1:173 58% 39%;--chart-2:12 76% 61%;--chart-3:197 37% 24%;--chart-4:43 74% 66%;--chart-5:27 87% 67%;--radius:0.5rem;}')

Style("h1, h2, h3, h4, h5, h6 { font-family: 'Inter', sans-serif; --font-sans-serif: 'Inter'; }")

Style("body { font-family: 'Inter', sans-serif; --font-sans-serif: 'Inter'; }")

Div(
    Div(
        Div(
            H1('Acme Cargo Trailer', cls='text-2xl font-bold'),
            Div(
                Span('Serial #:', cls='text-sm text-muted-foreground'),
                Span('CT-2345', cls='font-medium'),
                cls='flex items-center gap-2'
            ),
            Div(
                Span('VIN:', cls='text-sm text-muted-foreground'),
                Span('1ABCD2345EFG67890', cls='font-medium'),
                cls='flex items-center gap-2'
            ),
            Div(
                Span('Daily Price:', cls='text-sm text-muted-foreground'),
                Span('$50', cls='font-medium'),
                cls='flex items-center gap-2'
            ),
            cls='grid gap-2'
        ),
        Div(
            H2('Description', cls='text-lg font-medium'),
            P('The Acme Cargo Trailer is a versatile and durable trailer perfect for hauling a wide variety of cargo. With\r\n        a sturdy steel frame and a spacious interior, this trailer is built to handle your toughest hauling needs.', cls='text-sm text-muted-foreground'),
            cls='grid gap-2'
        ),
        Div(
            H2('Manufacturer', cls='text-lg font-medium'),
            Div(
                Span('Name:', cls='text-sm text-muted-foreground'),
                Span('Acme Trailers Inc.', cls='font-medium'),
                cls='flex items-center gap-2'
            ),
            Div(
                Span('Model:', cls='text-sm text-muted-foreground'),
                Span('CT-2345', cls='font-medium'),
                cls='flex items-center gap-2'
            ),
            Div(
                Span('Model Year:', cls='text-sm text-muted-foreground'),
                Span('2023', cls='font-medium'),
                cls='flex items-center gap-2'
            ),
            cls='grid gap-2'
        ),
        cls='grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3'
    ),
    Div(
        H2('Dimensions', cls='text-lg font-medium'),
        Div(
            Div(
                Span('Length:', cls='text-sm text-muted-foreground'),
                Span('16 ft', cls='font-medium'),
                cls='flex items-center gap-2'
            ),
            Div(
                Span('Width:', cls='text-sm text-muted-foreground'),
                Span('7 ft', cls='font-medium'),
                cls='flex items-center gap-2'
            ),
            Div(
                Span('Height:', cls='text-sm text-muted-foreground'),
                Span('7 ft', cls='font-medium'),
                cls='flex items-center gap-2'
            ),
            Div(
                Span('Weight:', cls='text-sm text-muted-foreground'),
                Span('2,500 lbs', cls='font-medium'),
                cls='flex items-center gap-2'
            ),
            cls='grid grid-cols-2 gap-2 md:grid-cols-4'
        ),
        cls='grid gap-4'
    ),
    Div(
        H2('Specifications', cls='text-lg font-medium'),
        Div(
            Div(
                Span('GVWR:', cls='text-sm text-muted-foreground'),
                Span('5,000 lbs', cls='font-medium'),
                cls='flex items-center gap-2'
            ),
            Div(
                Span('Purchase Date:', cls='text-sm text-muted-foreground'),
                Span('2023-04-15', cls='font-medium'),
                cls='flex items-center gap-2'
            ),
            Div(
                Span('Purchase Price:', cls='text-sm text-muted-foreground'),
                Span('$3,500', cls='font-medium'),
                cls='flex items-center gap-2'
            ),
            Div(
                Span('Reference ID:', cls='text-sm text-muted-foreground'),
                Span('TR-2345', cls='font-medium'),
                cls='flex items-center gap-2'
            ),
            cls='grid grid-cols-2 gap-2 md:grid-cols-4'
        ),
        cls='grid gap-4'
    ),
    Div(
        H2('Additional Information', cls='text-lg font-medium'),
        Div(
            Div(
                Span('License Plate:', cls='text-sm text-muted-foreground'),
                Span('ABC 1234', cls='font-medium'),
                cls='flex items-center gap-2'
            ),
            Div(
                Span('Addons:', cls='text-sm text-muted-foreground'),
                Span('Ramp, Spare Tire', cls='font-medium'),
                cls='flex items-center gap-2'
            ),
            cls='grid grid-cols-2 gap-2 md:grid-cols-4'
        ),
        cls='grid gap-4'
    ),
    Div(
        H2('Media', cls='text-lg font-medium'),
        Div(
            Img(src='/placeholder.svg', alt='Trailer Image 1', width='300', height='200', style='aspect-ratio:300/200;object-fit:cover', cls='rounded-lg object-cover'),
            Img(src='/placeholder.svg', alt='Trailer Image 2', width='300', height='200', style='aspect-ratio:300/200;object-fit:cover', cls='rounded-lg object-cover'),
            Img(src='/placeholder.svg', alt='Trailer Image 3', width='300', height='200', style='aspect-ratio:300/200;object-fit:cover', cls='rounded-lg object-cover'),
            Img(src='/placeholder.svg', alt='Trailer Image 4', width='300', height='200', style='aspect-ratio:300/200;object-fit:cover', cls='rounded-lg object-cover'),
            cls='grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4'
        ),
        cls='grid gap-4'
    ),
    cls='grid gap-8 p-4 md:p-8 lg:p-12'
)