Git Product home page Git Product logo

nextjs-woocommerce-restapi's Introduction

๐ŸŽจ Next.js WooCommerce REST API

Project Status: Active. Stars Forks Contributors Follow

  • React WooCommerce Theme, using Decoupled Architecture in Next.js
  • Backend in WordPress
  • Front end in React.
  • Data is Fetched through REST API.

Features

  • Home Page
  • Single Product Page With Gallery Carousel.
  • Cart Page
  • Checkout Page with Stripe Payment Gateway Integration.
  • REST API endpoints.
  • Header and Footer in Next.js fetching from WordPress Menu items.
  • WordPress Widgets displayed on Next.js frontend.
  • Site title, tagline, copyright text, social links sourced from WordPress.
  • Yoast SEO support
  • Next.js Image component, that has image optimization at request time
  • Incremental Static (Re)generation and automatic creation of New Static product pages without having to re-build next.js the application.
  • Gutenberg styles support
  • Blog Page with Pagination
  • Single Post
  • Pages
  • 404 Page
  • Display Comments
  • Post a Comment ( using a Comment Form )
  • Post Preview ( Coming Soon )
  • Product Pagination ( Coming Soon )
  • Load More Products ( Coming Soon )
  • Authentication with JWT and Http Only Cookie implementation. ( Coming Soon )
  • Login feature for WP Post Preview in Next.js ( Coming Soon )

Setup

First clone/fork the repo and cd into it.

git clone https://github.com/imranhsayed/nextjs-woocommerce-restapi.git
cd nextjs-woocommerce-restapi
npm ci
npm run dev

Add Headless features for WordPress

  • Install and Activate following WordPress Plugins:

Configuration ๐Ÿ”ง

  1. (Required) Create a .env file taking reference from .env-example and update your WordPressSite URL and Frontend next.js URL.
  • NEXT_PUBLIC_WORDPRESS_URL=https://example.com
  • NEXT_PUBLIC_SITE_URL=http://localhost.com ( This will be your frontend Next.js URL)
  1. Add your WC_CONSUMER_KEY and WC_CONSUMER_SECRET to the .env by following WooCommerce > Settings > Advanced > REST API

  2. In your WordPress Dashboard, Go to Settings > General > Site Address (URL) ( Set this to Frontend URL e.g. http://localhost:3000 during development )

  3. Create the Header and Footer Menus In WordPress Dashboard and set them to HCMS Header menu and HCMS Footer Menu respectively.

Useful Links

Versioning ๐Ÿ“‘

I use Git for versioning.

Author ๐Ÿ‘ค

License ๐Ÿ“ƒ

This project is licensed under the MIT License - see the LICENSE.md file for details

nextjs-woocommerce-restapi's People

Contributors

imranhsayed 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nextjs-woocommerce-restapi's Issues

[Feature Request]

Dear Imran,

I would like to see the following features in your woocommerce restapi example:

  • - Wishlist
  • - Profile Page (With order history and such)
  • - User Reviews
  • - Product Tags
  • - SEO
  • - Global Search
  • - Filters
  • - Shipping Methods
  • - Conditional Shipping Methods
  • - Product Properties
  • - Product Cost of Goods
  • - Product Pricing Tables
  • - Blog Page
  • - 404 Page
  • - Gutenberg Style support.
  • - Single Posts
  • - Display Comments
  • - Post a Comment ( using Comment Form )
  • - Pages
  • - Custom Post Types
  • - Custom Fields
  • - Login/Logout Form
  • - Contact Forms
  • - Email
  • - Woocommerce Analytics
  • - On Sale Badges
  • - Custom Badges
  • - User, Customer, Product, Category, Tag, Order Exports and Imports
  • - Meta Tags
  • - Coupons
  • - Marketing
  • - (Optional) Order Packaging for determining which boxes to get when ordering (shipping methods)

Let me know if I or anybody else can help in implementing these things within a NextJS project.
Currently I'm learning NextJS, and I'm not really sure if I'm the person that can help set this up with you as well.

I think a lot of people would like to see a (complete) woocommerce theme in NextJS, rather then a theme that only supports the basic woocommerce functions.

But that is probably a long road to go down.

Error: Request failed with status code 404

I'm having this error while trying acces to the site , this is my general config
e9fe7ae0fa4ca0defa0d83c8039f2445, if in the site adress url is the top link there is no problem, the problem is when i am trying to acces from localhost:3000

No items added to cart

After clicking "Add to Cart", the Bag (upper right) is not updated, and the cart is empty.

Steps I did to check if anything is working or not:

1 inspect page

  • go to Network > two items/ show up
  • first items/ (POST) show the correct Headers, Preview, and Response
  • second items/ (GET) do not show anything in Preview and Response (only [])
  • go to Application tab > my next-cart is 'null'

Screen Shot 2022-04-28 at 5 18 22 PM

Screen Shot 2022-04-28 at 5 19 39 PM

2 But in Postman, everything works. (POST, GET, DELETE)

3 Double checked .env file and WooCommerce keys; I even "reinstalled" everything from the latest repo commit, npm install, etc... still the same result

404 on detail pages

besides the homepage I am getting 404 on all blog, product, category, etc. Any idea what can be the cause. Products, Post are showing on the frontpage and the URL also look correct. I am running on a VM. I have no idea where to look.

Getting Server Error Error: connect ECONNREFUSED 127.0.0.1:80 after cloning and running the app.

Error: connect ECONNREFUSED 127.0.0.1:80
    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1146:16) {
  errno: -61,
  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: '127.0.0.1',
  port: 80,
  config: {
    url: 'undefined/api/get-products',
    method: 'get',
    headers: {
      Accept: 'application/json, text/plain, */*',
      'User-Agent': 'axios/0.21.1'
    },
    transformRequest: [ [Function: transformRequest] ],
    transformResponse: [ [Function: transformResponse] ],
    timeout: 0,
    adapter: [Function: httpAdapter],
    xsrfCookieName: 'XSRF-TOKEN',
    xsrfHeaderName: 'X-XSRF-TOKEN',
    maxContentLength: -1,
    maxBodyLength: -1,
    validateStatus: [Function: validateStatus],
    data: undefined
  },
  request: <ref *1> Writable {
    _writableState: WritableState {
      objectMode: false,
      highWaterMark: 16384,
      finalCalled: false,
      needDrain: false,
      ending: false,
      ended: false,
      finished: false,
      destroyed: false,
      decodeStrings: true,
      defaultEncoding: 'utf8',
      length: 0,
      writing: false,
      corked: 0,
      sync: true,
      bufferProcessing: false,
      onwrite: [Function: bound onwrite],
      writecb: null,
      writelen: 0,
      afterWriteTickInfo: null,
      buffered: [],
      bufferedIndex: 0,
      allBuffers: true,
      allNoop: true,
      pendingcb: 0,
      constructed: true,
      prefinished: false,
      errorEmitted: false,
      emitClose: true,
      autoDestroy: true,
      errored: null,
      closed: false,
      closeEmitted: false,
      [Symbol(kOnFinished)]: []
    },
    _events: [Object: null prototype] {
      response: [Function: handleResponse],
      error: [Function: handleRequestError]
    },
    _eventsCount: 2,
    _maxListeners: undefined,
    _options: {
      maxRedirects: 21,
      maxBodyLength: 10485760,
      protocol: 'http:',
      path: 'undefined/api/get-products',
      method: 'GET',
      headers: [Object],
      agent: undefined,
      agents: [Object],
      auth: undefined,
      hostname: null,
      port: null,
      nativeProtocols: [Object],
      pathname: 'undefined/api/get-products'
    },
    _ended: true,
    _ending: true,
    _redirectCount: 0,
    _redirects: [],
    _requestBodyLength: 0,
    _requestBodyBuffers: [],
    _onNativeResponse: [Function (anonymous)],
    _currentRequest: ClientRequest {
      _events: [Object: null prototype],
      _eventsCount: 7,
      _maxListeners: undefined,
      outputData: [],
      outputSize: 0,
      writable: true,
      destroyed: false,
      _last: true,
      chunkedEncoding: false,
      shouldKeepAlive: false,
      _defaultKeepAlive: true,
      useChunkedEncodingByDefault: false,
      sendDate: false,
      _removedConnection: false,
      _removedContLen: false,
      _removedTE: false,
      _contentLength: 0,
      _hasBody: true,
      _trailer: '',
      finished: true,
      _headerSent: true,
      _closed: false,
      socket: [Socket],
      _header: 'GET undefined/api/get-products HTTP/1.1\r\n' +
        'Accept: application/json, text/plain, */*\r\n' +
        'User-Agent: axios/0.21.1\r\n' +
        'Host: localhost\r\n' +
        'Connection: close\r\n' +
        '\r\n',
      _keepAliveTimeout: 0,
      _onPendingData: [Function: nop],
      agent: [Agent],
      socketPath: undefined,
      method: 'GET',
      maxHeaderSize: undefined,
      insecureHTTPParser: undefined,
      path: 'undefined/api/get-products',
      _ended: false,
      res: null,
      aborted: false,
      timeoutCb: null,
      upgradeOrConnect: false,
      parser: null,
      maxHeadersCount: null,
      reusedSocket: false,
      host: 'localhost',
      protocol: 'http:',
      _redirectable: [Circular *1],
      [Symbol(kCapture)]: false,
      [Symbol(kNeedDrain)]: false,
      [Symbol(corked)]: 0,
      [Symbol(kOutHeaders)]: [Object: null prototype]
    },
    _currentUrl: 'http:undefined/api/get-products',
    [Symbol(kCapture)]: false
  },
  response: undefined,
  isAxiosError: true,
  toJSON: [Function: toJSON]
}
wait  - compiling...
event - compiled successfully
Error: connect ECONNREFUSED 127.0.0.1:80
    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1146:16) {
  errno: -61,
  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: '127.0.0.1',
  port: 80,
  config: {
    url: 'undefined/api/get-products',
    method: 'get',
    headers: {
      Accept: 'application/json, text/plain, */*',
      'User-Agent': 'axios/0.21.1'
    },
    transformRequest: [ [Function: transformRequest] ],
    transformResponse: [ [Function: transformResponse] ],
    timeout: 0,
    adapter: [Function: httpAdapter],
    xsrfCookieName: 'XSRF-TOKEN',
    xsrfHeaderName: 'X-XSRF-TOKEN',
    maxContentLength: -1,
    maxBodyLength: -1,
    validateStatus: [Function: validateStatus],
    data: undefined
  },
  request: <ref *1> Writable {
    _writableState: WritableState {
      objectMode: false,
      highWaterMark: 16384,
      finalCalled: false,
      needDrain: false,
      ending: false,
      ended: false,
      finished: false,
      destroyed: false,
      decodeStrings: true,
      defaultEncoding: 'utf8',
      length: 0,
      writing: false,
      corked: 0,
      sync: true,
      bufferProcessing: false,
      onwrite: [Function: bound onwrite],
      writecb: null,
      writelen: 0,
      afterWriteTickInfo: null,
      buffered: [],
      bufferedIndex: 0,
      allBuffers: true,
      allNoop: true,
      pendingcb: 0,
      constructed: true,
      prefinished: false,
      errorEmitted: false,
      emitClose: true,
      autoDestroy: true,
      errored: null,
      closed: false,
      closeEmitted: false,
      [Symbol(kOnFinished)]: []
    },
    _events: [Object: null prototype] {
      response: [Function: handleResponse],
      error: [Function: handleRequestError]
    },
    _eventsCount: 2,
    _maxListeners: undefined,
    _options: {
      maxRedirects: 21,
      maxBodyLength: 10485760,
      protocol: 'http:',
      path: 'undefined/api/get-products',
      method: 'GET',
      headers: [Object],
      agent: undefined,
      agents: [Object],
      auth: undefined,
      hostname: null,
      port: null,
      nativeProtocols: [Object],
      pathname: 'undefined/api/get-products'
    },
    _ended: true,
    _ending: true,
    _redirectCount: 0,
    _redirects: [],
    _requestBodyLength: 0,
    _requestBodyBuffers: [],
    _onNativeResponse: [Function (anonymous)],
    _currentRequest: ClientRequest {
      _events: [Object: null prototype],
      _eventsCount: 7,
      _maxListeners: undefined,
      outputData: [],
      outputSize: 0,
      writable: true,
      destroyed: false,
      _last: true,
      chunkedEncoding: false,
      shouldKeepAlive: false,
      _defaultKeepAlive: true,
      useChunkedEncodingByDefault: false,
      sendDate: false,
      _removedConnection: false,
      _removedContLen: false,
      _removedTE: false,
      _contentLength: 0,
      _hasBody: true,
      _trailer: '',
      finished: true,
      _headerSent: true,
      _closed: false,
      socket: [Socket],
      _header: 'GET undefined/api/get-products HTTP/1.1\r\n' +
        'Accept: application/json, text/plain, */*\r\n' +
        'User-Agent: axios/0.21.1\r\n' +
        'Host: localhost\r\n' +
        'Connection: close\r\n' +
        '\r\n',
      _keepAliveTimeout: 0,
      _onPendingData: [Function: nop],
      agent: [Agent],
      socketPath: undefined,
      method: 'GET',
      maxHeaderSize: undefined,
      insecureHTTPParser: undefined,
      path: 'undefined/api/get-products',
      _ended: false,
      res: null,
      aborted: false,
      timeoutCb: null,
      upgradeOrConnect: false,
      parser: null,
      maxHeadersCount: null,
      reusedSocket: false,
      host: 'localhost',
      protocol: 'http:',
      _redirectable: [Circular *1],
      [Symbol(kCapture)]: false,
      [Symbol(kNeedDrain)]: false,
      [Symbol(corked)]: 0,
      [Symbol(kOutHeaders)]: [Object: null prototype]
    },
    _currentUrl: 'http:undefined/api/get-products',
    [Symbol(kCapture)]: false
  },
  response: undefined,
  isAxiosError: true,
  toJSON: [Function: toJSON]
}

Error: connect ECONNREFUSED 162.xxx.xxx.xx:3000

wp: publicly hosted backend

nextjs: locally hosted at localhost:3000

image

when I go to refresh my NextJS homepage i get this error
image

when I make a request in my browser directly to the backend. The URL changes to a different port on request

https://mobibooth.com/store/wp-json/wp/v2/pages
-- changes to --
https://mobibooth.com:3000/store/wp-json/wp/v2/pages

Help needed - NextJS in Shared Hosting

Imran,

Thanks a ton for creating this wonderful course. I have been a regular follower of most of your courses.

I am working with a client who has a full on WooCommerce site which is very slow and caching has improved performance a little bit but still is not great. I am thinking about suggesting NextJS+WooCommerce site to them, but have some questions before I can do that.

  1. First requirement would be, they already have a shared hosting cPanel account that has been paid for long term, they don't want move away from that account.
  2. They also don't want us to create a another CDN account, too many accounts for them to maintain it seems, so even a free Vercel/Netlify account is out of question.
  3. Only option I have now is to host both NextJS frontend (in root) and WooCommerce backend (in subdomain or subfoler) in the same account, thinking of NextJS export option.
  4. Do you think NextJS export would work for WooCommerce driven site? Or do you think NextJS regular build will work in shared hosting?
  5. I have a GatsbyJS WordPress static site hosted in the same fashion, but that does not have WooCommerce though, just plain WP.

Thanks a lot in advance for your input in this regard.

B.

Error: unable to verify the first certificate

Error: unable to verify the first certificate
at TLSSocket.onConnectSecure (node:_tls_wrap:1600:34)
at TLSSocket.emit (node:events:517:28)
at TLSSocket._finishInit (node:_tls_wrap:1017:8)
at ssl.onhandshakedone (node:_tls_wrap:803:12) {
code: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE',

error: "Request failed with status code 401"

When using the NextJS Url in the general settings i get a 401 error if i use the wordpress site settings i get products back, unfortunately the permalinks are referencing the wordpress site. Is there a way to pass CORS headers in the get request?

Unable to create an order: woocommerce_rest_cannot_create

When we attempt to create the order, we are presented with the following response from the server.

{ "code": "woocommerce_rest_cannot_create", "message": "Sorry, you are not allowed to create resources.", "data": { "status": 401 } }

Next JS Ecommerce?

Did you check the Next JS Commerce? I think if we built on that Project then it's gonna be cool and need to contribute it to that project.

I can help with any related coding and styling.

Axios.Post not adding to cart

linking my followed along project here
my github repo/ utils/cart.js

spots that need help are labeled with // TODO HELP -- *

when running the Woocommerce endpoints in POST MAN, I get desired result of adding to cart, and getting updated cart when running those enpoints in axios in the app I still get null return . I'll link the code snippet below

I've tried

  • trying browser in incognito
  • using a different browser
import { getSession, storeSession } from './cart-session';
import { getApiCartConfig } from './cart-api';
import axios from 'axios';
import { WC_CART } from 'utils/endpoints';
import { isEmpty, isArray } from 'lodash';

/**
 * Add To Cart Request Handler.
 *
 * @param {int} productId Product Id.
 * @param {int} qty Product Quantity.
 * @param {Function} setCart Sets The New Cart Value
 * @param {Function} setIsAddedToCart Sets A Boolean Value If Product Is Added To Cart.
 * @param {Function} setLoading Sets A Boolean Value For Loading State.
 */
export const addToCart = ( productId, qty = 1, setCart, setIsAddedToCart, setLoading ) => {
	const storedSession = getSession();
	const addOrViewCartConfig = getApiCartConfig();
	
	setLoading(true);

  // TODO HELP -- using enpoints in POST MAN works as it should, but not here
	axios.post( WC_CART, {
			product_id: productId,
			quantity: qty,
		},
		addOrViewCartConfig,
	)
		.then( ( res ) => {

      console.log('data post: ', res?.data);
      
      if ( isEmpty( storedSession ) ) { storeSession( res?.headers?.[ 'x-wc-session' ] ) }

			setIsAddedToCart(true)
			setLoading(false)
			viewCart( setCart ) 
		} )
		.catch( err => {
			console.warn( 'err', err )
		} );
};

/**
 * View Cart Request Handler
 *
 * @param {Function} setCart Set Cart Function.
 * @param {Function} setProcessing Set Processing Function.
 */
export const viewCart = ( setCart, setProcessing = () => {} ) => {
	
	const addOrViewCartConfig = getApiCartConfig();
	
	axios.get( WC_CART, addOrViewCartConfig )
		.then( ( res ) => {

      // TODO HELP -- This is returning 'null'
      console.log('viewCart', res?.data);

			const formattedCartData = getFormattedCartData( res?.data ?? [] )
			setCart( formattedCartData );
			setProcessing(false);
		} )
		.catch( err => {
			console.log( 'err', err );
			setProcessing(false);
		} );
};

/**
 * Update Cart Request Handler
 */
export const updateCart = ( cartKey, qty = 1, setCart, setUpdatingProduct ) => {
	
	const addOrViewCartConfig = getApiCartConfig();
	
	setUpdatingProduct(true);
	
	axios.put( `${WC_CART}${cartKey}`, {
		quantity: qty,
	}, addOrViewCartConfig )
		.then( ( res ) => {
			viewCart( setCart, setUpdatingProduct );
		} )
		.catch( err => {
			console.log( 'err', err );
			setUpdatingProduct(false);
		} );
};

/**
 * Delete a cart item Request handler.
 *
 * Deletes all products in the cart of a
 * specific product id ( by its cart key )
 * In a cart session, each product maintains
 * its data( qty etc ) with a specific cart key
 *
 * @param {String} cartKey Cart Key.
 * @param {Function} setCart SetCart Function.
 * @param {Function} setRemovingProduct Set Removing Product Function.
 */
export const deleteCartItem = ( cartKey, setCart, setRemovingProduct ) => {
	
	const addOrViewCartConfig = getApiCartConfig();
	
	setRemovingProduct(true);
	
	axios.delete( `${WC_CART}${cartKey}`, addOrViewCartConfig )
		.then( ( res ) => {
			viewCart( setCart, setRemovingProduct );
		} )
		.catch( err => {
			console.log( 'err', err );
			setRemovingProduct(false);
		} );
};

/**
 * Clear Cart Request Handler
 *
 * @param {Function} setCart Set Cart
 * @param {Function} setClearCartProcessing Set Clear Cart Processing.
 */
export const clearCart = async ( setCart, setClearCartProcessing ) => {
	
	setClearCartProcessing(true);
	
	const addOrViewCartConfig = getApiCartConfig();
	
	try {
		const response = await axios.delete( WC_CART, addOrViewCartConfig );
		viewCart( setCart, setClearCartProcessing );
	} catch ( err ) {
		console.log( 'err', err );
		setClearCartProcessing(false);
	}
};

/**
 * Get Formatted Cart Data.
 *
 * @param cartData
 * @return {null|{cartTotal: {totalQty: number, totalPrice: number}, cartItems: ({length}|*|*[])}}
 */
const getFormattedCartData = ( cartData ) => {
	if ( ! cartData.length ) {
		return null;
	}
	const cartTotal = calculateCartQtyAndPrice( cartData || [] );
	return {
		cartItems: cartData || [],
		...cartTotal,
	};
};

/**
 * Calculate Cart Qty And Price.
 *
 * @param cartItems
 * @return {{totalQty: number, totalPrice: number}}
 */
const calculateCartQtyAndPrice = ( cartItems ) => {
	const qtyAndPrice = {
		totalQty: 0,
		totalPrice: 0,
	}
	
	if ( !isArray(cartItems) || !cartItems?.length ) {
		return qtyAndPrice;
	}
	
	cartItems.forEach( (item, index) => {
		qtyAndPrice.totalQty += item?.quantity ?? 0;
		qtyAndPrice.totalPrice += item?.line_total ?? 0;
	} )
	
	return qtyAndPrice;
}

Images: Error: Invalid src prop

My case is a bit unique since I'm hosing my backend WP on Bluehost. All images get a hostname of i0.wp.com instead of my Domain Name

image

I've checked my next.config.js and reloaded my nextJS server after editing

const path = require('path');
const allowedImageWordPressDomain = new URL( process.env.NEXT_PUBLIC_WP_SITE_URL ).hostname;

module.exports = {
	trailingSlash: false,
	webpackDevMiddleware: config => {
		config.watchOptions = {
			poll: 1000,
			aggregateTimeout: 300
		}
		
		return config
	},
	sassOptions: {
		includePaths: [path.join(__dirname, 'styles')]
	},
	/**
	 * We specify which domains are allowed to be optimized.
	 * This is needed to ensure that external urls can't be abused.
	 * @see https://nextjs.org/docs/basic-features/image-optimization#domains
	 */
	images: {
		domains: [ 
      "i0.wp.com",
      allowedImageWordPressDomain, 
      "via.placeholder.com" 
    ],
	},
}

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  swcMinify: true,
}

module.exports = nextConfig

yet still it's giving me the error. It's like the custom next.config.js isn't being loaded?

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.