[HN Gopher] Show HN: Floro - Visual Version Control
___________________________________________________________________
Show HN: Floro - Visual Version Control
Hi HN, we're building Floro (https://floro.io), an open-source,
offline-first visual version control system that allows you to
merge and diff graphical content. Demo video here:
https://www.youtube.com/watch?v=5fjixBNKUbM. We were a YC W21
startup (Cheqout) that originally worked on restaurant tech. We
ended up pivoting after the pandemic and decided to build Floro due
to a lot of problems we encountered while working on Cheqout. We
struggled a lot with string content and dark mode, especially when
it came to static assets. We were a cross-platform product, so
everything was an SVG. What we wanted was a way for our designer
(who cannot use a command line) to be able to check static assets
into our codebase and be able to manage our color themes without us
having to manually edit the assets ourselves. We also faced a lot
of problems with i18n and keeping translations up to date. Both
problems felt kind of similar, they're both essentially just key
value solutions that require people who aren't software engineers
to edit them. This led us down a path of searching for a way to
incorporate something like Dropbox into git. We didn't want a
content management system, we wanted something where we could diff
and merge our static assets without requiring the user to know how
to fix conflicts in plain-text or binary. We wanted a way to
reference something like a snapshot of a tar of our static assets
so we could idempotently rebuild our application and add type-
safety to our assets. Eventually, we found a trick to diff and
merge a certain type of tree structure that fit these problems
well. After a bit more experimenting around, we figured out how we
could write an interface to make UIs that could be diffed and
display merge conflicts. To show what visual version control could
be applied to, we decided to build four plugins (applications that
can be diffed and merged in Floro). 1. Text - This plugin is
basically a replacement for i18n strings. It supports rich text,
typed variable interpolations, conditional logic (for things like
pluralization), links, ML translations, and a plethora of other
features. It's also sort of an IDE/TMS for translators & copy
editors. 2. Icons - This plugin allows you to recolor an SVG asset
so that all the colors are consistent with your color palette. You
can automatically generate dark mode (and any other themed)
versions of your assets, as well as versions of your asset that
change with state (e.g. hovered, etc.) by applying themes to the
asset. 3. Themes - This plugin allows you to create themes from
your color palette. 4. Palette - This plugin allows you to define
colors and shades that can be consumed by other plugins or used in
your code for managing your app's colors. Since Floro is an
offline-first desktop application we realized that we could allow
users to test their local content out by building a browser
extension that would allow them to override the state of their
production websites and apps with the local content from floro.
Floro essentially creates a localhost environment out of production
apps, which allows non-technical users to treat content similarly
to how engineers manage code. The demo video (shown above) does a
good job of showing how this works. We also have a demo of how this
works for mobile apps
(https://www.youtube.com/watch?v=Om-k08GDoZ4). We are fully open
source (MIT licensed). We intend to monetize with consulting and
private hosting. Users are more than welcome to self-host and build
their own distributions of the desktop application and all the
plugins we have created. This is really our launch (anticipate
some bugs but nothing serious, restarting the app(s) takes care of
most things). We've now built four applications with Floro
(including our website) and feel confident that it's ready. We've
spent 18 months getting here, we hope some of you like it! Thanks!
Jamie & Jacqueline
Author : jsunderland323
Score : 53 points
Date : 2024-04-01 15:01 UTC (1 days ago)
| ActionHank wrote:
| I don't know if I am your target audience, but it seems like it's
| doing a whole lot more than most people would need.
|
| I feel like there is huge value in version control that supports
| various binaries with custom diff support. Perforce, git-lfs,
| etc. offer binary version control, but not custom and useful diff
| tooling per binary type. Kaleidoscope, Beyond Compare, etc. offer
| some improved diff tooling, but not for a wide variety of file
| types.
|
| That seems like it would be the essence of a product like this.
|
| I suspect that many of the people who influence the adoption of
| VCS are likely deeply technical and will likely actively avoid
| products that are opinionated on the target output when using the
| VCS.
| jsunderland323 wrote:
| I think you're probably correct that you likely aren't the
| target audience here. Version control is a loaded term. This
| would be a terrible replacement for perforce or anything for
| diffing something like a CAD file.
|
| The real focus of the system is for things that are better
| managed by people who aren't engineers but end up interfacing
| with code very tightly. The idea was to focus on the peripheral
| functions that come up in UI engineering and enable e.g.
| translators, copy editors, and designers to essentially commit
| to a codebase without having to understand git or know how to
| handle plaint text merge conflicts.
|
| > I suspect that many of the people who influence the adoption
| of VCS are likely deeply technical and will likely actively
| avoid products that are opinionated on the target output when
| using the VCS.
|
| I totally agree. You can modify the output to your hearts
| desire. This was a big part of our design.
| IshKebab wrote:
| Git _does_ support custom diffing algorithms and tools.
| jsunderland323 wrote:
| It does but it can't support cascading states. I kind of
| explain this at the bottom of this page
| https://floro.io/technical-overview-part-2
| jFriedensreich wrote:
| i did not understand what a cascading merge is after
| reading this twice. if you have a git threeway merge and a
| merge tool that can parse and merge all three filestates
| what exactly would your solution solve that the git one
| cannot?
| jsunderland323 wrote:
| I'll try to contextualize it in the case of something
| like AST merging so it's more familiar.
|
| Imagine you have file A and file B. In one change someone
| adds some code that imports something from file B into
| file A. In another change someone deletes file B without
| touching file A. That will result in a valid three-way
| merge. However, your compiler will complain and you will
| have to update file A to remove the references to file B.
| This is okay because you can edit the plain-text and fix
| the inconsistency. This doesn't work for things where you
| can't really hop in and manually fix the conflict.
|
| You could definitely create a tool that understand the
| AST and knows how to remove stale references. If you add
| in the requirement that there cannot be inconsistent
| states at any commit you've essentially derived an
| entirely new merging system. Could you build this on top
| of git? Sure, it's a plain-text system, you could build
| anything on top it. Is there any gain if the point of the
| system is to disallow manual conflict resolution and
| enforce consistent state? I don't think so but maybe I'm
| not seeing something.
| IshKebab wrote:
| But can't you have a custom merge driver for 3 way merges
| too? So that when you try to merge the changes it _does_
| complain?
|
| The advantage of building this on top of Git is fairly
| obvious: you get to use all the existing Git tooling, and
| you can use Git for other files in the repo that don't
| need special merge drivers.
| jsunderland323 wrote:
| > But can't you have a custom merge driver for 3 way
| merges too? So that when you try to merge the changes it
| does complain?
|
| You kind of could, at least for diffing. This is what
| difftastic does https://difftastic.wilfred.me.uk/.
| Merging is really ambiguous in what the intended behavior
| of a removed reference is in AST. Do you delete or
| nullify or something else? How does that affect other
| upstream references? I'm not sure you'll ever find a
| satisfying answer there but floro is constrained to
| static assets, which are a bit more predictable.
|
| > The advantage of building this on top of Git is fairly
| obvious: you get to use all the existing Git tooling, and
| you can use Git for other files in the repo that don't
| need special merge drivers.
|
| So I think there is some confusion here in how this
| interfaces with code and I'm sorry I didn't think to
| explain this first. With floro you have a file in your
| git repository that points to a sha from floro to
| generate your assets from.
|
| Here's an example https://github.com/florophore/floro-
| react-native-demo/blob/m...
|
| I think of it sort of like having a package.json and a
| lockfile. You don't check your dependencies into git
| because odds are you don't want to deal with merge
| conflicts in third party dependencies, just the
| package.json and lockfile. Similarly you wouldn't want to
| deal with the conflicts of floro in a git repo. So you do
| still you get to use all the existing Git tooling with
| respect to your codebase.
|
| The problem really is that git would allow for
| inconsistent states, which is fine for programmers but
| tough for anyone who doesn't know how to resolve the
| inconsistencies.
| jFriedensreich wrote:
| i dont see how that solves the issue you describe. if i
| delete an icon from the floro repo and my code in git
| imports this icon and renders it. floro cannot do
| anything to help there. the only consistency floro can
| enforce is if i use a color from a color set in an icon
| in floro and remove the color, it could complain i have
| to first change the color in the icon. but this sound
| like a really minor inconvencience vs not being able to
| do everything with git. or is there a concrete example
| where this would matter?
| jFriedensreich wrote:
| another point is that enforcing invariancts is not the
| task of the repo but of the checks / review system. it is
| very simple to enforce your described cross file
| constraint with a ci check and prevent merging. and floro
| could also not automatically solve the conflict of
| inconsistency as concurrent deletion and modification of
| any data is fundamentally undecidable without knowledge
| of the application logic and business domain and
| sometimes even human user intent. this is the problem
| most conflict "free" replicated datatypes have, most
| inherently lose data in at least these situations unless
| they keep conflict markers for all these situations
| around until an application solves them at some point in
| the future.
| jsunderland323 wrote:
| HN isn't letting me nest further. I'll do my best to
| answer these in the order I saw them posted.
|
| 1) "i dont see how that solves the issue you describe..."
|
| >the only consistency floro can enforce is if i use a
| color from a color set in an icon in floro and remove the
| color, it could complain i have to first change the color
| in the icon.
|
| So it does do this actually, which is super helpful. You
| can also check for this in CI and choose to fail a build
| because of the inconsistency. It's also part of the REST
| api too so you can decide if you want to make a live
| update to something via webhook based on if
| inconsistencies are present. (see
| https://floro.io/docs/dev/api Invalidity Map Endpoint).
|
| > if i delete an icon from the floro repo and my code in
| git imports this icon and renders it. floro cannot do
| anything to help there.
|
| Actually, you kind of can. You have to do some static
| analysis that gets checked into git but you can use this
| to determine what is safe and unsafe to update in prod. I
| could delete the tagline of the webiste and modify some
| other piece of copy and it would not delete the tagline
| but would modify the other copy in production. This is
| really up to the codebase in how they want to handle live
| updates.
|
| Here is an example of the webhook I do this in
| https://github.com/florophore/floro-
| mono/blob/main/packages/....
|
| But I do not do this for icons because I don't really
| want to live update icons in production.
|
| > but this sound like a really minor inconvencience vs
| not being able to do everything with git. or is there a
| concrete example where this would matter?
|
| So the above point is where this really matters a lot and
| is not about minor convenience. Being able to make live
| updates to a site without having to worry about breaking
| the production app and going through a buid-pipeline is
| by far my favorite feature of the whole thing. Could you
| do this with a headless CMS? Yes/Kind of, it really
| depends how complicated the asset is and how much you
| think type-safety really benefits you. There's also a
| whole host of CI/CD problems you run into then.
|
| > i dont see how that solves the issue you describe.
|
| I don't know if I have much else to add aside from the
| above comments. If inconsistencies introduced to the
| repository prevent a translator or designer from using
| the tool until the inconsistency is resolved that's a
| really bad experience. I think if you can use plain-text
| for something, definitely do it. But it's a pretty
| unpleasant experience for people like translators and
| non-technical folks.
|
| 2) "another point is that enforcing invariancts..."
|
| > another point is that enforcing invariancts is not the
| task of the repo but of the checks / review system. it is
| very simple to enforce your described cross file
| constraint with a ci check and prevent merging.
|
| So yes and no. If we were to analogize this entirely to
| code I would 100% agree with you, but for simpler
| structured data types you can definitely describe
| cascading behaviors that could be anticipated and should
| be enforced by the version control system, which maybe
| gets at the heart of why I think it would not be useful
| to build this on top of git.
|
| > and floro could also not automatically solve the
| conflict of inconsistency as concurrent deletion and
| modification of any data is fundamentally undecidable
| without knowledge of the application logic and business
| domain and sometimes even human user intent.
|
| It does not use auto-merge, unlike CRDTs it does use user
| intent if a conflict occurs. It chooses between two
| sequences of potential acceptable merge results (yours
| and theirs). I do really describe this in depth in the
| page I posted above, I'm sorry if it's not clear.
|
| You are correct that you don't get the granularity of
| picking some changes from yours vs theirs. You have to
| accept the entire state of either yours or theirs for a
| conflict before you can make revisions to resolve the
| conflict but you can manually resolve the consistency
| issues of the merge conflict in the plugin UIs, I
| actually show this very briefly at the end of our demo
| video.
| jFriedensreich wrote:
| thanks for your answers, really appreciated! ok so now i
| am really confused. on one hand you are talking about
| live updating websites without rebuild and providing the
| assets as an api, but then you commit the root hash of
| the floro repo into the git repo. so your production
| website loads whatever latest asset version from a floro
| api endpoint and my repo state is not a snapshot anymore
| of what what the page will look like on production? in
| that case why do the repo connection at all? isnt floro
| then much more a cms / custom database with versioning
| for translations/ assets/ colors than an extension of the
| repo side?
| jsunderland323 wrote:
| Now we're getting into the depths! This is a great
| question/point.
|
| > so your production website loads whatever latest asset
| version from a floro api endpoint and my repo state is
| not a snapshot anymore of what what the page will look
| like on production?
|
| Yes! But it's your choice to decide which plugins to do
| this with. You can break your build environment without
| breaking your production environment, which is really
| important because you want CI to catch something like a
| missing icon or a bad invocation of a pluralized string
| but you also don't want to block being able to update
| safe production changes like correcting a minor-typo.
| Breaking a build because an assets was deleted is easy to
| resolve for engineers.
|
| > in that case why do the repo connection at all? isnt
| floro then much more a cms / custom database with
| versioning for translations/ assets/ colors than an
| extension of the repo side?
|
| I think it would be very intellectually dishonest to say
| otherwise (with some minor caveats) but you could say the
| same about code too. Isn't github just a CMS for code?
|
| The thing about the snapshot that the code imports at
| compile time is it allows you to determine the structure
| of how the application consumes assets in static
| analysis. This is what allows you to determine what is
| safe to update live and what isn't. Could you do this by
| snapshotting a database and performing static analysis on
| your imports? Yes, you certainly could but that's not
| what CMSs do at all ...and SQL is really not good for
| merging things. Headless CMSs are built for really
| redundant data-structures because that's what marketers
| need and they nearly all suffer from the same CI/CD
| issues for that reason. Why do we mostly check i18n
| string into git and not use CMSs for string content?
|
| Ignoring all the other parts of version control we're
| taking for granted here, branching, peer reviews,
| merging, etc. The big benefit of it all working offline
| is that you can let the non-engineers, who either lack
| access control to git or could not technically manage
| setting up the code base, test out content changes
| locally on your production site or app. CMSs can do with
| this with iframes but again, it's really for blogging
| content/static content and not i18n. The other area where
| offline testing shines for people who aren't engineers is
| being able to test out content changes on mobile devices
| over the local-network. That's not really a thing CMS
| systems can do at all.
| account_created wrote:
| I was building a very similar solution two years back after
| seeing the struggle of managing the assets for the design teams.
| Mostly people were using google-drive to share/collect/update the
| assets which was not very systematic. I envision my solution to
| fix this with the similar insiparation of VCS and proper
| integration with existing design tools, but after some time
| realized that the solution was not good enough and it quickly
| became too technical for the design folks.
| jsunderland323 wrote:
| I mean this is the struggle. And props to you for building
| that. It's an ugly problem.
|
| I actually do think (and have personal evidence now to believe)
| that most functions adjacent to engineering can learn
| distributed version control. Once you start using it, you
| really don't want to go back.
|
| We've internally adopted trunk based development for our assets
| and it gets rid of 99% of the confusing parts of version
| control to not use branches (I know blasphemy). My designer
| just pulls and pushes on the main branch and I do the same --
| we've had very very few merge conflicts and none that couldn't
| be resolved in 30 seconds.
|
| I feel silly now having spent so much time on branching as a
| feature. It makes a lot of sense for plain text and code but it
| probably doesn't matter that much (for small teams) for visual
| things. Merging has proven to be invaluable to us though.
| jbverschoor wrote:
| Every clone in git is a branch. People like to enterprisify
| things, resulting in miserable people, wasted time, and money
| flowing into consulting firms.
|
| Remember, git replaced tarballs
| jsunderland323 wrote:
| Exactly! This was actually Linus' point when he was
| explaining git to companies still on cvs. "You're all
| already using branches anyway".
|
| I think if you're in a low-trust enterprise environment,
| branches kind of make sense because you get the additional
| scrutiny of code-review and merges occur on a centralized
| server but if you're in a four person team where you trust
| everyone just use the main branch and resolve locally.
|
| > Remember, git replaced tarballs
|
| I would refine that to say 3-way-merging replaced tarballs
| but yes!
| vouaobrasil wrote:
| Hey this is cool. I think there could be a place for a new kind
| of version control. I'll test it out.
| jsunderland323 wrote:
| Thank you! I'll put my email in my bio if you want any help at
| all, It's a heavy installation (but straightforward once it's
| setup).
| kissgyorgy wrote:
| Great idea, but it seems more complicated than simply adding
| files to a git repo.
| jsunderland323 wrote:
| It for sure is more complicated than adding files to a git
| repo. You are 100% right and I wouldn't dispute that for even a
| second. I'm not exactly advocating this for solo-projects
| unless you are already sure you want to do something like
| internationalize your project.
|
| There are many problems where plain-text falls apart for even
| engineers though or there's some benefit to editing something
| through a UI or WYSIWYG rather than plain-text. If you're cool
| with markdown and editing SVG files manually -- do it.
|
| The problem being addressed is when you have team members who
| need to do things that requires some level of type-safety but
| they either don't have the technical background to work with
| something like git or it would be non-sensical to resolve the
| conflicts in plain-text. The idea here is for designers to
| basically take control of things like icons and theming and for
| translators to take control of i18n. Their work is state that
| can be used to generate a type-safe API for engineers to
| consume those assets.
| amir734jj wrote:
| One of struggles we had at Microsoft is versioning power bi pbix
| files. Someone publishes a change and the old version is gone
| unless they saved it somewhere else.
| Pwntastic wrote:
| Why does the main product page attempt to connect to a localhost
| port? It looks like it's trying to hit a socket.io port, but that
| seems pretty unnecessary for a landing page?
| jsunderland323 wrote:
| It's testing to see if the daemon is running from the electron
| app. It uses the connection to the browser for things like sign
| in and verification and for being able to redirect links into
| the electron app.
|
| https://github.com/florophore/floro-mono/blob/main/packages/...
|
| The reason it's happening on the landing page is because we use
| floro for editing the site and testing our changes offline
| first before pushing.
| password4321 wrote:
| Plastic SCM was acquired by Unity so I guess there's precedent.
| ramesh31 wrote:
| Love the idea but please pay for a UX professional. This UI just
| screams "we have $component_library, why would we ever need a
| designer?".
| jsunderland323 wrote:
| we do =D ... She's still getting her chops though.
|
| We'll probably end up using webflow to market to designers. We
| were going for hackerish today.
|
| We actually didn't use any component library. We designed all
| of our own components in-house
| ugh123 wrote:
| In this youtube video example
| https://www.youtube.com/watch?v=5fjixBNKUbM
|
| you demonstrate adding the new icon to the page and then
| modifying it with a hover alternative color. But the rest of the
| compare/diff/review workflow only focuses on the change between
| non-highlighted -> highlighted. To me, the important part is the
| addition of the icon to the page, and as a reviewer it would be
| of upmost importance to see the visual diff of the _page_ before
| and after, rather than just an icon and it 's hover alternative.
| jsunderland323 wrote:
| By page do you mean like your live website with the changes?
|
| I've thought about this too and I think down the line the plan
| is to be able to attach screenshots to merge requests. However,
| as a reviewer you can also pull down the changes and test them
| against your production site locally. So you can alter between
| the main branch and the feature branch and compare the
| differences like that. The benefit of this over a screenshot is
| it lets you actually get to see something like the hover effect
| in action.
| ugh123 wrote:
| In the demo they clearly have a wysiwyg app allowing them to
| drag in the icon, so the project is already set up for "live
| demo". If i'm a non-technical reviewer, like a designer
| (their target market I believe), I shouldn't be expected to
| pull down changes and test locally (unless that part can be
| automated and made super easy to do without fuss).
|
| Figma kind of already does this (visual diff) with some of
| their tools for designers, although i'm not sure how well
| that can be integrated into a full fledged web-app who's
| changes and reviews could be shared by designers _and_
| engineers.
| jsunderland323 wrote:
| > I shouldn't be expected to pull down changes and test
| locally (unless that part can be automated and made super
| easy to do without fuss).
|
| It's super easy and there's no fuss. You literally just
| switch branches. It's really easy to think the experience
| is analogous to code but it's not really. There's not a
| complex IDE setup or any complex local environment setup --
| so it really is like just pull the branch open your
| browser, navigate to your website and test the changes.
___________________________________________________________________
(page generated 2024-04-02 23:01 UTC)