Git Product home page Git Product logo

downwrite's Introduction

Downwrite

Node CI E2E Testing

About 🤔🦄🎉

A place to write. ✍️

So the idea here was simple build a simple markdown writing application. Markdown is a huge deal and all the cool tools kept getting shut down and naively,I thought, how hard can this really be? 🤔📝📦

So I've had poorly designed iterations of this thing for every year, on the year as one of these services got shut down. When Canvas shut down this last year, I started to get a little more serious about this idea. 💡 ⚡🔭

During planning out some of my quarterly goals at my last job I decided to go a little more full-stack with Node and start to really work through the process of building a microservice. Since I'm never really one to learning languages and frameworks in the abstract, I decided to take up Downwrite as an excuse to build those microservices. 📡💸🌎

Why Markdown 🧐🤨📋

Markdown is probably the most efficient and universal tool for conveying syntax, semantics and structure across platforms. ⬇️

Originally coined by John Gruber (Daring Fireball) it was originally conceived as a text to HTML and is the staple of static site generators, OSS as well as a fair amount of comment sections, notetaking applications or any documentation tool. 🛠

These shortcuts are almost as ubiquitous as cmd + b for bold or cmd + i for italics. ⌨️

Bottomline: markdown is data. It is a method for describing semantics of data and is data itself.

Features ✨🔥🚀

This is meant to be a simple writing application with some key features:

  • Write wherever you are in markdown
  • Share what you've written if you want
  • Upload a markdown file from your machine
  • Export to a static markdown file for your blog, etc.

Setup 📲⏳⚙️

This project uses Node (v12.18.x), TypeScript and pnpm.

brew cask install pnpm
pnpm install

Personally use fnm to manage my node versions.

fnm install
fnm use

Environment

To get started create an .env file in the root of your project with the following

SECRET_KEY="SECRET SECRETS ARE NO FUN"
CURRENT_DB_ADDRESS="127.0.0.1:27017/downwrite"

Client ⚡️🦊

Logos for Related Projects

Setup

Run in your terminal from the root of the project.

pnpm dev

Open http://localhost:3000 in your browser.

UI 📝

This is the client-side of the application, it uses Next.js and is a pretty stock implementation of how Next handles routing to different views. 👨‍💻🤜🦑🤯

Downwrite needs to server side rendered to make sharing an entry as easy as possible. Next.js' data-fetching API makes it the perfect candidate. So when the page calls getServerSideProps() it fetches the data directly from the database (DB creditentials aren't exposed to the client build at all because of the bundling features inside Next 😁) and for the initial render it has data available instead of a skeleton screen. 🤖☠️💀

For the Editor this project uses Draft.js and Draft.js Plugins. Markdown syntax is used inline and autogenerates the related rich text _hello_ becomes "hello" as you type.💻⌨️🔏

For styles I just used the built-in CSS support in Next.js

Serverless Functions 🌎✨

To update the data, this project calls endpoints at /api/.... to enable this we're using Next'js API Routes. These are serverless functions so we don't need to keep a server or database connectioin running all the time, with serverless functions you're essentially calling the API on-demand.

This project also depends on MongoDB 🍍 for data persistence, you should see this gist on how to setup MongoDB on your machine.

To authenticate we're using JWT to call the basic CRUD functions. Basically this is using a stateless auth model, more about that here. 🔐

Related Documentation 📚

Integration Testing 🌈🦁🐛

Logos for Related Projects

pnpm test

Info 📝🧪

Short hand: page is just a representation of whatever the headless browser, Puppeteer has rendered at that given moment.

Using Puppeteer I write assertions like this:

describe("Feature", () => {
	it("does this thing", async () => {
		await page.waitForSelector("#selector");
		await page.click("#selector");
		await page.waitForSelector("#other-selector");
	});
});

This approach accomplishes two things:

  • Ensures if an await statement errors or catch() the block will cause a failure
  • Makes the test sequential and simpler to write

Related Documentation 📚

Workflow 👷‍♀️🚧

Working on this project it uses GitHub actions to run the tests and deploys using vercel for easy rollback and immutable deployments.

License ⚖️💣🛡⚔️

MIT License

Copyright (c) 2022 Charlie Peters

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

downwrite's People

Contributors

charliewilco avatar dependabot-preview[bot] avatar dependabot[bot] avatar kodiakhq[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

downwrite's Issues

Night Mode

Dark theme for editor view

save in local storage

Feature: Local Drafts

If user goes offline, the user should save the draft to local storage.

should be able to detect draft on mount, show an alert to apply or discard the draft.

local draft

Add service to Confirm User

Users need to be confirmed in the system before too long.
A service should send an email confirm and not impede user

Header with token

there should be a generic header shouldn't need to reset it every time.

new Header()

More Error States

User needs appropriate context during an error.

  • Offline
  • Entry Couldn't Save

Tags

Need to solidify tags in

  • Design
  • Model definition
  • Implementing in Handlebars template
  • Saving to Firebase
  • Filtering by tags

Word Count

if text is selected, there should be a word count of the selection.

UX

A collection of style things that need to be addressed

  • Night Mode
  • Autosaving Notification
  • Horizontal overflow on smaller screen sizes
  • Alerter for login and logout
  • Preview CSS
  • Fix navigation to fill the full height
  • Animation to dismiss modal

Inline Comments

  • Design concept
  • Define Model
  • Actions [delete, resolve, respond]
  • Invitation other users to post? Own issue?

Move State

Move global state to use unstated

  • Auth (token, user_id, username)
  • Posts (just a top level list

Fix Registration Privacy, T&C

  • Need a legal route that has terms and conditions & basic privacy stuff
  • Fix registration with new Auth API
  • Confirm that you've read or wish to ignore the Legal shit (probably a checkbox)
  • Don't not submit unless confirmation is true

Decode Token

token should send username, user_id and client should decode it.

Editor should auto save

Editor should autosave every 3 seconds, debounce and then alert the user that the post has be saved.

Authentication

Basic authentication using firebase and torii

simple login email & password

Unauthed Header

When a post is previewed and the user isn't authenticate a header should appear with

  • Logo, on the left
  • Signup + Signin, on the right

Upload markdown file

<Main /> Component should be a drag and drop interface to drop in documents from desktop and parse them in the service and create an instance of the <NewEditor /> with the content and title.

Edit Component (Umbrella)

This component is begging for a refactor.

  • debouncing the autosave
  • fetching initial data
  • fetching new entry
  • current lifecycles best practice

SSR

Downwrite needs to be rendered on the server, especially the preview pages and the default list

Here are a few good options

  • After.js
  • Next.js
  • StaticRouter + Express + custom middleware

Mobile Optimization

UMBRELLA ISSUE:

need to refine editor and sidebar for mobile sizes

  • Editor Tasks (Settings)
  • Editor Tasks (Action)
  • Navigation

Dashboard

  • Modal should use portals
  • Layout Toggle should be it's own component that manages its own state (a function as child)
  • Modal needs new UI design
  • Modal needs a DeleteModal component to take those props
  • Flow Errors

Code Blocks

Code blocks in Editor

should be able to type in an Instance of Prism.

Confirm Delete

Should annoyingly confirm you want to delete the post.

Fail to Fetch

if i try and hit my endpoint and i get a 401 with an expired token the main list shouldn't return as the empty state, there should be a meaningful error.

  • /
  • /new
  • /:id/edit

Separate UI Library

  • UI components should live up one level in their own package.
  • Default CSS should live in its own package.

Preview

  • Refine Theme for Preview view
  • Deep link to preview
  • Return error if post isn't public or not owned by current logged in user
  • Logged out user should see login and register in header.

Share Button

Sharing button should be available on every card, should copy share link if it's public

onClick on small screen navigation

currently passing around top level closing function to dismiss the navigation. there should be a onSuccess or onClick in the navigation that dismisses, like pass location as prop and if the location updates in componentDidUpdate close the navigation.

bug:

small screens, tapping All Entries doesn't close the nav (because it's not re-routing).

Error State

Replace HOC of withUIFlashMessage with an ErrorContainer in unstated

Code Blocks

these are going to be important.

in both rendering markdown and in Editor also night mode

Publishing

Should be able to publish to Wordpress and Medium

Modal

for Helpers, export, tags, etc

Private Post

  • Defining private attr on post model
  • Flesh out toggle for private in UI
  • Showing private post on card

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.