Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Beyond OpenAPI (antonz.org)
168 points by nalgeon on Sept 11, 2023 | hide | past | favorite | 54 comments


I would prefer reading the OpenAPI spec for an API - which is in a standardized format and has easily searchable/skip-able sections, like schemas, endpoints, etc. An interactive tutorial that you mostly read from beginning to end is not convenient for devs - we want to find things within a few seconds of hitting the docs page.


The point of the article is not to _replace_ the spec. The point of the "four-document types" model is that different document types fit different use-cases.


Yeah that looks great for a blog post .. . Good luck writing and maintaining that for a real project in the real world


It's all about the tooling. I wrote my own for iommi where the html output of some code gets saved in a defined place, and then the finished documentation page embeds that html in an iframe. It's not only WAY WAY easier to maintain than a bunch of screenshots, but I found a ton of issues with the documentation after I made it so it runs all the examples and I can look at the output.

example: https://docs.iommi.rocks/en/latest/cookbook_forms.html

corresponding documentation/tests: https://github.com/iommirocks/iommi/blob/master/docs/test_do...

my evil hack to get this working: https://github.com/iommirocks/iommi/blob/master/make_doc_rst... and https://github.com/iommirocks/iommi/blob/master/iommi/docs.p...


That's brilliant! https://github.com/scientific-python/pytest-doctestplus seems to be similar working in the opposite direction, using the documentation source as the single location for test code. I like your approach better and wish there was more support for that pattern more generally!


I started with that approach actually. It turned untenable after a while. It's just much nicer to have the documentation just a part of your normal test suite without any preprocessing. That also means you get coverage in the normal way too.


Many projects maintain different document types in their docs. Of the top of my head: NestJS.



> According to the popular classification, there are four document types: tutorials, how-to guides, technical references, and explanations.

This is Diátaxis: https://diataxis.fr/


The "HTTP" format proposed in the article is the same we use with Hurl [1], an Open Source HTTP CLI based on plain text.

  POST http://httpbingo.org/anything/chat
  content-type: application/json
  
  {
      "message": "Hello!"
  }
We extend it a bit to add checks on response, and add request chaining, but it's basically HTTP 1.x as this article shows it. A lot of others tools have the same idea, with minor differences:

- Hurl (I'm one of the maintainer) https://hurl.dev

- HTTP Client https://www.jetbrains.com/help/idea/http-client-in-product-c...

- httpYac https://httpyac.github.io

- restclient.el https://github.com/pashky/restclient.el

- REST Client https://github.com/Huachao/vscode-restclient

- verb https://github.com/federicotdn/verb

And many more...

Worth noting, other tools have taken the YAML route (like Step CI https://stepci.com), JavaScript (k6 https://k6.io/docs/using-k6/http-requests/)... I'm biased of course, I've a tiny preference for the simple plain text format.

And of course, there are also GUI application (Postman, Insomnia, RecipeUI amon others)

[1]: https://hurl.dev


One thing that trips me up when I see this 4 quadrant structure for documentation is when to go with a tutorial and when to go with a how-to. Curious how others delineate between those.


Tutorial takes you from an exact point A to an exact point B. Guide is much "looser" and just describes the general steps to get something done, without making any type of guarantee of being able to take you exactly from A to B. Mostly out of acknowledgment that the real-world is messy and everyone is going to have a slightly different system. Tutorial is for people starting from scratch or who want a gentle hands-on intro to your thing, guide is for people who are doing messy integration work with existing systems. It's not a perfect delineator but it'll get you most of the way there...


The way I think about it is:

  - Tutorial: learn how the system works
  - How-to: recipes for common use-cases


Tutorial is a Getting Started, with no specific goal other than to serve as a general hands-on introduction. It does not assume any prior experience with the tool/product.

How-to(s) is a cookbook, targeting specific use cases, and may not particularly cater to novices.


In diataxis, a tutorial serves your education and a how-to guide serves your work.

Following this standard, a tutorial may contain a simpler or more contrived example; it may contain things you'd never do in production.


OpenAPI is more than just documentation generation, it’s also used for runtime time validation and codegen for both client and server stubs. I’d argue that what’s discussed in this article can complement OpenAPI but doesn’t replace it.


I was hopeful starting this article. Because I do think we need something better than OpenAPI for self-documenting APIs...

The idea of an interactive tutorial is great, but as others have mentioned, likely very difficult to maintain over time.


I built this because I had the same idea: https://github.com/hitchdev/hitchstory

If your specification is self rewriting, can be tested and can be used to generate docs then maintenance costs plummet.


What this misses is the curl response format.

Long time ago at Klarna we used this tool: https://github.com/for-GET/katt Here's an example: https://github.com/for-GET/katt/blob/master/doc/example-http...


OpenAPI has great affordances for providing examples along with pertinent documentation sections. Many OpenAPI UIs provide ways to execute those examples or other interactive ways to populate and try requests. These could surely be better honed for the how-to guide style of documentation! But I think that’s probably a better place to start for people who are starting at, and looking to go beyond, what OpenAPI currently provides.


What kind of sandbox are you using here for running Python/etc code on your server?


I'm not associated with the site, but using their bash one as an example it appears to just be docker <https://codapi.org/bash/#cat%20%2Fproc%2F1%2Fmounts>

I've always heard "containerization is not a security boundary" but I am not red-team enough to provide specific counter-examples


If you do want a stronger security boundary, you can do that without using cgroups and other kinds of namespaces (aside from chroot) pretty easily using something like `firejail` -- that's what I do for this demo [0] (all the software is in /opt/appfs, if you want to try stuff out -- you can browse it here [1])

[0] https://rkeene.dev/js-repl/?arg=bash

[1] https://browser.appfs.net/


codapi is slick and this tutorial provides good insight into how HTTP APIs work.

OpenAPI is wack though. It doesn't provide any guarantees that the API does what it is supposed to do. I think in most cases it is a distraction and developer time would be better spent understanding HTTP and implementing and testing the endpoints.

I'm curious if others have had good experiences consuming OpenAPI as intended, i.e. you get handed a new API and you generate the code interfaces and plug them directly into your business logic without writing any extra wrappers. Or do you end up writing lots of wrapping code anyways?


Would be very interesting to see the same documentation principles applied to other thing (not API or developer docs).


I mean, there is nothing stopping people from using the [Diataxis Framework](https://diataxis.fr/) for any sort of documentation - it just doesn't have as great a foothold outside our sphere.

I was a bit surprised it or Divio (where it was created) announced when they talked about the four types of documentation. I would love to see it make its way into information systems curriculum, as it's a quite useful mental model.


I go back and forth on the usefulness of Diataxis and related information frameworks—Mark Baker (of EPPO fame) has an interesting series[1] about the DITA equivalent of task, concept, and reference:

> If there is a problem with DITA, then, it is not that it lacks a theory of information design. The problem is that many people actually believe that it does have a theory of information design, and that that theory can be summed up in three words: concept, task, and reference. But a theory for breaking content up into pieces is not a theory of information design unless it also includes a theory of how the pieces should go back together.

> There is, of course, nothing preventing DITA users from having or developing a sound theory about how the pieces should go back together. The problem is not that DITA does not provide one. The problem is that writers often do not see that they need one. They believe, or act as if they believed, that the devolution into concept, task, and reference is a complete information design. The result, generally, is Frankenbooks.

Which I think is a salient point, and less an indictment on the "three/four types" model than a reminder that you shouldn't just throw together a bunch of type-delineated docs for their on sake; the individual pieces have to make a functional whole.

So I'm certainly in favor of supplementing traditional OpenAPI-esque reference docs with more conceptual or task-based docs... provided that they're actually designed to complement each other.

[1] https://everypageispageone.com/2012/07/28/the-tyranny-of-the...


this thread reminds me of another thread [1] several days ago about web component using WASI runtime (runno.dev), which may have overlapping usecases with this project. worth looking

[1] https://news.ycombinator.com/item?id=37287339


I think people may be missing the core point of this article. As often happens on Hacker News (and the internet in general), people are responding more to the post title than the actual content.

Anton has built a new thing, https://codapi.org/ - which provides a web component that makes it easy to embed interactive code snippets for HTTP APIs, Python code and more directly in pages of documentation.

This article demonstrates this new technology in the context of the https://diataxis.fr/ documentation framework, which recommends going beyond just straight API reference documentation and ensuring you cover tutorials, how-to guides and explanations as well.

I think this is really cool.


I read the full post. It meanders quite a bit. Would have been more effective to just announce the new tool without the provocative title or the detour into HTTP basics. Sending this comment in the spirit of friendly, respectful, constructive criticism.


I hate that my brain has now reprogrammed this to mean "ChatGPT" (OpenAI) to me. I legit opened the link and expected to read about "Beyond LLMs" or somebody leaving work at OpenAI.

But HTTP APIs with types are pretty cool too. Carry on, please!


At my job we recently implemented OpenAPI and it's been painful hearing people call it OpenAI on zoom calls but it makes sense, they're so darn close.


Or use jsonrpc and your documentation is ie typescript definition file, a list of function signatures.


I don't think that's even remotely true, based on https://www.jsonrpc.org/specification#examples


Just like author simplifies HTTP communication, you can simplify:

  --> {"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1}
  
  <-- {"jsonrpc": "2.0", "result": 19, "id": 1}
...example to:

  subtract(42, 23) -> 19


How do you express the schema for the jsonrpc endpoints being served? What are valid methods and parameters?


Subset of flow would work the best.


but that's not widely implemented, while OpenAPI is

there are reasons people left flow, why do you think it is a candidate for best? Simply claiming so does nothing to further anyone's understanding


If flow adoption in js bothers you, just replace it with "subset of ts" - it'd look almost the same (it's better when it comes to things like declaring exact vs inexact object types or having cosmetic shorthand for optional type).

The bottom line is that description is terse and natural. Ie. it can be generated directly from your code and code can be generated out of it.

Instead of describing protocol (headers, status codes, http verbs, redirects, urls, params, cookies, content types etc) - you describe function signatures - the very thing that already has first class support in your programming language. An api feels like a library.

Because it uses json as serialization the data types you need to cover are very small - there are no interfaces, classes, inheritance, functions (you can't provide or return objects that define functions) - everything is pretty much composed out of type aliases and unions on 6 basic json types.

Instead of programming in yaml to describe http protocol you work with functions having json on input and output - something that is natural to your host programming language already.

Think graphql but without its nonsense restrictions on query (unions on input are fine!) or cherry picking output (calling convention that is foreign to programming languages and requires embedding dsl/dedicated query engines).

Think more like header file for remote service constraint to list of functions and notifications using json as data type.


dude, the point was that flow/ts anything out of your preferred ecosystem...

it's not going to work as a general solution because

1. nobody wants the bs out of that "ecosystem" (applies to any language specific ecosystem)

2. it's not implemented in all the other languages and therefore not portable. Who's going to write all the parsers for your "solution"?

If all you write is JS/TS, you should really try out some other languages so you get a better perspective.

This is exactly why we have standards like OpenAPI... your solution would be a single ecosystem solution.

How would one put things like authentication, examples, and response codes in their public schema under your "solution"?


GraphQL has similar type system and it is portable.


yaml & json are more portable, with codecs available in many stdlibs. You can decode directly into language types in most cases

CUE is the future I hope for


Yes, cue is awesome.


You might like this thing I'm working on then

https://youtu.be/XNBqBWO4y08


most things are not written in typescript

OpenAPI, being JSON or Yaml, is portable


JsonRPC is also portable.

Whole spec fits single page.


the JsonRPC comes from the typescript in GP, so the process of schema generation from types is not portable to other languages...


Typescript is mentioned as an example of function signature format.

As it needs to describe only valid json values, the whole language needs to operate on 6 underlying data types only - it's really not that complicated to come up with minimal readable format that's easy to parse.

It doesn't matter much if it reassembles ts, flow, ocaml or haskell - the point is it can fit into single screen, serve as documentation and be parseable for verification/codegen etc.


Let's step back, and remember you posed JsonRPC as an alternative to OpenAPI or something like that?

There is a whole lot more to express than...

> 6 underlying data types only

... when automating REST documentation from some underlying source of truth

It seems this one-page spec is woefully insufficient to express the concepts that OpenAPI can. Hence why no one here thinks this is a viable alternative


OpenAPI is cluttered with protocol specifics that are irrelevant to something that is native to your host language (function signatures). Think of it as header file for api that is highly constrained (functions, notifications and json data types only - no classes, instances, polymorphism, no way to encode callbacks or returning functions etc. just basic algebra on json types - type aliases and unions).

Imagine api like this:

  // @endpoint wss://localhost:3000/api/v1

  notification heartbeat = {
    timestamp: number
  }

  type User = {
    id: string,
    email: Email
    type: "normal" | "admin"
  }

  type AuthError = {
    message: string,
    code: -123
  }

  type NotLoggedInError = {
    message: string,
    code: -124
  }

  // Logs you in.
  //
  // @throws AuthError
  login(username: string, password): User

  // Adds two numbers.
  // @throws NotLoggedInError
  add(x: number, y: number): number

  // Logs you out.
  // @throws NotLoggedInError
  logout(): null
It's terse, straight forward and maps to your host programming language naturally.


While I like it, it also has shortcomings. For example, while gpt-4-32k is listed in https://platform.openai.com/docs/models/gpt-4, it is not available for accounts that have access to its 8k-token variant, gpt-4-32k.


This is about OpenAPI, not OpenAI.


My bad!


this made my day




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: