-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #247 from AnnyFigueira/feature/blog
✨ blog engine and rc announcement
- Loading branch information
Showing
10 changed files
with
350 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
title: "Nullstack Blog" | ||
description: "Check the latest, coolest stuff going on with Nullstack" | ||
heading: "Nullstack Blog" | ||
tagline: "A collection of blog posts about Nullstack." | ||
contribute: "We accept guest posts! You can write it up in markdown and open a PR to our <a href='https://github.com/nullstack/nullstack.github.io/pulls'>github repo</a>." | ||
posts: | ||
- title: "0.17.2 Release Candidate Announcement" | ||
href: "/blog/release-candidate-announcement" | ||
description: "We're proud to announce the first release candidate of Nullstack" | ||
date: "Jan. 2023" | ||
author: | ||
name: Anny Figueira | ||
handle: AnnyFigueira |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,30 @@ | ||
home: | ||
home: | ||
title: "Nullstack" | ||
href: "/" | ||
links: | ||
- title: "What is Nullstack?" | ||
href: "/what-is-nullstack" | ||
- title: "Documentation" | ||
href: "/getting-started" | ||
- title: "Blog" | ||
href: "/blog" | ||
- title: "Contributors" | ||
href: "/contributors" | ||
- title: "Waifu" | ||
href: "/waifu" | ||
- title: "Announcement" | ||
href: "/blog/release-candidate-announcement" | ||
badge: "new" | ||
menu: | ||
title: "Toggle Menu" | ||
action: | ||
title: "Get Started" | ||
href: "/getting-started" | ||
search: | ||
title: "Search [ctrl + k]" | ||
language: | ||
language: | ||
title: "Português" | ||
href: "/pt-br" | ||
mode: | ||
dark: "Night Mode" | ||
light: "Day Mode" | ||
light: "Day Mode" |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--- | ||
title: Page Not Found | ||
description: Sorry, this is not the page you are looking for. | ||
status: 404 | ||
--- | ||
|
||
Perhaps you want to learn more about [Nullstack](/what-is-nullstack)? | ||
|
||
Or do you want to contribute to our [blog](/blog)? |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
--- | ||
title: "0.17.2 Release Candidate Announcement" | ||
description: "We're proud to announce the first release candidate of Nullstack" | ||
date: "Jan. 2023" | ||
author: | ||
name: Anny Figueira | ||
handle: AnnyFigueira | ||
--- | ||
We're proud to announce the first release candidate of Nullstack, after ~4 years of development and over 3 years being used in real-life, production projects. | ||
|
||
Every time we thought about officially releasing a 1.0 version, we got more feature requests from our small community and postponed the release to implement them. | ||
We believe we’ve reached a pretty solid, complete state in terms of both our API and the core functionalities. | ||
We finally reached the point where, for a few weeks, our Github repo has no open issues and we are running out of excuses not to launch it. | ||
|
||
For those new here: Nullstack is a full stack Javascript framework that aims to facilitate the process of quickly building MVPs with quality and scalability by allowing developers to plug-and-play isomorphic features into the code base seamlessly. We aim to be product-focused and feature-driven, although the framework is flexible enough to allow pretty much any design pattern you would like to use. | ||
|
||
Nullstack is just vanilla Javascript that reacts to your changes both on the client and server side. It allows you to build pretty much anything: from PWAs with ssr to hybrid mobile applications and even Google Chrome extensions backed by microservices within the same codebase. | ||
|
||
One cool thing about Nullstack is that we value **not** having Nullstack-specific notation, which means it supports any default HTML tag, such as an `<a>` for links. The framework handles it just fine, without going out of SPA mode just because of it. We also support the normal HTML attributes such as `class` and `onclick`, and we support any vanilla JS library that exists, relying on the already robust JavaScript and Node ecosystem, so that a developer wouldn't need to learn anything new to be able to start using it. | ||
|
||
You can learn more about our very comprehensive set of features in our [documentation](https://nullstack.app/getting-started). | ||
|
||
Apart from personal and freelancing projects, we've also been using Nullstack for the past year at [AE Studio](https://ae.studio/work) on both [skunkworks projects with thousands of users](https://instillvideo.com/) and [client projects](https://www.areyouonpoint.co/), to a point where we even made it part of our [onboarding process](https://ae.studio/jobs/4484720004/nullstack-developer). We're pretty adamant about how much it not only allows us to speed up the development process, but also the quality of life for developers and a more adaptable product to our clients. | ||
|
||
So, without further ado, we invite everyone to give it a try: all you need to do is run `npx create-nullstack-app@latest project-name` and start having fun! 🎉 | ||
|
||
If you have any questions, feel free to join our [Discord server](https://discord.com/invite/eDZfKz264v) where you can interact with our community 🥰 | ||
|
||
Found a bug or have a feature request? Feel free to [open an issue](https://github.com/nullstack/nullstack/issues) at our Github. | ||
|
||
We will interact over the feedback as fast as we can and release 1.0 pretty soon. | ||
|
||
You can help us by [leaving a star on our Github repo](https://github.com/nullstack/nullstack/stargazers)🌟. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import Translatable from "./Translatable"; | ||
|
||
class Blog extends Translatable { | ||
prepare({ page }) { | ||
page.priority = 0.3; | ||
} | ||
|
||
renderProject({ title, repository }) { | ||
return ( | ||
<a | ||
href={repository} | ||
target={repository.indexOf("http") === 0 && "_blank"} | ||
rel="noopener" | ||
class="block text-pink-600 dark:text-pink-500 border-t border-gray-100 dark:border-gray-800 py-2 mt-2" | ||
> | ||
{title} | ||
</a> | ||
); | ||
} | ||
|
||
renderPost({ title, href, description, date, author }) { | ||
return ( | ||
<a href={href} class="w-full block mb-8"> | ||
<h2 class="w-full text-xl sm:text-4xl font-light mb-2 text-pink-600"> | ||
{title} | ||
</h2> | ||
<p class="text-base" title={description}> | ||
{description} | ||
</p> | ||
<div class="opacity-80"> | ||
<span class="mr-2">By {author.name}</span> | ||
<span class="mr-2">|</span> | ||
<span>{date}</span> | ||
</div> | ||
</a> | ||
); | ||
} | ||
|
||
render() { | ||
if (!this.i18n) return false; | ||
return ( | ||
<section class="max-w-screen-lg mx-auto px-4 flex justify-between items-center flex-wrap py-12 sm:py-24"> | ||
<h1 class="w-full text-pink-600 text-4xl sm:text-6xl font-light block sm:mb-3"> | ||
{this.i18n.heading} | ||
</h1> | ||
<p class="text-2xl sm:text-4xl font-light block mb-3"> | ||
{" "} | ||
{this.i18n.tagline} | ||
</p> | ||
<p | ||
class="w-full prose dark:prose-dark max-w-none text-xl" | ||
html={this.i18n.contribute} | ||
/> | ||
<div class="w-full mt-8"> | ||
{this.i18n.posts?.map((post) => ( | ||
<Post {...post} /> | ||
))} | ||
</div> | ||
</section> | ||
); | ||
} | ||
} | ||
|
||
export default Blog; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import { readFileSync, existsSync } from "fs"; | ||
import Translatable from "./Translatable"; | ||
import "./Article.scss"; | ||
import prismjs from "prismjs"; | ||
import { Remarkable } from "remarkable"; | ||
import meta from "remarkable-meta"; | ||
|
||
class Post extends Translatable { | ||
html = ""; | ||
|
||
static async getPostByKey({ locale, key }) { | ||
await import("prismjs/components/prism-jsx.min"); | ||
let path = `i18n/${locale}/posts/${key}.md`; | ||
if (!existsSync(path)) { | ||
path = `i18n/${locale}/posts/404.md`; | ||
} | ||
const text = readFileSync(path, "utf-8"); | ||
const md = new Remarkable({ | ||
highlight: (code) => | ||
Prism.highlight(code, prismjs.languages.jsx, "javascript"), | ||
}); | ||
md.use(meta); | ||
md.use((md) => { | ||
const originalRender = md.renderer.rules.link_open; | ||
md.renderer.rules.link_open = function () { | ||
let result = originalRender.apply(null, arguments); | ||
const regexp = /href="([^"]*)"/; | ||
const href = regexp.exec(result)[1]; | ||
if (!href.startsWith("/")) { | ||
result = result.replace(">", ' target="_blank" rel="noopener">'); | ||
} | ||
return result; | ||
}; | ||
}); | ||
md.use((md) => { | ||
md.renderer.rules.heading_open = function (tokens, i) { | ||
const { content } = tokens[i + 1]; | ||
const { hLevel } = tokens[i]; | ||
const id = content | ||
.toLowerCase() | ||
.split(/[^a-z]/) | ||
.join("-"); | ||
return `<h${hLevel} id="${id}"><a href="#${id}">`; | ||
}; | ||
md.renderer.rules.heading_close = function (tokens, i) { | ||
const { hLevel } = tokens[i]; | ||
return `</a></h${hLevel}>`; | ||
}; | ||
}); | ||
return { | ||
html: md.render(text), | ||
...md.meta, | ||
}; | ||
} | ||
|
||
async initiate({ page, locale, params }) { | ||
super.initiate({ page, locale }); | ||
const post = await this.getPostByKey({ key: params.slug, locale }); | ||
Object.assign(this, post); | ||
} | ||
|
||
launch({ project, page }) { | ||
page.title = `${this.title} - ${project.name}`; | ||
page.description = this.description; | ||
if (this.status) { | ||
page.status = 404; | ||
} | ||
} | ||
|
||
render() { | ||
if (!this.html) return false; | ||
return ( | ||
<section class="max-w-screen-md mx-auto px-4 flex flex-wrap sm:flex-nowrap py-12 sm:py-24"> | ||
<article class="w-full pb-24"> | ||
<h1 class="text-pink-600 text-4xl font-light block">{this.title}</h1> | ||
<div class="opacity-80 mb-8"> | ||
<span class="mr-2"> | ||
By{" "} | ||
<a | ||
href={`https://github.com/${this.author.handle}`} | ||
rel="noopener" | ||
target="_blank" | ||
> | ||
{this.author.name} | ||
</a> | ||
</span> | ||
<span class="mr-2">|</span> | ||
<span>{this.date}</span> | ||
</div> | ||
|
||
<div | ||
html={this.html} | ||
class="prose dark:prose-dark max-w-none text-lg" | ||
/> | ||
</article> | ||
</section> | ||
); | ||
} | ||
} | ||
|
||
export default Post; |
Oops, something went wrong.