[MEGA TRICK] ⚡ User Scripts / Custom Actions

You thought hidden formulas or black magic were huge?
This is huge.

What if I told you —

Anything you can do manually in Coda can be turned into an action!


How about an action to truly reorder rows, without compromising on manual dragging?

ezgif.com-optimize

Or hiding and showing columns by a click of a button?

ezgif.com-optimize (1)

Or actually adding columns through an action, in those very few cases when you actually need it?

ezgif.com-optimize (2)

And all the other repetitive things that we all collectively spent hours doing manually — imagine we could finally automate most of these!

How?? :exploding_head:


I tapped into the frontend code of Coda — the ~400k lines of code that run the whole Coda editor.

I started exploring the document model — different modules and APIs within Coda’s frontend JS code responsible for pages, tables, formulas etc. The code is minified and obfuscated, and looks like an illegible mess. But I was so deprived of some Coda hacking lately, I eagerly took it up for a challenge :slight_smile:

To make it more accessible, I created a CodaTricks Chrome Extension. Right now it is but a proof-of-concept, but I have ambitions to develop it into a decent ‘Coda Dev Tools’ addon that would automate repetitive Coda building tasks, such as:

  • quickly generating databases (pages and tables)
  • bulk-editing column formats (e.g. setting all date/time columns to the same format in a single click)
  • quickly generating helper tables of various sorts
  • generating ‘flat’ pivot and transposed tables out of existing tables in a single click

and other things that take forever to do by point-and-click. Technically the extension could even perform true realtime 2-way editing provided that both docs are opened at the same time and the extension can sync the edits (although I still believe it’s a job better fit for Crossdoc Sync Tables Pro and/or webhooks)

The way the extension works with CFL is rather ingenious too.

At first I was thinking of a Pack-based setup (requiring a backend and a realtime messaging mechanism to deliver updates back to the browser) and I implemented that. But then I realized it had to be more straightforward. So I found a way to hook up to the CFL directly! The way this works is:

  • Anywhere in your action formula you make a call to a special ‘bogus’ pack like this:

    image

    It doesn’t have to be a single call on the formula — in fact it can be a 50-line long formula with many RunExtensionAction calls like this, and it will still run fine!

  • The extension intercepts calls to this particular pack and redirects them to the extension code, executing them immediately on the client side!

In the case the extension is not installed, the pack will simply show an error saying so. In fact that’s all that the pack does: it throws an error :slight_smile:

That’s because the code shall never reach it.

How to get it? :heart_eyes:


In a nutshell: fund it.

If you’re seriously interested in me developing this tool sooner rather than later, please DM me or write at paul@codatricks.com. If someone is eager to (collectively?) fund my R&D on this front I’ll be able to prioritize this project, otherwise I’ll have to put it on a pause for a while and work on things that can bring my family bread and butter in the shorter run.

Right now there’s not much but a proof of concept. It works though; the gifs above are real. If you’re interested in getting it already and you’re open to fund it, I won’t just share it with you but will also take requests for the features you want to automate first :wink:

When eventually the extension is out for GA, I’ll most likely make it a paid addon. My rationale for this is that it’s not an essential tool (in which case I’d gladly open it up) but a valuable extra that’s capable of drastically saving time and implementing new workflows. This addon can give commercial advantage to professionals, agencies, and companies, letting them build with Coda faster and making docs feel even more app-like to their users. I haven’t yet decided on how exactly but I’ll come up with some licensing for it.

Cheers! :blue_heart::yellow_heart:

27 Likes

This is pretty cool! But I’m not sure how useful it would be for enthusiasts when you can use existing keyboard shortcuts.

Adding a new column → Tab
Reordering rows → Alt+Up / Alt+Down

For making new pages and tables and such, custom templates always make things a breeze to reproduce!

Adding a new column programmatically through an action that generates a report to be copy-pasted in Excel — suddenly, not so easy :slight_smile: Besides, my code can create columns already with required names, data types, and even formulas.

Reordering rows with shortcuts — yes, but only if you’re editing the table directly. Imagine you want to instantly prioritize all the tasks from a project scattered around the table because the project became a priority. Would it be easier to fish out for each row and somehow drag it to the top, or do it all in a single click?

Custom templates only work as long as you’re happy with that template. In my case this is the norm:

And from project to project these are different.

I already can imagine the hours I could save by having these generated in a couple of text commands entered in a single place, then sent for processing to generate the whole structure for me.

2 Likes

This is super cool! One use case can I can see is that sometimes I need a helper column format or formula, but going ALL the way to the backend to run those takes for ever (for something that can run in the browser directly). Would it be possible to allow custom formulas to be run on client side?

1 Like

Goodness Gracious :star_struck: !

… I’m speechless :exploding_head: , so this is pretty much all I can find to say :sweat_smile: !

This goes to another whole level of Coda mastering :tophat: !

And of course, I hope we’ll see more of your CodaTricks Chrome Extension in a near future :raised_hands: :grin: !
(If not here, maybe a little bit on Patreon once in a while :innocent: )

This is cool but I would want to see some kind of alignment with Coda before I touched, never mind contributed to funding, something like this. I think I have far too much experience in the Google world where some cheese is moved (or deleted) seemingly for their own illogical satisfaction.

I wouldn’t want to hinge my productivity on functionality that is possibly/probably constantly in a cycle of reactive fixes to code changes, and start to leverage baked in functionality that I have access to but my team doesn’t, without an extension, leading to another layer of debugging.

Just sharing my honest thoughts, that no way detracts from the amazing work, or the countless other people that are in a position to leverage it.

1 Like

Got this concern several times today :slight_smile: so I’m going to reply it here.

I don’t think that the functionality I’m tapping into will significantly change any time soon, and here’s why:

  • First of all, I’m only hooking up into places that look like stable API.
    I.e., I’m not triggering any F.x(e, n, c) that would randomize on every weekly build — I’m triggering what looks like fairly mature and well-designed public interface:

    — i.e. I don’t think getCanvasGrids() or addColumn, or function parameters, or object fields will get changed in the coming few years.

  • And one of the reasons why I think they won’t get changed: Coda just recently rewrote their editor code when they introduced page columns. So I don’t see why they should still be unhappy with this part of the code and want to touch it any time soon.

  • Lastly, observing Coda for the last 4 years, I can’t see them putting time into changing any of it now. There have to be massive reasons to do that, on the brink of inability to make new features unless this code is rewritten. Which is very very unlikely. What I see Coda doing is doubling down on making new features, incorporating smaller fixes. The big topics will be AI and a better permission system (page-level sharing and stuff). But none of these will conceptually affect what, functions like addColumn? Pfft :slight_smile:

So the only way how I see this breaking is that Coda engineers decide to break it just in spite :slight_smile: But I haven’t been bad to them, so why would they do that? Remember we’re all still using the hidden formulas even in our production docs. Sure, Coda doesn’t endorse these, but they don’t deliberately break them either, and they only removed a few hidden formulas (mostly unused control-related ones like Slider() and Scale()) because they wouldn’t fit with some of the updates. And on the contrary, they made efforts to keep Button() alive, even though they could’ve just removed it. They broke it several times, yet still made efforts to restore their functionality.

There are several likes on this topic from Codans. Not sure if this comes along as approval though :slight_smile: but I just don’t see why they should oppose this. Not encourage, of course, because a 3rd party extension is out of their control (unlike packs where they can vouch for their security model; here they cannot make any claims and would rather not take any responsibility). It is up to you to take the responsibility and install an extension from a person you can or cannot trust (i.e. me.) This is basically a q-tip situation: on the package it says don’t clean your ears with it, but everyone is still doing it at their own risk.


I agree about the ‘the whole team needs an extension’ sentiment. That’s why I foremostly thought of this as a developer tools kind of thing — something with macros for the builder but not necessarily for the whole team. But if a certain team extensively uses Coda internally (which is, IMO, still the best way to use Coda — for the internal tooling), and the extension makes it possible to build some must-have workflow, then what is the problem if everyone just installs it?

6 Likes

This is an incredibly resourceful hack! You’re giving us a lot of ideas for the near future, especially as we’re focused on streamlining and making Coda simpler to use.

That said, Dan is spot on that this isn’t a realistic long-term solution. We’re constantly improving the way our underlying model works, which could break this extension without notice or cause poor user experience. Even worse it is very easy to break your document using these APIs incorrectly in ways that won’t always be obvious immediately. Our other concern is that issues generated by using this API have the potential to take up a lot of the teams time distracting from making the product better. Additionally this is unfortunately a violation of our terms of service.

This extension is a really cool experiment though, and if there are any functions of it that you’d fast-track if you had a magic wand, please let us know which and why.

The product team is listening, and are currently evaluating our streamline priorities for next quarter and beyond.

10 Likes

Thanks for the well-worded reply, @Jason_Tamulonis! Even though it’s basically a C&D, you didn’t make it sound harsh. I truly appreciate this!

I guess this is it then :slight_smile: I won’t be developing this extension. A bummer but TOS is TOS. Apologies from this curious soul that I didn’t check with the terms that prohibit any reverse engineering.

I still hope something good comes out of it. Maybe it reignites some conversations internally about what it is that power users actually want so much that they are ready to turn to 3rd party hacks. Psst, one of these could be more control over printing :wink:

12 Likes

If Paul’s ingenious find helps turn the product team’s focus even a tiny bit to the increasingly neglected power users, then it’s a win in my book.

@Jason_Tamulonis : You could make our lives a lot easier if there was more willingness to expose some of these internal API functions as new or improved CFL action formulas. This is a an easy win as you can tuck away these formulas in an Advanced section of the Coda | Formulas page. The newcomers’ experience won’t be changed a bit, but us power users will finally stop pulling out whatever few hairs we have left.

Here’s a list off the top of my head, just to get the conversation going:

  • Formally support button() formula, allowing us to write actions directly in the formula and not need intermediary table buttons to run.

  • SaveToPDF(…)

  • Change Notify(people, message) to become : Notify(people, message, link), because the current behaviour defaults to the source table which is rarely what you actually want your end user to see. You can restrict link to be only a relative url within the doc if you must.

  • SubscribeToComments(row, person)

  • UnsubscribeFromComments(row, person)

  • row.Comments attribute: a full json object would be great , but heck even just a simple comment count as a start would be a big step forward

  • GetColumn(tableName, columnName): programmatically retrieve a table or column object by their name can help a lot in some complex formulas.

  • ShowColumn(view, column, position?) and HideColumn(view, column)

  • ShowPage(page) and HidePage(page) - or even better: “Hide IF” as an optional formula we can write for each page.

Finally, not strictly-speaking formulas but related minor improvements that don’t require a lot of effort and would go a long in simplifying our lives:

12 Likes

Psst, _Subscribe() is actually there, I saw it when I was examining the code but haven’t yet tested it.

And super spot on on all other points. Also I remember there was a huge topic where Coda was collecting our wishes for ‘low-hanging fruit improvements’ — can’t find it but I remember lots of great ideas there.

P.S. Oh it’s this:

Tbh happy to scroll through that topic and see many pains addressed. A nice reminder that Coda is actually moving things forward at good pace :slightly_smiling_face:

4 Likes

Jumping in on this one.
Paul, great stuff, I’m always amazed how much energy you can put into this :wink:

Dear Jason & Coda team: please officially support _Button(). This is the one thing that differenciates a “dumb” document from a “smart” one. Oh, and I noticed you silently changed this week the way it behaves in grouped columns (now procedurally generated buttons are disabled in grouped column, that was naughty!). Also, it never sorted properly, such a shame, but with that and other issues I understand why it’s not yet supported. Still … that would change about everything.

Also, please please please, open some ways to let us create our own layouts. Navigating through data today in Coda = create a template page for a specific type of data (eg. “projects”), and then explain to all users that, no, they can’t directly link to a project, because first they need to click on a button to load the project in the page. I spent quite some time with template canvas column and dropped it because in the end it was unusable. There’s something missing there…

And finally, performance. To achieve “normal” results with the calculations I need, most of the time I need to create a secondary table that is automatically filled with filtered data from a much bigger table (Paul, mail me, you’ll write a trick out of this one :stuck_out_tongue:). All of this in order to not execute the calculations done in that small table in all the views of the original table. What about not evaluating columns that are not shown?

There a number of other things that could drastically change the way we do things with your wonderful software, please get in touch with your power user community!

3 Likes

@Paul_Danyliuk this is a stellar idea with long term benefits for heavy docs/systems in Coda.

I’d love to see you do a walk-through video of this code and what we can learn about Coda’s design as well!

Thanks, but that’s tucked far far away, I’m afraid. Coda basically asked me to not explore further for multiple reasons, the biggest of which is that it might have long term effects on how Coda itself is able to keep developing their product. I.e., ever since the hidden functions (like Button()) got exposed and widely used, Coda had to allocate resources it didn’t intend to, to keep those functional.

I briefly talked about this capability in my post-April Fools episode. You can explore the code yourself and make yourself scriptlets and bookmarklets to do what my extension would otherwise do. I guess this would also work as a sanity filter :slight_smile: if you’re capable of analyzing JS code to the point where you can make yourself those scriptlets, you’re much more likely to assume all responsibility over your hacking and not blame Coda or anyone else if your doc gets destroyed.

3 Likes