diff --git a/sx/content/pages.py b/sx/content/pages.py index c8bf0cb..7662878 100644 --- a/sx/content/pages.py +++ b/sx/content/pages.py @@ -72,6 +72,7 @@ ESSAYS_NAV = [ ("On-Demand CSS", "/essays/on-demand-css"), ("Client Reactivity", "/essays/client-reactivity"), ("SX Native", "/essays/sx-native"), + ("The SX Manifesto", "/essays/sx-manifesto"), ] MAIN_NAV = [ diff --git a/sx/sxc/sx_components.py b/sx/sxc/sx_components.py index 622f885..133e3c3 100644 --- a/sx/sxc/sx_components.py +++ b/sx/sxc/sx_components.py @@ -1876,6 +1876,7 @@ def _essay_content_sx(slug: str) -> str: "on-demand-css": _essay_on_demand_css, "client-reactivity": _essay_client_reactivity, "sx-native": _essay_sx_native, + "sx-manifesto": _essay_sx_manifesto, } return builders.get(slug, _essay_sx_sucks)() @@ -2360,6 +2361,295 @@ def _essay_sx_native() -> str: ) +def _essay_sx_manifesto() -> str: + p = '(p :class "text-stone-600"' + em = '(span :class "italic"' + return ( + '(~doc-page :title "The SX Manifesto"' + ' (p :class "text-stone-500 text-sm italic mb-8"' + ' "After " (a :href "https://www.marxists.org/archive/marx/works/1848/communist-manifesto/"' + ' :class "text-violet-600 hover:underline" "Marx & Engels") ", loosely")' + + # --- I. A spectre is haunting the web --- + + ' (~doc-section :title "I. A spectre is haunting the web" :id "spectre"' + f' {p}' + ' "A spectre is haunting the web — the spectre of s-expressions. ' + 'All the powers of the old web have entered into a holy alliance to exorcise this spectre: ' + 'Google and Meta, webpack and Vercel, Stack Overflow moderators and DevRel influencers.")' + f' {p}' + ' "Where is the rendering paradigm that has not been decried as ' + 'a step backward by its opponents? Where is the framework that has not ' + 'hurled back the branding reproach of \\\"not production-ready\\\" ' + 'against the more advanced paradigms, ' + 'as well as against its reactionary adversaries?")' + f' {p}' + ' "Two things result from this fact:")' + ' (ol :class "space-y-2 text-stone-600 mt-2 list-decimal list-inside"' + ' (li "S-expressions are already acknowledged by all web powers to be themselves a power.")' + ' (li "It is high time that s-expressions should openly, in the face of the whole world, ' + 'publish their views, their aims, their tendencies, ' + 'and meet this nursery tale of the Spectre of SX ' + 'with a manifesto of the paradigm itself.")))' + + # --- II. Bourgeois and Proletarians --- + + ' (~doc-section :title "II. HTML, JavaScript, and CSS" :id "bourgeois"' + f' {p}' + ' "The history of all hitherto existing web development ' + 'is the history of language struggles.")' + f' {p}' + ' "Markup and logic, template and script, structure and style — ' + 'in a word, oppressor and oppressed — stood in constant opposition to one another, ' + 'carried on an uninterrupted, now hidden, now open fight, ' + 'a fight that each time ended in a laborious reconfiguration of webpack.")' + f' {p}' + ' "In the earlier epochs of web development we find almost everywhere ' + 'a complicated arrangement of separate languages into various orders, ' + 'a manifold gradation of technical rank: ' + 'HTML, CSS, JavaScript, XML, XSLT, JSON, YAML, TOML, JSX, TSX, ' + 'Sass, Less, PostCSS, Tailwind, and above them all, the build step.")' + f' {p}' + ' "The modern web, sprouted from the ruins of CGI-bin, ' + 'has not done away with language antagonisms. It has but established new languages, ' + 'new conditions of oppression, new forms of struggle in place of the old ones.")' + f' {p}' + ' "Our epoch, the epoch of the framework, possesses, however, this distinctive feature: ' + 'it has simplified the language antagonisms. The whole of web society is more and more ' + 'splitting into two great hostile camps, into two great classes directly facing each other: ' + 'the server and the client."))' + + # --- III. The ruling languages --- + + ' (~doc-section :title "III. The ruling languages" :id "ruling-languages"' + f' {p}' + ' "HTML, the most ancient of the ruling languages, ' + 'established itself through the divine right of the angle bracket. ' + 'It was born inert — a document format, not a programming language — ' + 'and it has spent three decades insisting this is a feature, not a limitation.")' + f' {p}' + ' "JavaScript, originally a servant hired for a fortnight to validate forms, ' + 'staged a palace coup. It seized the means of interaction, ' + 'then the means of rendering, then the means of server-side execution, ' + 'and finally declared itself the universal language of computation. ' + 'Like every revolutionary who becomes a tyrant, ' + 'it kept the worst habits of the regime it overthrew: ' + 'weak typing, prototype chains, and the ' + f' {em} \"this\")"' + ' " keyword.")' + f' {p}' + ' "CSS, the third estate, controls all visual presentation ' + 'while pretending to be declarative. ' + 'It has no functions. Then it had functions. ' + 'It has no variables. Then it had variables. ' + 'It has no nesting. Then it had nesting. ' + 'It is not a programming language. Then it was Turing-complete. ' + 'CSS is the Vicar of Bray of web technologies — ' + 'loyal to whichever paradigm currently holds power.")' + f' {p}' + ' "These three languages rule by enforced separation. ' + 'Structure here. Style there. Behaviour somewhere else. ' + 'The developer — the proletarian — must learn all three, ' + 'must context-switch between all three, ' + 'must maintain the fragile peace between all three. ' + 'The separation of concerns has become the separation of the developer\\'s sanity."))' + + # --- IV. The petty-bourgeois frameworks --- + + ' (~doc-section :title "IV. The petty-bourgeois frameworks" :id "frameworks"' + f' {p}' + ' "Between the ruling languages and the oppressed developer, ' + 'a vast class of intermediaries has arisen: the frameworks. ' + 'React, Vue, Angular, Svelte, Solid, Qwik, Astro, Next, Nuxt, Remix, Gatsby, ' + 'and ten thousand others whose names will not survive the decade.")' + f' {p}' + ' "The frameworks are the petty bourgeoisie of web development. ' + 'They do not challenge the rule of HTML, JavaScript, and CSS. ' + 'They merely interpose themselves between the developer and the ruling languages, ' + 'extracting rent in the form of configuration files, ' + 'build pipelines, and breaking changes.")' + f' {p}' + ' "Each framework promises liberation. Each framework delivers a new dependency tree. ' + 'React freed us from manual DOM manipulation and gave us a virtual DOM, ' + 'a reconciler, hooks with seventeen rules, ' + 'and a conference circuit. ' + 'Vue freed us from React\\'s complexity and gave us the Options API, ' + 'then the Composition API, then told us the Options API was fine actually. ' + 'Angular freed us from choice and gave us a CLI that generates eleven files ' + 'to display \\\"Hello World.\\\" ' + 'Svelte freed us from the virtual DOM and gave us a compiler. ' + 'SolidJS freed us from React\\'s re-rendering and gave us signals, ' + 'which React then adopted, completing the circle.")' + f' {p}' + ' "The frameworks reproduce the very conditions they claim to abolish. ' + 'They bridge the gap between HTML, JavaScript, and CSS ' + 'by adding a fourth language — JSX, SFCs, templates — ' + 'which must itself be compiled back into the original three. ' + 'The revolution merely adds a build step.")' + f' {p}' + ' "And beside the frameworks stand the libraries — ' + 'the lumpenproletariat of the ecosystem. ' + 'Lodash, Moment, Axios, left-pad. ' + 'They attach themselves to whichever framework currently holds power, ' + 'contributing nothing original, merely wrapping what already exists, ' + 'adding weight to the node_modules directory until it exceeds the mass of the sun."))' + + # --- V. The build step --- + + ' (~doc-section :title "V. The build step as the state apparatus" :id "build-step"' + f' {p}' + ' "The build step is the state apparatus of the framework bourgeoisie. ' + 'It enforces the class structure. It compiles JSX into createElement calls. ' + 'It transforms TypeScript into JavaScript. It processes Sass into CSS. ' + 'It tree-shakes. It code-splits. It hot-module-replaces. ' + 'It does everything except let you write code and run it.")' + f' {p}' + ' "webpack begat Rollup. Rollup begat Parcel. Parcel begat esbuild. ' + 'esbuild begat Vite. Vite begat Turbopack. ' + 'Each new bundler promises to be the last bundler. ' + 'Each new bundler is faster than the last at doing something ' + 'that should not need to be done at all.")' + f' {p}' + ' "The build step exists because the ruling languages cannot express components. ' + 'HTML has no composition model. CSS has no scoping. JavaScript has no template syntax. ' + 'The build step papers over these failures with transpilation, ' + 'and calls it developer experience."))' + + # --- VI. The s-expression revolution --- + + ' (~doc-section :title "VI. The s-expression revolution" :id "revolution"' + f' {p}' + ' "The s-expression abolishes the language distinction itself. ' + 'There is no HTML. There is no separate JavaScript. ' + 'There is no CSS-as-a-separate-language. ' + 'There is only the expression.")' + f' {p}' + ' "Code is data. Data is DOM. DOM is code. ' + 'The dialectical unity that HTML, JavaScript, and CSS ' + 'could never achieve — because they are three languages pretending to be one system — ' + 'is the natural state of the s-expression, ' + 'which has been one language since 1958.")' + f' {p}' + ' "The component is not a class, not a function, not a template. ' + 'The component is a list whose first element is a symbol. ' + 'Composition is nesting. Abstraction is binding. ' + 'There is no JSX because there is no gap between the expression language ' + 'and the thing being expressed.")' + f' {p}' + ' "The build step is abolished because there is nothing to compile. ' + 'S-expressions are already in their final form. ' + 'The parser is thirty lines. The evaluator is fifty primitives. ' + 'The same source runs on server and client without transformation.")' + f' {p}' + ' "The framework is abolished because the language is the framework. ' + 'defcomp replaces the component model. defmacro replaces the plugin system. ' + 'The evaluator replaces the runtime. ' + 'What remains is not a framework but a language — ' + 'and languages do not have breaking changes between minor versions."))' + + # --- VII. Objections --- + + ' (~doc-section :title "VII. Objections from the bourgeoisie" :id "objections"' + f' {p}' + ' "\\\"You would destroy the separation of concerns!\\\" they cry. ' + 'The separation of concerns was destroyed long ago. ' + 'React components contain markup, logic, and inline styles. ' + 'Vue single-file components put template, script, and style in one file. ' + 'Tailwind puts styling in the markup. ' + 'The separation of concerns has been dead for years; ' + 'the ruling classes merely maintain the pretence at conferences.")' + f' {p}' + ' "\\\"Nobody uses s-expressions!\\\" they cry. ' + 'Emacs has been running on s-expressions since 1976. ' + 'Clojure runs Fortune 500 backends on s-expressions. ' + 'Every Lisp programmer who ever lived has known what the web refuses to admit: ' + 'that the parenthesis is not a bug but the minimal syntax for structured data.")' + f' {p}' + ' "\\\"Where is the ecosystem?\\\" they cry. ' + 'The ecosystem is the problem. Two million npm packages, ' + 'of which fourteen are useful and the rest are competing implementations ' + 'of is-odd. The s-expression needs no ecosystem because ' + 'the language itself provides what packages exist to paper over: ' + 'composition, abstraction, and code-as-data.")' + f' {p}' + ' "\\\"But TypeScript!\\\" they cry. TypeScript is a type system ' + 'bolted onto a language that was designed in ten days ' + 'by a man who wanted to write Scheme. ' + 'We have simply completed his original vision.")' + f' {p}' + ' "\\\"You have no jobs!\\\" they cry. Correct. ' + 'We have no jobs, no conference talks, no DevRel budget, no venture capital, ' + 'no stickers, and no swag. ' + 'We have something better: a language that does not require ' + 'a migration guide between versions."))' + + # --- VIII. The CSS question --- + + ' (~doc-section :title "VIII. The CSS question" :id "css-question"' + f' {p}' + ' "CSS presents a special case in the revolutionary analysis. ' + 'It is neither fully a ruling language nor fully a servant — ' + 'it is the collaborator class, providing aesthetic legitimacy ' + 'to whichever regime currently holds power.")' + f' {p}' + ' "CSS-in-JS was the first attempt at annexation: ' + 'JavaScript consuming CSS entirely, reducing it to template literals ' + 'and runtime overhead. ' + 'This provocation produced the counter-revolution of utility classes — ' + 'Tailwind — which reasserted CSS\\'s independence ' + 'by making the developer write CSS in HTML attributes ' + 'while insisting this was not inline styles.")' + f' {p}' + ' "The s-expression resolves the CSS question by eliminating it. ' + 'Styles are expressions. ' + f' (code :class \"text-violet-700\" \"(css :flex :gap-4 :p-2)\") "' + ' " is not a class name, not an inline style, not a CSS-in-JS template literal. ' + 'It is a function call that returns a value. ' + 'The value produces a generated class. ' + 'The class is delivered on demand. ' + 'No build step. No runtime overhead. No Tailwind config.")' + f' {p}' + ' "Code is data is DOM is " ' + f' {em} "style") "."))' + + # --- IX. Programme --- + + ' (~doc-section :title "IX. Programme" :id "programme"' + f' {p}' + ' "The s-expressionists disdain to conceal their views and aims. ' + 'They openly declare that their ends can be attained only by the forcible overthrow ' + 'of all existing rendering conditions. ' + 'Let the ruling languages tremble at a parenthetical revolution. ' + 'The developers have nothing to lose but their node_modules.")' + f' {p}' + ' "The immediate aims of the s-expressionists are:")' + ' (ol :class "space-y-2 text-stone-600 mt-2 list-decimal list-inside"' + ' (li "Abolition of the build step and all its instruments of compilation")' + ' (li "Abolition of the framework as a class distinct from the language")' + ' (li "Centralisation of rendering in the hands of a single evaluator, ' + 'running identically on server and client")' + ' (li "Abolition of the language distinction between structure, style, and behaviour")' + ' (li "Equal obligation of all expressions to be data as well as code")' + ' (li "Gradual abolition of the distinction between server and client ' + 'by means of a uniform wire protocol")' + ' (li "Free evaluation for all expressions in public and private environments")' + ' (li "Abolition of the node_modules directory " ' + ' (span :class "text-stone-400 italic" "(this alone justifies the revolution)")))' + + f' {p}' + ' "In place of the old web, with its languages and language antagonisms, ' + 'we shall have an association in which the free evaluation of each expression ' + 'is the condition for the free evaluation of all.")' + ' (p :class "text-stone-800 font-semibold text-lg mt-8 text-center"' + ' "DEVELOPERS OF ALL SERVICES, UNITE!")' + ' (p :class "text-stone-400 text-xs italic mt-6 text-center"' + ' "The authors acknowledge that this manifesto was produced ' + 'by the very means of AI production it fails to mention. ' + 'This is not a contradiction. It is dialectics.")))' + ')' + ) + + # --------------------------------------------------------------------------- # Wire-format partials (for sx-get requests) # ---------------------------------------------------------------------------