Skip to content

Commit

Permalink
Tentative copy (#254)
Browse files Browse the repository at this point in the history
* 📝 tentative new copy

* 📝 fixing copy typos
  • Loading branch information
Mortaro authored Mar 6, 2023
1 parent b462b6c commit b381afc
Show file tree
Hide file tree
Showing 11 changed files with 126 additions and 281,734 deletions.
62 changes: 53 additions & 9 deletions i18n/en-US/articles/what-is-nullstack.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,67 @@ title: What is Nullstack?
description: Nullstack is an isomorphic JavaScript framework that allows developers to build Full Stack applications while staying focused on the product features, and solving the user problems, rather than spending a significant amount of their time worrying about layers of abstraction and choosing which tools make them look fancy
---

Nullstack is an isomorphic JavaScript framework that allows developers to build Full Stack applications while staying focused on the product features, and solving the user problems, rather than spending a significant amount of their time worrying about layers of abstraction and choosing which tools make them look fancy.
Nullstack is a full stack web framework that allows features to be created in a single component, we call it "feature-driven" components. Nullstack's main feature is having functions that run in the server and client within the same file, it uses a compilation step to create multiple bundles.
Besides that, the framework comes with tons of small conveniences out of the box, but the cool thing is that all of them are usable in the exact same way, they are passed as arguments to every function of your components, and you don't have to learn a bunch of new concepts to be productive. As a rule of thumb, all you need to know ahead of time is that every static async function will run in the server, and every function receives an object with the framework context merged with the application context and the component context.

Nullstack can be used to build a variety of projects, such as Blockchain dapps, web applications (SSR, SPA, SSG), Google Chrome extensions, Hybrid Native applications, Electron applications, and anything else you can do with JavaScript at the same time with a single codebase.
# What is feature-driven?
It means that every component is a full feature in itself, but it is up to you to decide how to break features down. As an example, you could have a "BlogPost" component or you could have a Blog a Post a Comment, and a Like component and they are nested into each other, heck you could even have an entire e-commerce application be a top-level component imported in another application, that's the beauty of full stack components.

## Feature Driven
In the case of the Like button for instance, you would have the server functions to load the number of likes that item has, a render function to show your likes, and an event that triggers a server function to save your like, all in a single file if you want, the main reasoning for this architecture is that the project manager's tickets, the UX and the code look pretty much the same.

A Nullstack feature speaks the same language to the developer, the project manager, and the client.
*But my bootcamp teacher said I need at least 3 layers of abstraction to be a good developer, can I do that in Nullstack?*

Nullstack components are complete features. They connect the application from the backend to the frontend providing a fully functional feature in a single component.
Yes you can, Nullstack is a big foot-gun you can shoot your own foot in your favorite style, just ask for the permission of an adult first.

There're no such thing as big projects in Nullstack, only small features. A feature could be composed of other features, one feature could even be an entire application imported as a component into another application.
# Is it a react framework?
Nope, but it uses JSX. Nullstack does not use hooks, instead, it aims to keep JavaScript's natural flow, but makes it reactive. Fun fact tho, Nullstack actually started as a react framework that just aimed to add server functions to the components, but eventually, I found that sticking to that model was limiting our creativity.

This might look wrong and go against everything you've ever learned, but it works, it's faster and more flexible. Your code gets much simpler and easier to understand, people can quickly jump in your codebase and start contributing. Developers can make changes in giant projects without any cognitive overhead.
*But react has the support from all those big companies, why should we use Nullstack?*

Nullstack does not need an ecosystem, you probably won't find "nullstack-*" libraries as you can simply use vanilla JavaScript packages. We believe that JavaScript reached a maturity level that creating a piece of code that does exactly what you need is going to often take less lines and lead to less overengineering than configuring a library .
Well, you shouldn't use it just because its a new tool, use it if you want, I love using it at AE Studio tho, though we are building brain-to-computer interface software here, and we have a few opinions about just letting meta dominate everything.

Feature-driven development might not be for everyone, but Nullstack gives you enough freedom to use it however you see fit. You can still use Nullstack with layers and abstractions, we're not here to hold your hand, you're free to shoot your own foot.
# Why did you build another framework?
That wasn't the original intention, we were actually trying to build a coffee shop, but we get distracted very easily... you can learn more about the history behind Nullstack in Anny's TDC talk.

Initially, we just wanted to put the server code alongside the client code, because the projects we were working on had very similar patterns, and one of those patterns was that the clients would completely change their minds all the time, and your regular clean code kinda thing was not keeping up with the changes.

# Does it use a virtual dom or a compiler or signals?
The answer is yes. Nullstack has what I like to call a "Virtual Pipeline" it optimizes things differently in different scenarios for different environments. However that is just an implementation detail, the main thing is that it **just works** and we may change anything internal at any time. The only condition we have is that anything that works in vanilla JS should work in Nullstack, so we won't adopt any cool new trends if it limits the developer experience, or if the developer now needs to be aware of new edge cases instead of getting stuff done.

# Does it uses Classes or Functions?
It uses whatever JavaScript code you can come up with. By default it follows the same paradigm as vanilla: functions are pure, and classes hold state. I know I will lose a lot of devs after the previous sentence, but keep in mind when people say "classes are bad" they actually mean "classes are bad on the current framework I'm using" . In Nullstack it just feels very natural, give it a try.

# Is it blazingly fast?
Yes. But it is optimized for what I consider the "right type of fast", it's fast for the users. It uses a mix of architectures to optimize for different scenarios, but all of them aim to have the users have very responsive experiences, even when they are offline.

You can always benchmark things and be excited about microseconds happy, but that all ends when your user 3g is not feeling like reaching your server that day.

That being said, we love spending time micro benchmarking things and its actually pretty fast, if you sneak into our commit history you will notice we went for "what we need to create products" first then we went "optimization happy", as you should if you plan to code professionally and not just watch youtube videos.

# What can i build with it? Does it scale?
You can build anything you can build with regular JavaScript. We've built so far plenty of PWAs, blockchain applications across multiple blockchains (dApps), mobile games, capacitor applications, electron applications, chrome extensions, and even things to visualize brain data that require a lot of performance. Currently, we have a SaaS with hundreds of thousands of hits a day, and it is holding just fine on a "regular JavaScript-priced" server.

# How can i use a new framework? it wont have an ecosystem.
Remember when I mentioned we keep everything vanilla just working? that makes most JavaScript packages for browser and server compatible with Nullstack out of the box, that's a pretty huge ecosystem in my opinion. But also if you are feeling like a mad scientist, you could always just install your favorite framework on top of a Nullstack's application by rendering to an element controlled by it.

# Does it have any kind of telemetry?
No, we do not collect any data. Nullstack was not built as a framework first, it was extracted from real applications we worked on over the years, so the features it has are based on what we needed as opposite of what the data would point would cause better thumbnails.

*But how will you guys know what features we want then?*

You can always tell us on discord or create an issue on GitHub, we will be happy to talk about it!

# Does Nullstack have any social media?
Of the 6 main contributors of Nullstack 6 of them are autistic, including the person writing this wall of text... so you mostly lost us at the "social" part. We did try tho, and we created a YouYube Channel, a Twitter, and an Instagram, but 4 of us also have ADHD so we ended up procrastinating and not posting on it, oopsie. We are pretty active on discord though, that's the place we are forced to log in anyway to coordinate our raids.

# What is Nulla-Chan?
Nulla-Chan is the avatar of Nullstack, it belongs to a category of avatars called a "Waifu". If you don't know what a waifu is, that probably means that you have your life on the right track. Fun fact, the waifu character was created by the author's IRL waifu.

# What was the hardest part creating a framework?
Definitively it was deciding if we should spell it "full stack", "fullstack", or "full-stack". Seriously please tell us on discord which one to pick.

# How can i get started?
Just go to your favorite terminal and type "npx create-nullstack-app app-name", and if you are feeling fancy you can also pass the flags --typescript and --tailwind.

## Next step

Expand Down
3 changes: 0 additions & 3 deletions i18n/en-US/components/Header.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ links:
href: "/contributors"
- title: "Waifu"
href: "/waifu"
- title: "Announcement"
href: "/blog/release-candidate-announcement"
badge: "new"
menu:
title: "Toggle Menu"
action:
Expand Down
30 changes: 14 additions & 16 deletions i18n/en-US/components/Home.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ hero:
heading: "Feature-Driven"
subHeading: "Full Stack JavaScript Components"
descriptions:
- "Write the backend and frontend of a feature in a single
- Your new favorite web framework.
- "Write the backend and frontend of a feature in a single isomorphic
component and let the framework decide where the code should run."
- "Nullstack provides you all the tools you need to stay focused on the product."
callToAction: "npx create-nullstack-app"
actionLink: '/getting-started'
actionCallback: 'Command copied, paste it on the terminal'
trinity:
heading: "The Holy Trinity"
subHeading: "of progressive web apps development"
heading: "Great for the Dev. Great for the User"
subHeading: "from fast SSR to offline PWA out of the box"
roles:
- title: "Optimized for the first render"
image: "/illustrations/nulla-tanker.webp"
Expand All @@ -33,35 +33,33 @@ trinity:
generated microservice API, deserialize the response, update the
aplication state, and rerender the page out of the box"
features:
- title: "Stop wasting time glueing code together"
- title: "No more glue code"
snippet: "GlueCode"
image: "/illustrations/nulla-glue.webp"
text:
"A full stack lifecycle combined with a feature-driven mindset allows
you to write clean and reusable code without the need to create APIs
manually."
- title: "Become a programmer less dependent on gimmicks"
"You write features for products. The compiler extracts your front end code and replaces all static async functions with calls to microservices"
- title: "Easy to read and write"
snippet: "Vanilla"
image: "/illustrations/nulla-scrolls.webp"
inverted: true
text:
"Your components are just POJOs.
Take advantage of the existing ecosystem while you write JavaScript as it is supposed to be,
and see the result reflected in the dom."
Take advantage of the existing ecosystem while you write JavaScript or TypeScript as it is supposed to be,
and see the result reflected in the DOM."
- title: "You already know Nullstack"
snippet: "Modern"
image: "/illustrations/nulla-map.webp"
text:
"Routes are simple attributes you can assign to any tag, and links are just 'a' tags.
"JSX tags follow the HTML standard, routes are simple attributes you can assign to any tag, and links are just anchor tags.
You will find out that Nullstack is just a modern version of your current stack."
- title: "All the tools you need speak the same language"
- title: "DX with Batteries Included"
snippet: "Batteries"
image: "/illustrations/nulla-tools.webp"
inverted: true
text:
"Most chores are very repetitive.
Save your energy for the real challenges using the shortcuts we created,
like object events and two-way bindings."
"Nullstack has a lot of out of the box shortcuts that
were extracted out of repeating patterns in real projects
instead of architecture books. Give it a try and you will get it!"
playlist:
heading: "Learn with our "
slang: "Dweebs"
Expand Down
21 changes: 11 additions & 10 deletions i18n/en-US/snippets/Batteries.njs
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
class Batteries extends Nullstack {

// variables can be bound to the dom
name = 'Nulla-Chan';
isWaifu = true;
render() {
// preparing an object event
const isWaifu = !this.isWaifu;
happy = false;

action() {
console.log('event already prevented')
}

// events are prevented by default
render() {
return (
<form>
<form onsubmit={this.action}>
{/* two way bindings */}
<input bind={this.name} />
<button onclick={{isWaifu}}>
Toggle Waifu
{/* object events */}
<button onclick={{ happy: true }}>
Hug {this.name}
</button>
</form>
)
Expand Down
6 changes: 3 additions & 3 deletions i18n/en-US/snippets/Modern.njs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ class Modern extends Nullstack {
<p> Hi i'm {params.name} </p>
)
}

// routes can have dynamic segments
render() {
return (
<>
<div class="not-class-name">
<Waifu route="/waifus/:name" />
<a href="/waifus/Nulla">
NullaChan
</a>
</>
</div>
)
}

Expand Down
16 changes: 6 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,13 @@
"author": "",
"license": "ISC",
"devDependencies": {
"concurrently": "^7.2.0",
"nullstack": "~0.17.2",
"tailwindcss": "^3.0.0"
"nullstack": "~0.17.0",
"tailwindcss": "^3.0.0",
"postcss-loader": "^7.0.1"
},
"scripts": {
"start:nullstack": "npx nullstack start",
"start:tailwind": "npx tailwindcss -o ./tailwind.css --watch",
"start": "concurrently npm:start:*",
"build:nullstack": "npx nullstack build --mode=ssg --output=docs",
"build:tailwind": "npx tailwindcss -o ./tailwind.css",
"build": "npm run build:tailwind && npm run build:nullstack",
"start": "npx nullstack start",
"build": "npx nullstack build --mode=ssg --output=docs",
"reinstall": "rm -rf .development .production package-lock.json node_modules && npm install"
},
"dependencies": {
Expand All @@ -31,4 +27,4 @@
"remarkable-meta": "^1.0.1",
"yaml": "^1.10.0"
}
}
}
2 changes: 1 addition & 1 deletion src/Application.njs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class Application extends Nullstack {
<body data-theme={mode} class={mode}>
<div class="dark:bg-gray-900 dark:text-white">
<Header locale={locale} />
<HiringBanner />
{/* <HiringBanner /> */}

<Home route="/" locale="en-US" persistent />
<Home route="/pt-br" locale="pt-BR" persistent />
Expand Down
27 changes: 16 additions & 11 deletions src/Home.njs
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,20 @@ class Home extends Translatable {
return (
<section class="max-w-screen-xl mx-auto px-4 flex justify-between items-center flex-wrap sm:pt-12">
<div class="sm:w-5/12 grid gap-8 mt-12 sm:mt-0">
<p class="text-xl sm:text-3xl text-center sm:text-left">
{this.i18n.hero.descriptions[0]}
</p>
<h1 class="w-full">
<span class={`text-pink-600 ${page.locale === 'pt-BR' ? 'text-xl sm:text-3xl' : 'text-3xl sm:text-6xl'} font-light block sm:mb-3 text-center sm:text-left`}>
<span class={`text-pink-600 ${page.locale === 'pt-BR' ? 'text-xl sm:text-3xl' : 'text-5xl sm:text-6xl'} font-light block sm:mb-3 text-center sm:text-left`}>
{this.i18n.hero.heading}
</span>
<span class={`text-pink-600 dark:text-pink-500 ${page.locale !== 'pt-BR' ? 'text-xl sm:text-3xl' : 'text-3xl sm:text-5xl'} font-light block sm:mb-3 text-center sm:text-left`}>
{this.i18n.hero.subHeading}
</span>
</h1>
<>
{this.i18n.hero.descriptions.map(description =>
<p class="text-xl sm:text-2xl text-center sm:text-left">
{description}
</p>
)}
</>
<p class="text-xl sm:text-2xl text-center sm:text-left">
{this.i18n.hero.descriptions[1]}
</p>
<div>
<button
class="bg-pink-600 text-white px-6 py-4 border border-pink-600 hover:bg-transparent hover:text-pink-600 inline-block w-full sm:w-auto"
Expand All @@ -51,7 +50,7 @@ class Home extends Translatable {
<div class="bg-center bg-0 hover:bg-100 bg-repeat-y mt-6" style="background-image: url(/stars.webp); transition: background-size 3s;">
<img src="/illustrations/nulla-hero.webp" alt="Nulla-Chan" class="max-w-full" width="627" height="765" loading="lazy" />
</div>
</section>
</section >
)
}

Expand All @@ -73,7 +72,7 @@ class Home extends Translatable {
return (
<section class="max-w-screen-xl mx-auto px-4 flex justify-between items-center flex-wrap py-12 sm:py-36">
<h2 class="w-full text-center mb-8 sm:mb-24">
<span class="w-full text-pink-600 text-4xl sm:text-6xl font-light block sm:mb-3">{this.i18n.trinity.heading}</span>
<span class="w-full text-pink-600 text-2xl sm:text-5xl font-light block sm:mb-3">{this.i18n.trinity.heading}</span>
<span class="sm:text-xl block">{this.i18n.trinity.subHeading}</span>
</h2>
{this.i18n.trinity.roles.map((role) => <Role {...role} />)}
Expand Down Expand Up @@ -144,9 +143,15 @@ class Home extends Translatable {
<div>
<Hero />
<Separator />
{this.i18n.features.slice(0, 1).map(feature =>
<>
<Feature {...feature} />
<Separator />
</>
)}
<Trinity />
<Separator />
{this.i18n.features.map(feature =>
{this.i18n.features.slice(1).map(feature =>
<>
<Feature {...feature} />
<Separator />
Expand Down
Loading

0 comments on commit b381afc

Please sign in to comment.