core VS anvil-runtime

Compare core vs anvil-runtime and see what are their differences.

core

WebSharper - Full-stack, functional, reactive web apps and microservices in F# and C# (by dotnet-websharper)

anvil-runtime

The runtime engine for hosting Anvil web apps (by anvil-works)
InfluxDB - Power Real-Time Data Analytics at Scale
Get real-time insights from all types of time series data with InfluxDB. Ingest, query, and analyze billions of data points in real-time with unbounded cardinality.
www.influxdata.com
featured
SaaSHub - Software Alternatives and Reviews
SaaSHub helps you find the best software and product alternatives
www.saashub.com
featured
core anvil-runtime
7 14
585 846
0.3% 1.4%
8.7 3.5
7 days ago 19 days ago
F# Clojure
Apache License 2.0 GNU General Public License v3.0 or later
The number of mentions indicates the total number of mentions that we've tracked plus the number of user suggested alternatives.
Stars - the number of stars that a project has on GitHub. Growth - month over month growth in stars.
Activity is a relative number indicating how actively a project is being developed. Recent commits have higher weight than older ones.
For example, an activity of 9.0 indicates that a project is amongst the top 10% of the most actively developed projects that we are tracking.

core

Posts with mentions or reviews of core. We have used some of these posts to build our list of alternatives and similar projects. The last one was on 2023-11-22.
  • Show HN: New Version of MyOwnDB
    2 projects | news.ycombinator.com | 22 Nov 2023
  • The combined power of F# and C#
    10 projects | news.ycombinator.com | 7 Aug 2023
  • Launch HN: Pynecone (YC W23) – Web Apps in Pure Python
    25 projects | news.ycombinator.com | 13 Mar 2023
    Websharper[1] lets you develop web apps all in F# or C#. Its reactive HTML layer is particularly useful.

    1: https://websharper.com/

  • What do people use for REST APIs and Web Development now?
    9 projects | /r/fsharp | 31 Jan 2023
    I was using websharper in the past, but is that still a good F# centric method of web development, or are there better frameworks now?
  • AOT
    3 projects | /r/fsharp | 16 Jan 2023
    With F# you can compile your app as an html5 app.
  • Functional, reactive Point of sale with WebSharper
    1 project | dev.to | 26 Dec 2022
    A WebSharper application may be developed and deployed using Linux or Windows.
  • Functional, reactive Point of sale with F# and WebSharper
    3 projects | dev.to | 26 Dec 2022
    updates the two reactive Var that, guess what? will be updated automatically in any form bounded to it. I used two variables on purpose to demonstrate a couple of ways they can be used. The ```amountDueVarTxt``` is bounded in the ```RegisteredItemsForm``` . It updates the amount due text on the fly, after you register or remove an item. Look for ```textView AmountDueRv``` `. ```fsharp let UpdateAmountDueVar () = ... let total = transactionItemsVar.Value |> List.map (fun v -> PriceToFloat v.TotaPrice ) // convert List to List |> List.sumBy id // id is shorthand to (fun v -> v) amountDueVar.Value <- total amountDueVarTxt.Value <- $"{total}" ``` A Form have it's logic separated from the rendering. The CartForm is used in two different endpoints by two distinct render functions. It uses Form.YieldVar instead of Yield to use a reactive Var. On ```|> Form.Render```, itemsInCart refers to the transactionItemsVar bound in CartForm function The lambda function passed on this binding install the function that will be used to render whenever the transactionItemsVar is updated. ```fsharp itemsInCart.View |> Doc.BindView (fun items -> ``` This is the "remove registered item from sale" event handler. The ```items``` refers to ```transactionItemsVar``` contents. ```fsharp on.click (fun _ _ -> itemsInCart.Update(fun items -> items |> List.filter (fun i -> i <> item)) ``` ### Registered items form ![alt text](https://audisoft.com.br/diego/fsadvent2022-websharper/pos-registered-items-form.png "alt text") ```fsharp let CartForm () = // simplified way for a form with a single yield // Use YieldVar when using a shared reactive Var. Form.YieldVar transactionItemsVar |> Form.WithSubmit let RegisteredItemsForm () = let AmountDueRv = amountDueVarTxt.View |> View.Map (fun x -> $"Amount due is {x}") div [] [ div [] [ // You could use textView amountDueVarTxt.View, but amountDueRv shows you how to manipulate the View textView AmountDueRv ] CartForm () |> Form.Render (fun itemsInCart _ -> itemsInCart.View |> Doc.BindView (fun items -> items |> List.map (fun item -> div [attr.``class`` "item"] [ text $"UID: {GuidHead (TransactionItemUid.value item.Uid)} Product {item.Description} Price {item.Price} Quantity {item.Quantity} TotalPrice {item.TotaPrice}" button [ on.click (fun _ _ -> itemsInCart.Update(fun items -> items |> List.filter (fun i -> i <> item)) UpdateAmountDueVar () ) ] [text "Remove"] ] ) |> Doc.Concat ) ) ] ``` When you hit the "Checkout" Button, the event handler defined on the ```TransitionArea().StartPayment()``` is triggered Here is a refresher: ```fsharp let TransactionArea (routerLocation:Var) = Templates.MainTemplate.TransactionArea() .RegisterItems(RegisterItemForm()) .RegisteredItems(RegisteredItemsForm()) .StartPayment(fun _ -> routerLocation.Set SPA.Checkout ) .Doc() ``` ## Checkout EndPoint ![alt text](https://audisoft.com.br/diego/fsadvent2022-websharper/pos-checkout.png "alt text") This form does not provide any functionality. I used it to demonstrate the EndPoint/Form transition, and a how a Form can be rendered using a different function. ```fsharp routerLocation.View.Doc(function ... | SPA.Checkout -> Doc.Concat [ h1 [] [text $"SPA checkout"] // link equivalent to the back button // a [attr.href (router.Link (EndPoint.SPA SPA.PointOfSale))] [text "Back"] // renders a button that, when clicked, change the browser to the PointOfSale EndPoint ("/") button [ on.click (fun _ _ -> routerLocation.Set SPA.PointOfSale ) ] [text "Back"] // renders a button that, when clicked, change the browser to the PointOfSale EndPoint ("/payment") button [ on.click (fun _ _ -> routerLocation.Set SPA.Payment ) ] [text "Proceed to Payment"] ItemsToCheckoutForm() ] ``` Here, ```CartForm``` is rendered in a different way. The ```items``` refers to ```transactionItemsVar``` contents. ```fsharp let ItemsToCheckoutForm () = CartForm () |> Form.Render (fun itemsInCart _ -> // gotcha: if you pass this code without the outer div [] [], only the last will be rendered, and no error wil be thrown. div [] [ div [] [ label [] [text "transactionUid: "]; label [] [text transactionUidVar.Value] ] itemsInCart.View |> Doc.BindView (fun items -> items |> List.map (fun item -> div [attr.``class`` "item"] [ text $"Product {item.Description} Price {item.Price} TotalPrice {item.TotaPrice}" ] ) |> Doc.Concat ) ] ) ``` ## Payment EndPoint ![alt text](https://audisoft.com.br/diego/fsadvent2022-websharper/pos-payment.png "alt text") Dynamic forms: It may seem overwhelmingly difficult, but once you got the grasp of it, they're a lot of fun to work with. One more EndPoints to our collection. ```PaymentForm``` third's argument is a sequence of one ```CreditCardFormFields```. It's used to initialize the Multiple Credit Cards form. Had I passed two items, there would be two "Pay with Credit Card" lines. ```routerLocation``` is responsible to tell the browser to change to an EndPoint. As the code show, it handles this SPA EndPoints. ```fsharp type CreditCardFormFields = { Type : CreditCardType Flag : string Value : CheckedInput } let PointOfSaleMain () = StartSaleTransaction () let router = Router.Infer() let routerLocation = router |> Router.Slice (function | SPA spa -> Some spa | _ -> None) EndPoint.SPA |> Router.Install SPA.PointOfSale routerLocation.View.Doc(function | SPA.PointOfSale -> ... | SPA.Checkout -> ... | SPA.Payment -> Doc.Concat [ h1 [] [text $"SPA payment"] PaymentForm (routerLocation, SPA.Checkout, [|{ Type=Debit; Flag= "MasterCard"; Value= CheckedInput.Make(0.0) }|]) ] ``` The Payment Form arguments are: ```backLocation``` is used in the Back button event handler. The user is able to add as many Credit Cars as needed thanks to ```Form.Many```. Let's break down this line: ```<*> Form.Many creditCards { Type=Debit; Flag="Visa"; Value=CheckedInput.Make(0.0) } CreditCardPaymentForm``` ```crediCards``` The initial collection of values. Check out the ```| SPA.Payment``` EndPoint for a refresher. ```{ Type=Debit; Flag="Visa"; Value=CheckedInput.Make(0.0) }``` The value of type CreditCardFormFields with which the new sub-form should be initialized when the user adds a new Credit Card. ```CreditCardPaymentForm``` Is the form that will be rendered when ```creditCards.Render (fun ops cardType cardFlag cardValue ->``` ```fsharp let PaymentForm (routerLocation:Var, backLocation, creditCards:seq) = Form.Return (fun moneyAmount creditCards -> moneyAmount, creditCards) <*> (Form.Yield (CheckedInput.Make amountDueVar.Value) |> Validation.Is (ValidateCheckedFloatPositive) "Money must be positive number" |> Validation.Is (ValidateCheckedFloatDecimalPlaces 2) "Money must have up to two decimal places" ) <*> Form.Many creditCards { Type=Debit; Flag="Visa"; Value=CheckedInput.Make(0.0) } CreditCardPaymentForm |> Form.WithSubmit |> Form.Run (fun (moneyAmount, creditCards) -> let moneyPayment:list = if (MoneyFromCheckedInput moneyAmount) > 0m then [PaymentMethod.Money (MoneyFromCheckedInput moneyAmount)] else [] let creditCardPayments = creditCards |> Seq.toList |> List.map (fun x -> PaymentMethod.CreditCard {Type = x.Type; Flag = x.Flag; TransactionId = Guid.NewGuid().ToString(); Value = MoneyFromCheckedInput x.Value}) let payments = List.concat [ moneyPayment creditCardPayments ] |> Seq.toList let transaction:SaleTransaction = {Uid = (SaleTransactionUid.create (Guid.Parse(transactionUidVar.Value))); Datetime=System.DateTime.Now; Items = transactionItemsVar.Value; Payments = payments} async { let! res = Server.PerformSaleTransaction transaction // JS.Alert($"Transaction performed: {SaleTransactionUid.value res} %A{transaction}") routerLocation.Set (SPA.Receipt transactionUidVar.Value) } |> Async.StartImmediate ) |> Form.Render (fun paymentMethodAmount creditCards submit-> div [] [ button [ on.click (fun _ _ -> routerLocation.Set backLocation ) ] [text "Back"] Doc.Button "End transaction" [] submit.Trigger div [] [ label [] [text "transactionUid: "]; label [] [text transactionUidVar.Value] ] div [] [ label [] [text "Money"] Doc.InputType.Float [attr.``step`` "0.01"; attr.``min`` "0"] paymentMethodAmount ShowErrorsFor (submit.View.Through paymentMethodAmount) ] div [] [ creditCards.Render (fun ops cardType cardFlag cardValue -> div [] [ RenderCreditCardPaymentForm cardType cardFlag cardValue Doc.Button "Delete" [] ops.Delete ShowErrorsFor (submit.View.Through cardValue) ] ) Doc.Button "Add Payment Form" [] creditCards.Add ] ] ) ``` While other forms use reactive Var to share state, this one use EndPoint Argument. One of the benefits of this is that you can share the url. EndPoints be of GET or POST in case you're wondering. ## Receipt EndPoint ![alt text](https://audisoft.com.br/diego/fsadvent2022-websharper/pos-receipt.png "alt text") The Receipt EndPoint definition: ```Receipt of uid: string``` defines that this EndPoint have an argument of type string. The URL will have this format: "https://localhost:5001/spa/point-of-sale/receipt/string-containing-the-sale-uid" ```fsharp type SPA = ... | [] Receipt of saleUid: string ``` The Receipt EndPoint Handler: ```fsharp let PointOfSaleMain () = ... routerLocation.View.Doc(function ... | SPA.Receipt saleUid -> Doc.Concat [ h1 [] [text $"SPA receipt"] ReceiptForm (saleUid, routerLocation) ] ) ``` Finally e have some Server action! Brace yourself and prepare to write a bit of JavaScript and some DTOs. ### Just kidding. I know that wasn't funny. But writing client/server applications in WebSharper is! It takes care of it all. You write FSharp all the way down. The serialization is all done for you. You just need to call an RPC basically the same way you would call a local function. In ```Server.SaleReceipt``` I chose to let the rendering work to the server, and passing a simple list of strings to the client. The cash flow Report, on the other hand, the server will deliver a complex type. Client side: ```fsharp let ReceiptForm (uid:string, routerLocation:Var) = div [] [ div [] [ button [ on.click (fun _ _ -> StartSaleTransaction () routerLocation.Set SPA.PointOfSale ) ] [text "New"] ] async { let currentTransactionUid = (SaleTransactionUid.create (Guid.Parse(uid))) let! res = Server.SaleReceipt currentTransactionUid let render line = tr [] [ td [] [text line ] ] return Templates.MainTemplate.ReportTable().ReportRows( List.map render res |> Doc.Concat ).Doc() } |> Client.Doc.Async ] ``` Server side: ```fsharp [] let SaleReceipt (saleUid:SaleTransactionUid.T)= async { return match saleTransactions.TryGetValue(saleUid) with | true, sale -> RenderSaleTransactionReceiptTxt sale | _ -> [$"UID not found: {saleUid.ToString()}"] } ``` ## Cash flow report ![alt text](https://audisoft.com.br/diego/fsadvent2022-websharper/pos-cashflow-report.png "alt text") We exited the SPA realm and are back to the client/server. The cash flow report EndPoint is defined here: ```fsharp [] let Main = Application.MultiPage (fun ctx endpoint -> match endpoint with | EndPoint.Home -> HomePage ctx | EndPoint.About -> AboutPage ctx | EndPoint.CashFlow -> CashFlowReportPage ctx | EndPoint.SPA _ -> PointOfSale ctx // the _ means that all routes e.g. "/spa/*" will be handed to PointOfSale function. The SPA takes care it's own routes. ) ``` Here is the cash flow report handler. It is marked to run on the client. Don't worry, we're not back to SPA again. This EndPoint is intended to open up the cash flow report page. The user clicks on the Report button. It then calls the server asynchronously, and receives a list of `````` Finally, the rendering occurs on the client side, thanks to that ```client (``` ```fsharp let CashFlowReportPage ctx = let title = $"Cash Flow Report" Templating.Main ctx EndPoint.CashFlow title [ div [] [client (Client.RetrieveCashFlowReport())] ] ``` Client side: ```fsharp let RetrieveCashFlowReport () = Templates.MainTemplate.ReportForm() .OnSend(fun e -> async { let! res = Server.GenerateCashFlowReport System.DateTime.Now let RenderSaleTransaction (sale:SaleTransaction) = tr [] [ td [] [text $"{sale.Datetime.ToShortDateString()} - {sale.Datetime.ToShortTimeString()}"] td [] [text $"Transaction UID: {SaleTransactionUid.value sale.Uid}"] td [] [text $"%A{sale.Items}"] td [] [text $"%A{sale.Payments}"] ] Templates.MainTemplate.ReportTable().ReportRows( List.map RenderSaleTransaction res |> Doc.Concat ).Doc() |> Client.Doc.RunById "report-container" } |> Async.StartImmediate ) .Doc() ``` Server side: ```fsharp [] let GenerateCashFlowReport (date:DateTime): Async = async { // returns complex data on purpose to demonstrate that you can pass complex data and treat it on the client. return GetSalesTransactions() } ``` The types that are being sent over the RPC call: ```fsharp type TransactionItem = { Uid: TransactionItemUid.T Sku: string Description: string Price: decimal TotaPrice: decimal // Unit of Measure that accepts ( times ) Quantity: decimal } type SaleTransaction = { Uid: SaleTransactionUid.T Datetime: System.DateTime Items: TransactionItem list Payments: PaymentMethod list } ``` ```fsharp (SaleTransactionUid.create (Guid.Parse("cca24efe-fffa-4a7f-86fc-38ea41016926"))), { Uid = SaleTransactionUid.create (Guid.Parse("cca24efe-ffff-4a7f-86fc-38ea41016926")) Datetime = DateTime.Now Items = [ { Uid = TransactionItemUid.create (Guid.Parse("3f57720d-4b16-4911-88ed-e6d266c72e4a")) Sku = "1" Description = "Bolt" Price = 1.5m TotaPrice = 3.0m Quantity = 2m } { Uid = TransactionItemUid.create (Guid.Parse("1fde5c26-3f00-4916-a5f4-3456bd0b93f2")) Sku = "2" Description = "Blue Wire" Price = 2.0m TotaPrice = 3m Quantity = 1.5m } ] Payments = [ PaymentMethodsDomain.Money 13m ] } ``` ## Resources - Introduction to F# web programming with WebSharper by Adam Granicz: - [![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/CeMq9Fg-HME/0.jpg)](https://www.youtube.com/watch?v=CeMq9Fg-HME) - https://github.com/dotnet-websharper/forms/blob/master/docs/Introduction.md ## How to proceed from here? I intend to grow this project so, keep an eye on this article and the github project. ### What if I need some library that are not supported? - If you mean javascript libraries: - https://developers.websharper.com/docs/v4.x/fs/wig - also, take a look into some existing lib bindings on https://github.com/dotnet-websharper - For .net libraries: - https://developers.websharper.com/docs/v4.x/fs/proxying - https://www.yvesdennels.com/posts/websharper-proxy-project/ - https://github.com/dotnet-websharper/core/issues/1067 Fear not! Thsi issue is already closed! - proxima versão: banco de dados sql no servidor e armazenamento local no browser - comunicação com o servidr via rpc transparente, sem necessidade de DTO You can also ping me on Twitter [Diego Pego](https://twitter.com/sergey_tihon)

anvil-runtime

Posts with mentions or reviews of anvil-runtime. We have used some of these posts to build our list of alternatives and similar projects. The last one was on 2023-03-13.
  • Launch HN: Pynecone (YC W23) – Web Apps in Pure Python
    25 projects | news.ycombinator.com | 13 Mar 2023
    Founder here. Self hosting is a thing - just "pip install anvil-app-server"!

    https://anvil.works/open-source

  • The New Anvil Editor: Build Python Web Apps with Even More Power and Flexibility
    1 project | /r/Python | 31 Jan 2023
    To be fair, it has a free tier which gives you most of Anvil's features and lets you build unlimited apps. There's also the open-source app server if you want to host your apps yourself and work around the paid tier's DB limits: https://github.com/anvil-works/anvil-runtime
  • Pynecone - a full-stack framework for building and deploying web apps.
    2 projects | /r/Python | 14 Dec 2022
    The runtime is open source: https://github.com/anvil-works/anvil-runtime
  • Ask HN: Hunting for a Framework
    23 projects | news.ycombinator.com | 4 Dec 2022
    https://github.com/anvil-works/anvil-runtime#using-the-stand...

    The code is GNU AFFERO GENERAL PUBLIC LICENSE Version 3.

  • New Anvil tutorial, 150+ pages, with 220 screenshots, and 25 app examples
    1 project | /r/Python | 3 Jul 2022
    anvil server
  • New? READ ME FIRST!
    1 project | /r/AnvilWorks | 2 May 2022
    Anvil is a platform for building web apps with nothing but Python - no HTML, CSS or JavaScript required. Anvil also comes with lots of built-in features like one-click deployment, databases, user authentication, email and the open-source app server.
  • Is JavaScript necessary for python web developer.
    4 projects | /r/learnpython | 22 Oct 2021
    anvil.works
  • The new (beta) Anvil editor has been released
    2 projects | /r/Python | 16 Sep 2021
  • Ask HN: Who is hiring? (June 2021)
    17 projects | news.ycombinator.com | 1 Jun 2021
    Anvil | Software Developer | Cambridge, UK | On-site/Semi-Remote | Full-time or Part-time | https://anvil.works/jobs

    Anvil | Junior Software Developer | Cambridge, UK | On-site/Semi-Remote | Full-time or Part-time | https://anvil.works/jobs

    Anvil | Developer Advocate | Cambridge, UK | On-site/Semi-Remote | Full-time or Part-time | https://anvil.works/jobs

    Help us fix web development at Anvil (https://anvil.works)!

    Web development is way too hard – Javascript, HTML, CSS, SQL, and frameworks coming out of your ears. So we built Anvil: a simpler way for anyone to build full-stack web apps, entirely in Python. Anvil is a web framework; it’s an online code editor; it’s a GUI builder; and it’s a hosting platform. And you’ll be helping us with all of it.

    We're looking for:

    SOFTWARE DEVELOPERS:

    Build the platform that's fixing web development for everyone. You’ll be working on the Anvil editor (that’s the development environment, code editor, drag-and-drop designer, version control, and so on) and the Anvil runtime (that’s the Python-to-JS compiler, UI toolkit, database, integrations, and the hosting engine that makes it so easy to deploy).

    Our stack is mostly Javascript, Clojure and Python (in descending order of line count). We don’t need you to be an expert in all of these already, and for the junior role we don't need any. Otherwise, we’ll want to see evidence that you can hit the ground running with at least one of them – or that you’re a great all-rounder who won’t have a problem with any of them.

    Much (or most) of your work will be open source: https://anvil.works/open-source

    DEVELOPER ADVOCATES:

    We need developers with great communication skills, to show people how to build awesome things with Anvil. You’ll be writing how-to guides, blog posts and tutorials, building example apps, presenting Anvil at conferences (when those resume), and helping our users – from individual developers to huge tech companies – build their applications. And then you’ll help us work out how to improve Anvil for them.

    It's rewarding work – developers love being introduced to Anvil (our stand is always crowded[0] at conferences!). Plus, there are all the advantages of an early-stage startup: lots of autonomy, and huge impact.

    We're bootstrapped and profitable, with customers ranging from tiny startups to household names. Find out more: https://anvil.works/jobs

  • How to host Anvil web app with the uplink
    1 project | /r/AnvilWorks | 16 Apr 2021
    Are you using the `--uplink-key` flag or `--client-uplink-key` flag when running your app with the app server? Anvil App Server - advanced config

What are some alternatives?

When comparing core and anvil-runtime you can also consider the following projects:

Leaflet.markercluster - Marker Clustering plugin for Leaflet

brython - Brython (Browser Python) is an implementation of Python 3 running in the browser

remi - Python REMote Interface library. Platform independent. In about 100 Kbytes, perfect for your diet.

appsmith - Platform to build admin panels, internal tools, and dashboards. Integrates with 25+ databases and any API.

django-unicorn - The magical reactive component framework for Django ✨

Grafana - The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.

tauri - Build smaller, faster, and more secure desktop applications with a web frontend.

Metabase - The simplest, fastest way to get business intelligence and analytics to everyone in your company :yum:

SharpLab - .NET language playground

language-ext - C# functional language extensions - a base class library for functional programming

cli - Official Command Line Interface for the IPinfo API (IP geolocation and other types of IP data)

InfluxDB - Power Real-Time Data Analytics at Scale
Get real-time insights from all types of time series data with InfluxDB. Ingest, query, and analyze billions of data points in real-time with unbounded cardinality.
www.influxdata.com
featured
SaaSHub - Software Alternatives and Reviews
SaaSHub helps you find the best software and product alternatives
www.saashub.com
featured